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
10 changes: 7 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,23 +12,25 @@ defaults:

jobs:
cabal:
name: ${{ matrix.os }} / GHC ${{ matrix.ghc }} / ${{ matrix.python-version }}
name: ${{ matrix.os }} / GHC ${{ matrix.ghc }} / ${{ matrix.python-version }} / ${{ matrix.cabal-flags }}
runs-on: ${{ matrix.os }}
strategy:
matrix:
include:
- { cabal: "3.14", os: ubuntu-latest, ghc: "9.2.8", python-version: "3.12" }
- { cabal: "3.14", os: ubuntu-latest, ghc: "9.4.8", python-version: "3.12" }
- { cabal: "3.14", os: ubuntu-latest, ghc: "9.6.6", python-version: "3.12" }
- { cabal: "3.14", os: ubuntu-latest, ghc: "9.8.4", python-version: "3.12" }
- { cabal: "3.14", os: ubuntu-latest, ghc: "9.10.2", python-version: "3.12" }
- { cabal: "3.14", os: ubuntu-latest, ghc: "9.12.2", python-version: "3.12" }
- { cabal: "3.14", os: ubuntu-latest, ghc: "9.14.1", python-version: "3.12" }
# Scan over supported python versions
- { cabal: "3.14", os: ubuntu-latest, ghc: "9.10.2", python-version: "3.10" }
- { cabal: "3.14", os: ubuntu-latest, ghc: "9.10.2", python-version: "3.11" }
- { cabal: "3.14", os: ubuntu-latest, ghc: "9.10.2", python-version: "3.12" }
- { cabal: "3.14", os: ubuntu-latest, ghc: "9.10.2", python-version: "3.13" }
- { cabal: "3.14", os: ubuntu-latest, ghc: "9.10.2", python-version: "3.14" }
# Build with python3-config instead of pkg-config
- { cabal: "3.14", os: ubuntu-latest, ghc: "9.10.2", python-version: "3.12", cabal-flags: "-fpython3-config" }
fail-fast: false
steps:
# ----------------
Expand Down Expand Up @@ -58,6 +60,8 @@ jobs:
python -V
pkg-config python3-embed --cflags
pkg-config python3-embed --libs
python3-config --cflags
python3-config --libs
# ----------------
- name: Make sdist
run: |
Expand All @@ -77,7 +81,7 @@ jobs:
run: |
if [ "${{ matrix.skip-test }}" == "" ]; then FLAG_TEST=--enable-test; fi
if [ "${{ matrix.skip-bench }}" == "" ]; then FLAG_BENCH=--enable-benchmarks; fi
cabal configure $FLAG_TEST $FLAG_BENCH
cabal configure $FLAG_TEST $FLAG_BENCH ${{ matrix.cabal-flags }}
cabal build all --write-ghc-environment-files=always
# ----------------
- name: Test
Expand Down
79 changes: 79 additions & 0 deletions Setup.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
{-# LANGUAGE CPP #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE ImportQualifiedPost #-}
{-# LANGUAGE OverloadedRecordDot #-}
{-# LANGUAGE OverloadedStrings #-}
import Data.Either

import Distribution.Simple
import Distribution.Simple.Setup
import Distribution.Simple.LocalBuildInfo
import Distribution.PackageDescription
import Distribution.Types.BuildInfo
import Distribution.Types.PackageDescription
import Distribution.Types.CondTree
import Distribution.Types.ForeignLib
import Distribution.Types.UnqualComponentName
import Distribution.Utils.Path
import Distribution.Compat.Lens
import Distribution.Types.BuildInfo.Lens qualified as L

import Data.List (intercalate, nub)
import System.Process


main :: IO ()
main = defaultMainWithHooks $ simpleUserHooks
{ confHook = patchedConfHook }



patchedConfHook
:: (GenericPackageDescription, HookedBuildInfo)
-> ConfigFlags
-> IO LocalBuildInfo
patchedConfHook (gpd, hbi) flags
| Just True <- lookupFlagAssignment ("python3-config") $ configConfigurationsFlags flags
= do cflags_raw <- readProcess "python3-config" ["--cflags"] ""
ldflags_raw <- readProcess "python3-config" ["--embed", "--ldflags"] ""
-- Split flags
let (inc_dirs,cflags) = partitionEithers
[ case flag of
'-':'I':path -> Left path
_ -> Right flag
| flag <- tokenizeArguments cflags_raw
]
(ldflags, (libs, lib_dirs)) = fmap partitionEithers $ partitionEithers
[ case flag of
'-':'l':path -> Right (Left path)
'-':'L':path -> Right (Right path)
_ -> Left flag
| flag <- tokenizeArguments ldflags_raw
]
let tweakLib lib = case lib.libName of
LMainLibName -> lib & L.ccOptions %~ (++ cflags)
& L.includeDirs %~ (++ (toSymb <$> inc_dirs))
& L.ldOptions %~ (++ ldflags)
& L.extraLibs %~ (++ libs)
& L.extraLibDirs %~ (++ (toSymb <$> lib_dirs))
_ -> lib
confHook simpleUserHooks
( gpd { condLibrary = (fmap . fmap) tweakLib (condLibrary gpd) }
, hbi
) flags
| otherwise = do
confHook simpleUserHooks (gpd, hbi) flags

tokenizeArguments :: String -> [String]
tokenizeArguments = words

----------------------------------------------------------------
-- Compatibility

#if MIN_VERSION_Cabal_syntax(3,14,0)
toSymb :: String -> SymbolicPathX 'AllowAbsolute from to
toSymb = makeSymbolicPath
#else
toSymb :: String -> String
toSymb = id
#endif
70 changes: 40 additions & 30 deletions inline-python.cabal
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Cabal-Version: 3.0
Build-Type: Simple

Build-Type: Custom
Name: inline-python
Version: 0.2.1.0
Synopsis: Python interpreter embedded into haskell.
Expand All @@ -24,12 +24,24 @@ extra-source-files:
py/bound-vars.py

Tested-With:
GHC == 9.2.8
GHC == 9.4.8
GHC == 9.6.7
GHC == 9.8.4
GHC == 9.10.2
GHC == 9.12.2
GHC == 9.14.1


custom-setup
setup-depends: base >=4.15 && <5
, Cabal >=3.0 && <4
, Cabal-syntax >=3.6 && <4
, process >=1.6 && <2

flag python3-config
Description: Use python3-config instead of pkg-config
Manual: True
Default: False

source-repository head
type: git
Expand All @@ -55,7 +67,7 @@ common language
----------------------------------------------------------------
Library
import: language
Build-Depends: base >=4.14 && <5
Build-Depends: base >=4.15 && <5
, primitive >=0.6.2
, vector >=0.13.2
, containers >=0.5
Expand All @@ -72,7 +84,9 @@ Library
include-dirs: include
c-sources: cbits/python.c
cc-options: -g -Wall
pkgconfig-depends: python3-embed >= 3.10
-- Else we use python3-config in Setup.hs
if !flag(python3-config)
pkgconfig-depends: python3-embed >= 3.10
--
Exposed-modules:
Python.Inline
Expand All @@ -89,11 +103,10 @@ Library
Python.Internal.Types
Python.Internal.Util

----------------------------------------------------------------
library test
import: language
common tests
Default-Extensions:
QuasiQuotes
hs-source-dirs: test
build-depends: base
, inline-python
, tasty >=1.2
Expand All @@ -106,38 +119,35 @@ library test
, vector
, bytestring
, text
hs-source-dirs: test
Exposed-modules:
TST.Run
TST.ToPy
TST.FromPy
TST.Callbacks
TST.Roundtrip
TST.Util


-- Running tests using several threads does very good job at finding threading
-- bugs. Especially deadlocks
test-suite inline-python-tests
import: language
import: language, tests
type: exitcode-stdio-1.0
Ghc-options: -threaded -rtsopts -with-rtsopts=-N2
hs-source-dirs: test/exe
main-is: main.hs
build-depends: base
, inline-python
, inline-python:test
, tasty
main-is: exe/main.hs
Other-modules:
TST.Run
TST.ToPy
TST.FromPy
TST.Callbacks
TST.Roundtrip
TST.Util

test-suite inline-python-tests1
import: language
import: language, tests
type: exitcode-stdio-1.0
Ghc-options: -rtsopts
hs-source-dirs: test/exe
main-is: main.hs
build-depends: base
, inline-python
, inline-python:test
, tasty
main-is: exe/main.hs
Other-modules:
TST.Run
TST.ToPy
TST.FromPy
TST.Callbacks
TST.Roundtrip
TST.Util

benchmark pysmall
import: language
Expand Down
19 changes: 18 additions & 1 deletion src/Python/Inline.hs
Original file line number Diff line number Diff line change
Expand Up @@ -105,14 +105,31 @@ import Python.Internal.Eval
--
-- Here's list of common problems and solutions and workarounds.
--
--
-- 1. __@inline-python@ cannot find libraries__
--
-- @inline-python@ may look for modules in wrong place. Set
-- environment variables @PYTHONHOME@ or @PYTHONPATH@ to point it
-- right way.
--
--
-- 2. __Linker error in GHCi__
-- 2. __Picking correct python interpreter__
--
-- Python's version @inline-python@ uses is determined by @libpython3@
-- it's linked with. This is decided when package is build. Normally
-- @pkg-config@ is used and this means using whatever distribution is
-- shipping. It's also possible to use @python3-config@ program by
-- specifying manual cabal flag @-fpython3-config@.
--
-- If it's desired that @inline-python@ should use python installed by
-- conda\/uv\/etc @inline-python@ should be built in environment where
-- desired python version is active and use @-fpython3-config@ flag.
-- This could be done by adding following to cabal.project:
--
-- > constraints: inline-python -fpython3-config
--
--
-- 3. __Linker error in GHCi__
--
-- Attempting to import library using C extensions from ghci may
-- result in linker failing to find symbols from @libpython@ like
Expand Down
2 changes: 1 addition & 1 deletion src/Python/Internal/Eval.hs
Original file line number Diff line number Diff line change
Expand Up @@ -518,7 +518,7 @@ runPyInMain py
pure ( atomically (releaseLock tid_main)
, evalInOtherThread tid_main eval_lock
)
-- If we513 can grab lock and main thread taken lock we're
-- If we can grab lock and main thread taken lock we're
-- already executing on main thread. We can simply execute code
Locked t ts
| t /= tid
Expand Down
Loading