Bibliothèque package

La bibliothèque package implémente le système de modules du langage : la fonction globale require, ainsi que la configuration des chemins de recherche et des « searchers » (les stratégies successives essayées pour localiser un module). Elle est chargée automatiquement par OpenLibs().

local json = require("json")       -- charge (ou récupère depuis le cache) le module 'json'
print(package.path)                -- chemin de recherche des modules script (.yes)

Vue d'ensemble

Fonction / champ Description
require(modname) Charge (ou récupère depuis le cache) le module modname
package.searchpath(name, path [, sep [, rep]]) Cherche name dans un gabarit de chemins path
package.path Gabarit de chemins pour les modules script (.yes)
package.dotnetpath Gabarit de chemins pour les modules Dotnet compilés (.dll)
package.searchers Table des fonctions « searcher », essayées dans l'ordre par require
package.preload Table nom -> fonction de chargement, court-circuite la recherche par chemin
package.loaded Table nom -> valeur retournée par le module, le cache de require
package.config Chaîne multi-lignes décrivant les conventions de chemins de la plateforme
package.currentroot, package.userpath, package.userroot, package.globalroot Racines d'installation prêtes à l'emploi (voir plus bas)
package.loadlib(libname, funcname) Non implémentée — lève toujours une erreur

require(modname)

Charge le module modname et retourne sa valeur. Un module n'est chargé qu'une seule fois : les appels suivants avec le même nom retournent la valeur déjà mise en cache dans package.loaded, sans réexécuter le module.

require retourne en réalité deux valeurs : la valeur du module, et une donnée de chargement secondaire (typiquement le nom du fichier trouvé) — dans l'usage courant, seule la première valeur est utilisée :

local json = require("json")

Si aucun searcher ne trouve modname, require lève une erreur script listant, pour chaque searcher ayant échoué, le chemin qu'il a tenté :

local ok, err = pcall(require, "inexistant")
if not ok then print(err) end

Si un module est trouvé mais que son code lève une erreur pendant le chargement, require propage cette erreur (préfixée du nom du fichier concerné).

Recherche de modules

require essaie, dans l'ordre, chaque fonction de package.searchers jusqu'à ce que l'une d'elles trouve un chargeur pour modname :

  1. preload — cherche modname comme clé de package.preload. Utile pour enregistrer un module déjà en mémoire (par exemple défini par l'hôte .NET) sans passer par le système de fichiers.
  2. script — cherche un fichier .yes en substituant modname dans chaque gabarit de package.path (? remplacé par le nom, . du nom remplacé par /), et charge le premier fichier trouvé.
  3. dotnet — cherche un fichier .dll en substituant modname dans package.dotnetpath, charge l'assembly (Assembly.LoadFrom) et y recherche un type public, non abstrait, dérivant de BaseScriptModule dont le nom de module résolu (attribut [Module] ou nom du type) correspond à modname.

package.path / package.dotnetpath

Gabarits de recherche, chaînes de la forme "gabarit1;gabarit2;..." où chaque gabarit contient un ? remplacé par le nom du module recherché (avec ses . convertis en / pour package.path).

Valeur par défaut construite à partir de plusieurs racines (dossier de l'exécutable, dossier courant, dossier utilisateur, dossier partagé), avec deux formes par racine pour package.path (?.yes et ?/init.yes, pour permettre un module en un seul fichier ou en dossier avec point d'entrée) :

print(package.path)
--> !/yes/?.yes;!/yes/?/init.yes;!/modules/?.yes;...;./?.yes;./?/init.yes;...

Peut être surchargé via les variables d'environnement YSCRIPT_PATH/YSCRIPT_DOTNET_PATH (ou leur variante suffixée par la version à deux composants, ex. YSCRIPT_PATH2.0, prioritaire) — voir aussi package.config pour les caractères de gabarit exacts (séparateur de chemin, marque ?, etc. — peuvent varier selon la plateforme hôte).

package.searchpath(name, path [, sep [, rep]])

Cherche name dans le gabarit de chemins path (même syntaxe que package.path), en remplaçant au préalable dans name chaque occurrence de sep (par défaut ".") par rep (par défaut "/"). Retourne le chemin trouvé, ou nil plus un message listant les chemins essayés si aucun fichier n'existe à aucun des emplacements :

local path, err = package.searchpath("mon.module", package.path)

package.preload

Table associant un nom de module à une fonction de chargement (function(modname, ...) ... end). Le searcher « preload » la consulte en premier : y déposer une entrée permet à require(nom) de retourner un module déjà construit en mémoire, sans passer par le système de fichiers ni par un searcher de fichier.

package.loaded

Table associant chaque nom de module déjà chargé à la valeur retournée par son chargeur — le cache que require consulte et alimente. Modifier directement package.loaded[nom] permet d'injecter ou de retirer un module du cache sans repasser par require.

Racines d'installation

package.currentroot, package.userpath, package.userroot et package.globalroot exposent, déjà construites, les racines de chemins utilisées pour dériver package.path/package.dotnetpath (dossier modules à côté de l'exécutable, dossier utilisateur brut, et ses sous-dossiers versionnés utilisateur/partagé). Pratiques pour un script qui doit lui-même localiser où installer ou lire des fichiers annexes, sans avoir à reconstruire ces chemins depuis package.path (qui est un gabarit de recherche, pas une liste de dossiers).

package.loadlib(libname, funcname)

Non implémentée dans cette version : tout appel lève une erreur .NET (NotImplementedException).