-- Copyright (C) 2009 John Millikin -- -- This program is free software: you can redistribute it and/or modify -- it under the terms of the GNU General Public License as published by -- the Free Software Foundation, either version 3 of the License, or -- any later version. -- -- This program is distributed in the hope that it will be useful, -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- GNU General Public License for more details. -- -- You should have received a copy of the GNU General Public License -- along with this program. If not, see . -- {-# LANGUAGE ForeignFunctionInterface #-} module CPython.Types.Module ( Module , moduleType , new , getDictionary , getName , getFilename , addObject , addIntegerConstant , addTextConstant , importModule , reload ) where import Prelude hiding (toInteger) import Data.Text (Text) import CPython.Internal hiding (new) import CPython.Types.Integer (toInteger) import CPython.Types.Unicode (toUnicode) #include newtype Module = Module (ForeignPtr Module) instance Object Module where toObject (Module x) = SomeObject x fromForeignPtr = Module instance Concrete Module where concreteType _ = moduleType {# fun pure hscpython_PyModule_Type as moduleType {} -> `Type' peekStaticObject* #} -- | Return a new module object with the @__name__@ attribute set. Only the -- module’s @__doc__@ and @__name__@ attributes are filled in; the -- caller is responsible for providing a @__file__@ attribute. -- {# fun PyModule_New as new { withText* `Text' } -> `Module' stealObject* #} -- | Return the dictionary object that implements a module’s namespace; -- this object is the same as the @__dict__@ attribute of the module. This -- computation never fails. It is recommended extensions use other -- computations rather than directly manipulate a module’s @__dict__@. -- {# fun PyModule_GetDict as getDictionary { withObject* `Module' } -> `Dictionary' peekObject* #} -- | Returns a module’s @__name__@ value. If the module does not -- provide one, or if it is not a string, throws @SystemError@. -- getName :: Module -> IO Text getName py = withObject py $ \py' -> do raw <- {# call PyModule_GetName as ^ #} py' exceptionIf $ raw == nullPtr peekText raw -- | Returns the name of the file from which a module was loaded using the -- module’s @__file__@ attribute. If this is not defined, or if it is -- not a string, throws @SystemError@. -- getFilename :: Module -> IO Text getFilename py = withObject py $ \py' -> do raw <- {# call PyModule_GetFilename as ^ #} py' exceptionIf $ raw == nullPtr peekText raw -- | Add an object to a module with the given name. This is a convenience -- computation which can be used from the module’s initialization -- computation. -- addObject :: Object value => Module -> Text -> value -> IO () addObject py name val = withObject py $ \py' -> withText name $ \name' -> withObject val $ \val' -> incref val' >> {# call PyModule_AddObject as ^ #} py' name' val' >>= checkStatusCode -- | Add an integer constant to a module. This convenience computation can be -- used from the module’s initialization computation. -- addIntegerConstant :: Module -> Text -> Integer -> IO () addIntegerConstant m name value = toInteger value >>= addObject m name -- | Add a string constant to a module. This convenience computation can be -- used from the module’s initialization computation. -- addTextConstant :: Module -> Text -> Text -> IO () addTextConstant m name value = toUnicode value >>= addObject m name -- | This is a higher-level interface that calls the current “import -- hook” (with an explicit level of @0@, meaning absolute import). It -- invokes the @__import__()@ computation from the @__builtins__@ of the -- current globals. This means that the import is done using whatever import -- hooks are installed in the current environment. -- -- This computation always uses absolute imports. -- importModule :: Text -> IO Module importModule name = do pyName <- toUnicode name withObject pyName $ \namePtr -> {# call PyImport_Import as ^ #} namePtr >>= stealObject -- | Reload a module. If an error occurs, an exception is thrown and the old -- module still exists. -- {# fun PyImport_ReloadModule as reload { withObject* `Module' } -> `Module' stealObject* #}