Le module pypkgs.py de buildez.sys inclue des primitives permettant de tester un paquetage donné pour récolter les informations liés à son installation. Des méthodes basées sur importlib, pip, conda ou mamba, sont utilisables. Chaque approche apporte des données dont une partie peut être différente, par exemple seules les méthodes conda et mamba nous permettent d’accéder au build d’un paquetage. Importlib est une bibliothèque de Python et s’utilise directement, mais pour utiliser pip, conda, mamba, il faut mettre en place un appel externe via un sous-processus, avec éventuellement un échange de données en Json. Une approche simple, mais qui doit être précise en termes de programmation. Dans cette note, seules les fonctions de pypkgs à destination d’un paquetage donné (unique) seront décrites, une autre note abordant les primitives liées à des listes de paquetages.
1. Prérequis
Pour que le module fonctionne, il faut instancier un dictionnaire qui sera utilisé par toutes les fonctions, de manière à partager le recueil d’informations. Il faut également mettre en place une fonction de score, qui va augmenter la valeur d’un score au fur et à mesure de l’ajout d’informations.
Initialisation du dictionnaire commun
Chaque méthode (importlib, pip, conda …) va mettre à jour les champs du dictionnaire pdict en fonction des informations qu’elle nous amène (pour un paquetage donné). Le dictionnaire est initialisé par la fonction pypkgs_init_pdict :
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
def pypkgs_init_pdict(pname=''): ''' This is a dictionnary used to store metadata relative to a given package. *** 1.10/150725/Fred ''' pdict = { 'name':pname, # Package name. 'ver':'', # Package version. 'loc':'', # Package Path. 'files':[], # Package files. 'err':'', # Set of errors in process. 'installer':'', # Package installer. 'channel':'', # Package channel. 'score':0, # Package resolution score. 'summary':'', # Package summary. 'pythonver':'', # Required version of Python. 'req':[], # Required packages. 'reqby':[], # Required by packages. 'build':'' # Package build } return pdict |
Toutes les méthodes nous renverront le nom du paquetage, mais importlib n’a pas toujours accès à la version, pip n’a pas accès au build … nous allons utiliser les différentes fonctions (pypkgs_init_pdict), pypkgs_importlib, pypkgs_pkg_pip, pypkgs_pkg_conda_json, pypkgs_pkg_conda_json … comme une fusée à plusieurs étages, chaque méthode complétant les champs de pdict. L’avantage c’est d’avoir quelque chose de robuste, mais l’inconvénient c’est que plus nous utiliserons d’étages, plus le processus prendra du temps.
La fonction de score
Elle sert à renseigner le champ pdict[score] en utilisant un tableau de bits, avec un bit par méthode. Si le résultat de la méthode est satisfaisant (nous avons récolté des données) le bit correspondant passe de 0 à 1.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
def pypkgs_scoring(pdict, what='', verb=0): """ The subroutine is used to set the value of pdict['score'] using a bit scheme. A table of 8 bits is used and each value is set to 1, according to what. Five bits are used in the order : ['importlib', 'meta', 'files', 'pip', 'mamba', 'conda']. If the resolution is done using a given process (i.e. 'pip'), the pypkgs_scoring subroutine is called with the corresponding (what='pip') value of what argument, and the corresponding bit is updated. The bits are converted to a decimal score value (0..255) and stored in pdict['score']. *** 1.01/150725/Fred """ # convert score and set corresponding bit binary_str = format(pdict['score'], '08b') bits = [int(b) for b in binary_str] if (what == 'importlib'): bits[0] = 1 if (what == 'meta'): bits[1] = 1 if (what == 'files'): bits[2] = 1 if (what == 'pip'): bits[3] = 1 if (what == 'mamba'): bits[4] = 1 if (what == 'conda'): bits[5] = 1 # convert bit to decimal value and update score binary_str = ''.join(str(b) for b in bits) pdict['score'] = int(binary_str, 2) # done and return if (verb > 2): print("updated score to %d" % (pdict['score'])) return pdict |
Nous notons que les bits meta et files ne correspondent pas vraiment à une méthode (cf. pip). Ces éléments sont des options de importlib, on peut activer cette méthode à plusieurs niveaux de précision.
Actuellement les 6 premiers bits sont utilisés, ce qui laisse un peu de marge. Une fois que la table est mise à jour, une valeur numérique (entier) est calculée (0 à 255). la fonction pypkgs_scoring est complétée par une fonction pypkgs_scoring_explain qui renvoie la valeur du score en affichant les contributions de chaque méthode.