IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Python Discussion :

Import avec extension "py3" [Python 3.X]


Sujet :

Python

  1. #1
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 690
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 690
    Points : 30 985
    Points
    30 985
    Billets dans le blog
    1
    Par défaut Import avec extension "py3"
    Bonjour à tous
    Aujourd'hui je franchis le pas et je commence à porter mes projets sous Python3

    Et de suite je suis confronté à un souci d'import.

    En effet, pour ne pas me mélanger entre le "après" et le "avant", mes codes que je migre sous python3 ont alors une extension en ".py3". Or, il semblerait qu'on ne puisse pas importer un script ayant cette extension.

    En effet, si par exemple j'écris un fichier "toto.py" je peux alors demander ensuite un import toto mais si le fichier se nomme "toto.py3" ben là que dalle, python me dit que le module "toto" n'existe pas.

    Pourtant le suffixe "py3" existe puisque le programme "2to3" inclus une option permettant de le positionner. J'ai même d'ailleurs fait un test en créant dans un dossier X un script "toto.py" et un "essai.py" qui importe toto (en Python2) puis demandé un "2to3 --output=Y --add-suffix=3 X" => ça a créé un dossier "Y" contenant "toto.py3" et "essai.py3" mais là ben ça ne fonctionne quand-même pas => "essai" ne peut pas importer "toto".

    Donc en fait à partir de là j'ai juste deux questions
    1) peut-on importer un fichier ".py3" (ou mieux demander que le "py3" soit l'extension par défaut dans les import) ?
    2) est-ce bien conventionnel/usité/standard/propre de mettre ".py3" comme extension de ses scripts P3 ?

    Merci à tous de votre soutien
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  2. #2
    Membre émérite

    Homme Profil pro
    Ingénieur calcul scientifique
    Inscrit en
    Mars 2013
    Messages
    1 229
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur calcul scientifique

    Informations forums :
    Inscription : Mars 2013
    Messages : 1 229
    Points : 2 328
    Points
    2 328
    Par défaut
    Salut Sve@r

    J'utilise Python3 depuis plusieurs années maintenant et j'avoue ne jamais avoir vu l'extension .py3. Même dans des packages disponibles à la fois en python2 et 3 (avec version différente).

    La différence python2/python3 doit être faite à l'échelle du projet pour moi, et non à l'échelle du fichier. Donc tu as ton dossier avec tout ton projet dedans. Et juste à côté un autre dossier pour la v3, ayant exactement la même hierarchie et contenant des fichiers portant le même nom.

    Je n'ai jamais eu à utiliser 2to3, mais il me semble qu'il fournit aussi une possibilité pour convertir un projet complet. Dans ce cas là je suis curieux de voir si 2to3 te mets les fichiers à côté des originaux en y mettant l'extension .py3 pour les différencier, ou bien s'il te créé un nouveau dossier et y met les fichiers converti à l'intérieur.

    EDIT : Je viens de relire ton post et visiblement 2to3 créer un nouveau dossier avec dedans des .py3. Bon, ceci dit l'ajout du suffixe .py3 est une option, sans doute là pour les utilisateurs qui ne traite simplement qu'avec des scripts tout en un fichier.

  3. #3
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 690
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 690
    Points : 30 985
    Points
    30 985
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par lg_53 Voir le message
    La différence python2/python3 doit être faite à l'échelle du projet pour moi, et non à l'échelle du fichier. Donc tu as ton dossier avec tout ton projet dedans. Et juste à côté un autre dossier pour la v3, ayant exactement la même hierarchie et contenant des fichiers portant le même nom.
    Oui c'est ce que j'ai fait heureusement (sinon c'était la cata). J'ai créé une nouvelle branche, y ai déversé le contenu de la branche précédente puis ensuite je traite les fichiers un à un pour au final n'avoir que du v3.
    Mais c'était aussi pour une question de lisibilité (exemple je tape ls je vois de suite si je suis dans une branche P2 ou P3). Certes à plus ou moins long terme le P2 disparaitra complètement de mon home mais pour l'instant...

    Citation Envoyé par lg_53 Voir le message
    Je n'ai jamais eu à utiliser 2to3, mais il me semble qu'il fournit aussi une possibilité pour convertir un projet complet. Dans ce cas là je suis curieux de voir si 2to3 te mets les fichiers à côté des originaux en y mettant l'extension .py3 pour les différencier, ou bien s'il te créé un nouveau dossier et y met les fichiers converti à l'intérieur.
    Par défaut il ne fait rien d'autre que raconter ce qu'il faut changer. Si on rajoute l'option "-W" il réécrit alors le fichier d'origine (qui est donc perdu). Si on demande l'option "--add-suffix=3" là il le copie en "py3". Et si on demande en plus l'option arborescente (avec "--output=dest") et qu'on lui donne un dossier à manger il traite tout son contenu et chaque fichier traité est copié dans "dest" en "py3".
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  4. #4
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 287
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 287
    Points : 36 776
    Points
    36 776
    Par défaut
    Salut,

    Citation Envoyé par Sve@r Voir le message
    1) peut-on importer un fichier ".py3" (ou mieux demander que le "py3" soit l'extension par défaut dans les import) ?
    Oui grâce à importlib. Cependant, c'est pas des plus faciles à utiliser. Fut un temps, je m'étais amusé à attraper les "import" pour mettre à jour "à la volée" des fichiers .uic pour Qt. Ça fonctionne très bien sauf que importlib était tellement instable dans les versions 3.3, 3.4,... que c'est un peu prise de tête à maintenir.
    Normalement, çà devrait être stable depuis 3.6 mais il faut trouver des exemples de code et les adapter ou plonger dans la lecture studieuse des sources.

    Citation Envoyé par Sve@r Voir le message
    2) est-ce bien conventionnel/usité/standard/propre de mettre ".py3" comme extension de ses scripts P3 ?
    La convention est toujours ".py".
    Et bien qu'on puisse résoudre le problème côté Python (voir ce qui précède), d'autres outils importants comme les IDE risquent de ne pas le supporter (et là pour mettre à jour....).

    La moins mauvaise solution (mais peut être riche) est d'utiliser un gestionnaire de configuration comme Git.

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  5. #5
    Membre émérite

    Homme Profil pro
    Ingénieur calcul scientifique
    Inscrit en
    Mars 2013
    Messages
    1 229
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur calcul scientifique

    Informations forums :
    Inscription : Mars 2013
    Messages : 1 229
    Points : 2 328
    Points
    2 328
    Par défaut
    Citation Envoyé par Sve@r Voir le message
    Mais c'était aussi pour une question de lisibilité (exemple je tape ls je vois de suite si je suis dans une branche P2 ou P3). Certes à plus ou moins long terme le P2 disparaitra complètement de mon home mais pour l'instant...
    Ca ne répond pas vraiment à la question initialement posée, mais tu peux trouver des parades pour contourner le problème tant que les versions cohabitent.

    Pour le ls, tu peux par exemple créer un fichier vide à la racine de ton projet (ou bien dans tous les dossiers), portant un nom du genre __versionxx__.txt
    Tu peux également reconfigurer ta console pour qu'elle t'affiche dans l'invit le chemin complet de là où tu te trouve (comme ca quelle que soit la commande que tu souhaite faire, le chemin t'indique quel version c'est via le nom de la branche.

    Pour conaitre dans le terminal python la version que tu manipules, tu peux aussi ajouter une variable global à chacun de tes fichiers du genre :
    __python_version__ = 3
    voire ajouter cette variable directement dans les __init__.py si tu as packagé ton projet.

  6. #6
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 690
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 690
    Points : 30 985
    Points
    30 985
    Billets dans le blog
    1
    Par défaut
    Ouaip. Effectivement en vous lisant je pense que "py3" serait en fait une "fausse" bonne idée. Apparemment c'est possible mais si je dois me lancer dans une usine à gaz pour ça... C'est toutefois bizarre que "2to3" le propose en option. Preuve que d'autres ont dû tout de même y penser.

    En tout cas, porter du P2 vers P3 me fait en plus prendre conscience de trucs que j'ai fait mais que j'aurais pas dû. Par exemple jusqu'à présent, quand je voulais vérifier si le type d'un truc était de type "machin", j'utilisais le module "types" sous forme isinstance(truc, types.MachinType) ce qui, sous P3, devient bêtement isinstance(truc, machin) car le module "types" s'est radicalement allégé.
    Or j'ai découvert que ce type d'instruction était aussi possible sous P2 (depuis la v2.2) et en lisant la doc, qu'elle était même recommandée à la place de la première (accessoirement je me demande aussi maintenant à quoi sert ce module).

    J'ai donc filtré tous mes sources P2 (un gros paquets) pour remplacer la première syntaxe par la seconde. Heureusement "vi" est pas mal pour ce genre de travail parce que sinon j'avais pas fini.

    Enfin merci à vous de vos précieux avis et conseils qui m'ont bien aidé dans mes choix.
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  7. #7
    Membre actif
    Homme Profil pro
    Conseil - Consultant en systèmes d'information
    Inscrit en
    Mai 2018
    Messages
    73
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Conseil - Consultant en systèmes d'information

    Informations forums :
    Inscription : Mai 2018
    Messages : 73
    Points : 228
    Points
    228
    Par défaut
    Pour répondre à la seconde question, non, ce n'est pas une bonne pratique, un module Python est un fichier texte avec l'extension .py

    Migrer vers Python 3 devrait se faire dans l'autre sens, c'est à dire rendre le code compatible Python3 (futur et autres) et basculer vers Python 3. Pour moi, le script 2to3 est un truc legacy.

    Citation Envoyé par Sve@r Voir le message
    Par exemple jusqu'à présent, quand je voulais vérifier si le type d'un truc était de type "machin", j'utilisais le module "types" sous forme isinstance(truc, types.MachinType) ce qui, sous P3, devient bêtement isinstance(truc, machin) car le module "types" s'est radicalement allégé.
    Or j'ai découvert que ce type d'instruction était aussi possible sous P2 (depuis la v2.2) et en lisant la doc, qu'elle était même recommandée à la place de la première (accessoirement je me demande aussi maintenant à quoi sert ce module).
    Lorsque je lis ça, il me semble toujours nécessaire de rajouter que en Python, c'est vérifier le type qui est une mauvaise pratique… Bien entendu c'est présumer de l'usage, mais rappelez-vous que le principe du DuckTyping fait que dans la plupart des cas, on ne test pas le type.

  8. #8
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 690
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 690
    Points : 30 985
    Points
    30 985
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par dad3zero Voir le message
    Migrer vers Python 3 devrait se faire dans l'autre sens, c'est à dire rendre le code compatible Python3 (futur et autres)
    Si tu lis bien tout ce que j'ai écrit, tu verras que c'est aussi ce que je cherche à faire. Mais ce n'est pas forcément toujours possible.
    Par exemple sous Python2/Qt4, la méthode translate() renvoie une QString (objet de Qt), laquelle affiche ses arguments via une méthode arg() => ex QCoreApplication.translate("source_python", "Le carré de %1 est %2", "note pour le traducteur", QCoreApplication.UnicodeUTF8).arg(n, n**2).
    Or sous Python3/Qt4 (et aussi Python3/Qt5) la QString n'existe plus. La méthode translate() renvoie maintenant une simple string Python. Cette string n'a bien évidemment pas de méthode "arg" mais une méthode sensiblement équivalente "format". Il est donc assez facile de remplacer l'instruction de l'exemple par celle-ci QCoreApplication.translate("source_python", "Le carré de {0} est {1}", "note pour le traducteur").format(n, n**2) (j'ai même écrit un script qui le fait automatiquement). Mais cette instruction ne fonctionne pas sous Python2/Qt4 car la QString ne connait pas la méthode "format".

    Citation Envoyé par dad3zero Voir le message
    Lorsque je lis ça, il me semble toujours nécessaire de rajouter que en Python, c'est vérifier le type qui est une mauvaise pratique… Bien entendu c'est présumer de l'usage, mais rappelez-vous que le principe du DuckTyping fait que dans la plupart des cas, on ne test pas le type.
    Hum... j'ai un gros doute. Par exemple je travaille avec une bdd. J'ai donc un module dédié à l'accès dans lequel j'ai une fonction select(). Cette fonction prend comme premier paramètre une colonne (ex "nom" => select nom from ...) ou bien une liste de colonnes (ex (nom, prenom, adresse) => select nom, prenom, adresse from .... Comment puis-je détecter qu'elle a reçu une chaine ou un itérable (tuple/liste) sans vérifier le type reçu ??? J'aurais pu effectivement la programmer pour qu'elle reçoive un tuple exclusivement et lui passer des tuples même pour une seule colonne mais j'ai préféré l'écrire plus complexe afin de simplifier sa façon de l'appeler (je veux juste une colonne je lui passe son nom, j'en veux plusieurs je lui passe un tuple de noms).

    Autre exemple: j'utilise Qt. Et je gère les évènements reçus notamment l'évènement "fermeture fenêtre" (qui arrive dans un closeEvent()) Cet évènement arrive soit via une demande de fermeture d'un autre widget, soit via l'utilisateur qui appuie sur "Esc".
    Dans ce dernier cas, l'évènement reçu est de type QKeyEvent (ce n'est pas une valeur mais bel et bien un type). Mais comment détecter ce type sans tester le type ??? Et après-tout, si l'instruction isinstance() existe, ce n'est pas non plus que pour faire joli...

    Citation Envoyé par dad3zero Voir le message
    Bien entendu c'est présumer de l'usage
    Hé oui.
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  9. #9
    Membre actif
    Homme Profil pro
    Conseil - Consultant en systèmes d'information
    Inscrit en
    Mai 2018
    Messages
    73
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Conseil - Consultant en systèmes d'information

    Informations forums :
    Inscription : Mai 2018
    Messages : 73
    Points : 228
    Points
    228
    Par défaut
    Citation Envoyé par Sve@r Voir le message
    Mais ce n'est pas forcément toujours possible.
    Tout à fait, là on est sur le cas de comment une lib tierce a géré sa migration.

    Hum... j'ai un gros doute. Par exemple
    Ah ! Exemples très intéressants

    Cette fonction prend comme premier paramètre une colonne ou bien une liste de colonnes. Comment puis-je détecter qu'elle a reçu une chaine ou un itérable sans vérifier le type reçu ???
    En fait, tu reçois toujours un itérable puisqu'une chaine est aussi un itérable… Ce qui est plus cocasse en Python. Alors

    J'aurais pu effectivement la programmer pour qu'elle reçoive un tuple exclusivement et lui passer des tuples même pour une seule colonne mais j'ai préféré l'écrire plus complexe afin de simplifier sa façon de l'appeler
    Et tu a tout à fait raison, en fournissant des interfaces, tu dois permettre à l'appelant d'écrire un code simple en limitant la délégation de contraintes techniques comme le formatage des données.

    Dans un cas comme décrit, il est possible que j'aurai préféré soit proposer 2 fonctions (dont une ne fait que passe-plat), soit si la fonction doit être très générique prendre en paramètre un variadic (ainsi, c'est la fonction qui gère la notion d'itérable).

    L'autre conséquence est que si tu a soit un paramètre unique soit une collection, tu a certainement aussi un critère de discrimination "interne" en fonction de tes requêtes et si une collection de paramètres est attendue, tu passe les paramètres à ta requête en utilisant un splat qui créera un nombre d'éléments différent des attendus. Et bien entendu on passe par la gestion de l'exception (forgiveness, permission, tout ça…)

    Autre exemple: j'utilise Qt. Et je gère les évènements reçus notamment l'évènement "fermeture fenêtre" (qui arrive dans un closeEvent()) Cet évènement arrive soit via une demande de fermeture d'un autre widget, soit via l'utilisateur qui appuie sur "Esc".
    Dans ce dernier cas, l'évènement reçu est de type QKeyEvent (ce n'est pas une valeur mais bel et bien un type). Mais comment détecter ce type sans tester le type ???
    Je ne connais pas Qt, ce que tu décris laisse entendre que les évènements sont des types et des messages en eux même. Très bien, le mécanisme des exceptions fonctionne comme ça.

    Attention !

    Et après-tout, si l'instruction isinstance() existe, ce n'est pas non plus que pour faire joli...
    Je n'ai pas écris qu'en Python il ne faut pas tester les types mais j'ai très mal formulé (en rebondissant que la première question sur les questions des pratiques) qu'il n'est pas d'usage de vérifier les types. Le cas des types comme message est un exemple comme quoi cette validation a un sens. Dans d'autres cas, c'est un risque de "limiter" inutilement un code.
    Là dessus, ce principe découlant du Duck Typing est surtout là parce que dans la manipulation d'objets, seuls les comportements nous intéresse en Python, pas les types. Donc ma formulation devait être "en Python, c'est vérifier le type qui est en général une mauvaise pratique", ce qui n'a rien d'absolu

  10. #10
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 690
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 690
    Points : 30 985
    Points
    30 985
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par dad3zero Voir le message
    En fait, tu reçois toujours un itérable puisqu'une chaine est aussi un itérable… Ce qui est plus cocasse en Python.
    Très cocasse surtout que j'ai effectivement été confronté au souci "je veux pouvoir détecter les itérables que je nomme "groupés" (style liste, tuples, ensembles dictionnaires) mais ne pas considérer une chaine comme itérable". J'ai dû alors créer ma propre fonction "isIterable()" qui, si elle reçoit une chaine (et là bien évidemment le terme "chaine "est à prendre au sens large => str, unicode => à ce sujet je regrette d'ailleurs profondément le "types.StringTypes") lève une exception identique à celle qui est levée quand on tente d'itérer ce qui ne l'est pas naturellement
    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    def isIterable(x):
    	try:
    		if isinstance(x, (str, unicode)): raise TypeError
    		iter(x)
    	except TypeError:
    		return False
    	else:
    		return True
    	# try
    # isIterable()

    Citation Envoyé par dad3zero Voir le message
    soit si la fonction doit être très générique prendre en paramètre un variadic (ainsi, c'est la fonction qui gère la notion d'itérable).
    Tu veux parler du "*args" ? Déjà je ne l'ai découvert qu'après. Mais c'est ici impossible car ma fonction reçoit aussi une (ou une liste) de tables. Ainsi elle reçoit deux arguments
    • une (ou une liste) de colonnes
    • une (ou une liste) de tables

    et elle gère le "select" en conséquence. Impossible donc de passer par "*args". Et le "**kwargs" est utilisé pour les options spécifiques du select comme "distinct", "order by" ou "limit".
    Et perso je n'aime pas les fonctions "passe-plat".

    Citation Envoyé par dad3zero Voir le message
    Je ne connais pas Qt, ce que tu décris laisse entendre que les évènements sont des types et des messages en eux même.
    Il y a le type d'un côté et la valeur de l'autre.
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Module - Empêcher l'importation de modules
    Par rambc dans le forum Général Python
    Réponses: 2
    Dernier message: 29/03/2011, 20h09
  2. [XL-2007] xla vs Import de modules, écrire ou importer Classes et Userforms
    Par GuyXL dans le forum Conception
    Réponses: 2
    Dernier message: 15/03/2011, 14h11
  3. Réponses: 6
    Dernier message: 18/05/2010, 12h13
  4. Executer une fonction dans un module pas encore importe
    Par Aragorn_destroy dans le forum Macros et VBA Excel
    Réponses: 2
    Dernier message: 20/06/2007, 14h21
  5. blocage base après importation d'un module
    Par voodoo dans le forum Access
    Réponses: 3
    Dernier message: 13/10/2004, 15h15

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo