Maison > développement back-end > Tutoriel Python > Comment construire un nouvel adaptateur Harlequin avec Poetry

Comment construire un nouvel adaptateur Harlequin avec Poetry

WBOY
Libérer: 2024-07-18 10:22:21
original
321 Les gens l'ont consulté

How to build a new Harlequin adapter with Poetry

Bienvenue dans le premier article de la série de didacticiels LETSQL !

Dans cet article de blog, nous faisons un détour par notre thème habituel des pipelines de données pour montrer comment créer et publier un package Python avec Poetry, en utilisant DataFusion comme exemple.

Introduction

Harlequin est un client TUI pour les bases de données SQL connu pour sa prise en charge étendue et légère des bases de données SQL. Il s'agit d'un outil polyvalent pour les flux de travail d'exploration et d'analyse de données. Harlequin fournit un éditeur SQL interactif avec des fonctionnalités telles que la saisie semi-automatique, la coloration syntaxique et l'historique des requêtes. Il dispose également d'une visionneuse de résultats qui peut afficher de grands ensembles de résultats. Cependant, Harlequin n'avait pas d'adaptateur DataFusion auparavant. Heureusement, c’était très simple d’en ajouter un.

Dans cet article, nous démontrerons ces concepts en créant un adaptateur Harlequin pour DataFusion. Et, ce faisant, nous couvrirons également les fonctionnalités essentielles de Poetry, la configuration du projet et les étapes pour publier votre package sur PyPI.

Pour tirer le meilleur parti de ce guide, vous devez avoir une compréhension de base des environnements virtuels, des packages et modules Python et de pip.
Nos objectifs sont de :

  • Présenter la poésie et ses avantages
  • Monter un projet en utilisant la Poésie
  • Développer un adaptateur Harlequin pour DataFusion
  • Préparer et publier le package sur PyPI

À la fin, vous aurez une expérience pratique de la poésie et une compréhension de la gestion moderne des packages Python.

Le code implémenté dans cet article est disponible sur GitHub et disponible dans PyPI.

Arlequin

Harlequin est un IDE SQL qui s'exécute dans le terminal. Il fournit une alternative puissante et riche en fonctionnalités aux outils de base de données en ligne de commande traditionnels, ce qui le rend polyvalent pour les flux de travail d'exploration et d'analyse de données.

Quelques éléments clés à savoir sur Arlequin :

  • Harlequin prend en charge plusieurs adaptateurs de base de données, vous connectant à DuckDB, SQLite, PostgreSQL, MySQL et plus encore.
  • Harlequin fournit un éditeur SQL interactif avec des fonctionnalités telles que la saisie semi-automatique, la coloration syntaxique et l'historique des requêtes. Il dispose également d'une visionneuse de résultats qui peut afficher de grands ensembles de résultats.
  • Harlequin remplace les outils de base de données traditionnels basés sur des terminaux par une interface plus puissante et conviviale.
  • Harlequin utilise des plug-ins d'adaptateur comme interface générique pour n'importe quelle base de données.

Fusion de données

DataFusion est un moteur de requête rapide et extensible permettant de créer des systèmes centrés sur les données de haute qualité dans Rust, en utilisant le format en mémoire Apache Arrow.

DataFusion offre des API SQL et Dataframe, d'excellentes performances, une prise en charge intégrée de CSV, Parquet, JSON et Avro, une personnalisation étendue et une excellente communauté.

Il est livré avec sa propre CLI, plus d'informations peuvent être trouvées ici.

Poésie

Poetry est un outil moderne et riche en fonctionnalités qui rationalise la gestion des dépendances et le packaging des projets Python, rendant le développement plus déterministe et efficace.
Extrait de la documentation :

Poetry est un outil de gestion des dépendances et de packaging en Python. Il vous permet de déclarer les bibliothèques dont dépend votre projet, et il les gérera (installer/mettre à jour) pour vous.
Poetry propose un fichier de verrouillage pour garantir des installations reproductibles et peut créer votre projet pour la distribution.

Création de nouveaux adaptateurs pour Harlequin

Un adaptateur Harlequin est un package Python qui permet à Harlequin de fonctionner avec un système de base de données.

Un adaptateur est un package Python qui déclare un point d'entrée dans le groupe harlequin.adapters. Ce point d'entrée doit faire référence à une sous-classe de la classe de base abstraite HarlequinAdapter.
Cela permet à Harlequin de découvrir les adaptateurs installés et d'instancier un adaptateur sélectionné au moment de l'exécution

En plus de la classe HarlequinAdapter, le package doit également fournir des implémentations pour HarlequinConnection et HarlequinCursor. Une description plus détaillée peut être trouvée à ce sujet
guider.

Le modèle d’adaptateur Harlequin

La première étape pour développer un adaptateur Harlequin consiste à générer un nouveau dépôt à partir du modèle d'adaptateur harlequin existant

Les modèles GitHub sont des référentiels qui servent de points de départ à de nouveaux projets. Ils fournissent des fichiers, des structures et des paramètres préconfigurés qui sont copiés dans de nouveaux référentiels, permettant une configuration rapide du projet sans les frais de fork.
Cette fonctionnalité rationalise le processus de création de projets cohérents et bien structurés basés sur des modèles établis.

Le modèle harlequin-adapter est livré avec un fichier poésie.lock et un fichier pyproject.toml, en plus d'un code passe-partout pour définir les classes requises.

Codage de l'adaptateur

Explorons les fichiers essentiels nécessaires à la distribution des packages avant d'entrer dans les détails du codage.

Configuration du paquet

Le fichier pyproject.toml est désormais le standard pour configurer les packages Python pour la publication et d'autres outils. Introduit dans les PEP 518 et PEP 621, ce fichier au format TOML consolide plusieurs fichiers de configuration en un seul. Il améliore la gestion des dépendances en la rendant plus robuste et standardisée.

Poésie, utilise pyproject.toml pour gérer l'environnement virtuel du projet, résoudre les dépendances et créer des packages.

Le pyproject.toml du modèle est le suivant :

[tool.poetry]
name = "harlequin-myadapter"
version = "0.1.0"
description = "A Harlequin adapter for <my favorite database>."
authors = ["Ted Conbeer <tconbeer@users.noreply.github.com>"]
license = "MIT"
readme = "README.md"
packages = [
    { include = "harlequin_myadapter", from = "src" },
]

[tool.poetry.plugins."harlequin.adapter"]
my-adapter = "harlequin_myadapter:MyAdapter"

[tool.poetry.dependencies]
python = ">=3.8.1,<4.0"
harlequin = "^1.7"

[tool.poetry.group.dev.dependencies]
ruff = "^0.1.6"
pytest = "^7.4.3"
mypy = "^1.7.0"
pre-commit = "^3.5.0"
importlib_metadata = { version = ">=4.6.0", python = "<3.10.0" }

[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"
Copier après la connexion

Comme on peut le constater :

  • La section [tool.poetry] du fichier pyproject.toml est l'endroit où vous définissez les métadonnées de votre package Python, telles que le nom, la version, la description, les auteurs, etc.

  • La sous-section [tool.poetry.dependencies] est l'endroit où vous déclarez les dépendances d'exécution requises par votre projet. Exécution de la poésie ajouter mettra automatiquement à jour cette section.

  • La sous-section [tool.poetry.dev-dependencies] est l'endroit où vous déclarez les dépendances de développement uniquement, comme les frameworks de test, les linters, etc.

  • La section [build-system] est utilisée pour stocker les données liées à la construction. Dans ce cas, il spécifie le build-backend comme "poetry.core.masonry.api". Au sens étroit, la responsabilité essentielle d'un
    build-backend consiste à construire des roues et sdist.

  • Le référentiel comprend également un fichier poésie.lock, un composant spécifique à la poésie généré en exécutant l'installation de poésie ou la mise à jour de poésie. Ce fichier de verrouillage spécifie les versions exactes de toutes les dépendances et sous-dépendances de votre projet, garantissant des installations reproductibles dans différents environnements.

    Il est crucial d'éviter les modifications manuelles du fichier poésie.lock, car cela peut entraîner des incohérences et des problèmes d'installation. Au lieu de cela, apportez des modifications à votre fichier pyproject.toml et autorisez Poetry à mettre à jour automatiquement le fichier de verrouillage en exécutant le verrouillage de poésie.

    Obtenir de la poésie

    Avertissement d'installation de Per Poetry

    ::: {.avertissement}
    Poetry doit toujours être installé dans un environnement virtuel dédié pour l'isoler du reste de votre système. Il ne doit en aucun cas être installé dans l'environnement du projet qui sera géré par Poésie.
    :::

    Ici, nous supposerons que vous avez accès à Poetry en exécutant pipx install poésie

    Développer dans l'environnement virtuel

    Une fois notre structure de fichiers clarifiée, commençons le processus de développement en configurant notre environnement. Étant donné que notre projet comprend déjà les fichiers pyproject.toml et poésie.lock, nous pouvons lancer notre environnement à l'aide de la commande du shell poésie.

    Cette commande active l'environnement virtuel lié au projet Poetry en cours, garantissant que toutes les opérations ultérieures se déroulent dans le contexte de dépendance du projet. Si aucun environnement virtuel n'existe, le shell de poésie en crée et en active automatiquement un.

    poetry shell détecte votre shell actuel et lance une nouvelle instance dans l'environnement virtuel. Comme Poetry centralise les environnements virtuels par défaut, cette commande élimine le besoin de localiser ou de rappeler le chemin spécifique du script d'activation.

    Pour vérifier quel environnement Python est actuellement utilisé avec Poetry, vous pouvez utiliser les commandes suivantes :

    poetry env list --full-path
    
    Copier après la connexion

    Cela affichera tous les environnements virtuels associés à votre projet et indiquera lequel est actuellement actif.
    Comme alternative, vous pouvez obtenir le chemin complet uniquement de l'environnement actuel :

    poetry env info -p
    
    Copier après la connexion

    Une fois l'environnement activé, utilisez poésie install pour installer les dépendances requises. La commande fonctionne comme suit

    1. Si un fichier poésie.lock est présent, l'installation de poésie utilisera les versions exactes spécifiées dans ce fichier plutôt que de résoudre les dépendances de manière dynamique. Cela garantit des installations cohérentes et reproductibles dans différents environnements. je. Si vous exécutez l'installation de poésie et qu'elle ne semble pas progresser, vous devrez peut-être exécuter export PYTHON_KEYRING_BACKEND=keyring.backends.null.Keyring dans le shell dans lequel vous installez
    2. Sinon, il lit le fichier pyproject.toml dans le projet en cours, résout les dépendances qui y sont répertoriées et les installe.
    3. Si aucun fichier poésie.lock n'existe, l'installation de poésie en créera un après avoir résolu les dépendances, sinon elle mettra à jour celui existant.

    Pour terminer la configuration de l'environnement, nous devons ajouter la bibliothèque datafusion à nos dépendances. Exécutez la commande suivante :

    poetry add datafusion
    
    Copier après la connexion

    Cette commande met à jour votre fichier pyproject.toml avec le package datafusion et l'installe. Si vous ne spécifiez pas de version, Poetry en sélectionnera automatiquement une appropriée en fonction des versions de package disponibles.

    Implementing the Interfaces

    To create a Harlequin Adapter, you need to implement three interfaces defined as abstract classes in the harlequin.adapter module.

    The first one is the HarlequinAdapter.

    #| eval: false
    #| code-fold: false
    #| code-summary: implementation of HarlequinAdapter
    
    class DataFusionAdapter(HarlequinAdapter):
        def __init__(self, conn_str: Sequence[str], **options: Any) -> None:
            self.conn_str = conn_str
            self.options = options
    
        def connect(self) -> DataFusionConnection:
            conn = DataFusionConnection(self.conn_str, self.options)
            return conn
    
    Copier après la connexion

    The second one is the HarlequinConnection, particularly the methods execute and get_catalog.

    #| eval: false
    #| code-fold: false
    #| code-summary: implementation of execution of HarlequinConnection
    
     def execute(self, query: str) -> HarlequinCursor | None:
         try:
             cur = self.conn.sql(query)  # type: ignore
             if str(cur.logical_plan()) == "EmptyRelation":
                 return None
         except Exception as e:
             raise HarlequinQueryError(
                 msg=str(e),
                 title="Harlequin encountered an error while executing your query.",
             ) from e
         else:
             if cur is not None:
                 return DataFusionCursor(cur)
             else:
                 return None
    
    Copier après la connexion

    For brevity, we've omitted the implementation of the get_catalog function. You can find the full code in the adapter.py file within our GitHub repository.

    Finally, a HarlequinCursor implementation must be provided as well:

    #| eval: false
    #| code-fold: false
    #| code-summary: implementation of HarlequinCursor
    
    class DataFusionCursor(HarlequinCursor):
        def __init__(self, *args: Any, **kwargs: Any) -> None:
            self.cur = args[0]
            self._limit: int | None = None
    
        def columns(self) -> list[tuple[str, str]]:
            return [
                (field.name, _mapping.get(field.type, "?")) for field in self.cur.schema()
            ]
    
        def set_limit(self, limit: int) -> DataFusionCursor:
            self._limit = limit
            return self
    
        def fetchall(self) -> AutoBackendType:
            try:
                if self._limit is None:
                    return self.cur.to_arrow_table()
                else:
                    return self.cur.limit(self._limit).to_arrow_table()
            except Exception as e:
                raise HarlequinQueryError(
                    msg=str(e),
                    title="Harlequin encountered an error while executing your query.",
                ) from e
    
    Copier après la connexion

    Making the plugin discoverable

    Your adapter must register an entry point in the harlequin.adapters group using the packaging software you use to build your project.
    If you use Poetry, you can define the entry point in your pyproject.toml file:

    [tool.poetry.plugins."harlequin.adapter"]
    datafusion = "harlequin_datafusion:DataFusionAdapter"
    
    Copier après la connexion

    An entry point is a mechanism for code to advertise components it provides to be discovered and used by other code.

    Notice that registering a plugin with Poetry is equivalent to the following pyproject.toml specification for entry points:

    [project.entry-points."harlequin.adapter"]
    datafusion = "harlequin_datafusion:DataFusionAdapter"
    
    Copier après la connexion

    Testing

    The template provides a set of pre-configured tests, some of which are applicable to DataFusion while others may not be relevant. One test that's pretty cool checks if the plugin can be discovered, which is crucial for ensuring proper integration:

    #| eval: false
    #| code-fold: false
    if sys.version_info < (3, 10):
        from importlib_metadata import entry_points
    else:
        from importlib.metadata import entry_points
    
    
    def test_plugin_discovery() -> None:
        PLUGIN_NAME = "datafusion"
        eps = entry_points(group="harlequin.adapter")
        assert eps[PLUGIN_NAME]
        adapter_cls = eps[PLUGIN_NAME].load()
        assert issubclass(adapter_cls, HarlequinAdapter)
        assert adapter_cls == DataFusionAdapter
    
    Copier après la connexion

    To make sure the tests are passing, run:

    poetry run pytest
    
    Copier après la connexion

    The run command executes the given command inside the project’s virtualenv.

    Building and Publishing to PyPI

    With the tests passing, we're nearly ready to publish our project. Let's enhance our pyproject.toml file to make our package more discoverable and appealing on PyPI. We'll add key metadata including:

    1. A link to the GitHub repository
    2. A path to the README file
    3. A list of relevant classifiers

    These additions will help potential users find and understand our package more easily.

    classifiers = [
        "Development Status :: 3 - Alpha",
        "Intended Audience :: Developers",
        "Topic :: Software Development :: User Interfaces",
        "Topic :: Database :: Database Engines/Servers",
        "License :: OSI Approved :: MIT License",
        "Programming Language :: Python :: Implementation :: CPython"
    ]
    readme = "README.md"
    repository = "https://github.com/mesejo/datafusion-adapter"
    
    Copier après la connexion

    For reference:

    • The complete list of classifiers is available on PyPI's website.
    • For a detailed guide on writing pyproject.toml, check out this resource.
    • The formal, technical specification for pyproject.toml can be found on packaging.python.org.

    Building

    We're now ready to build our library and verify its functionality by installing it in a clean virtual environment. Let's start with the build process:

    poetry build
    
    Copier après la connexion

    This command will create distribution packages (both source and wheel) in the dist directory.

    The wheel file should have a name like harlequin_datafusion-0.1.1-py3-none-any.whl. This follows the standard naming convention:

    • harlequin_datafusion is the package (or distribution) name
    • 0.1.1 is the version number
    • py3 indicates it's compatible with Python 3
    • none compatible with any CPU architecture
    • any with no ABI (pure Python)

    To test the installation, create a new directory called test_install. Then, set up a fresh virtual environment with the following command:

    python -m venv .venv
    
    Copier après la connexion

    To activate the virtual environment on MacOS or Linux:

    source .venv/bin/activate
    
    Copier après la connexion

    After running this command, you should see the name of your virtual environment (.venv) prepended to your command prompt, indicating that the virtual environment is now active.

    To install the wheel file we just built, use pip as follows:

    pip install /path/to/harlequin_datafusion-0.1.1-py3-none-any.whl
    
    Copier après la connexion

    Replace /path/to/harlequin_datafusion-0.1.1-py3-none-any.whl with the actual path to the wheel file you want to install.

    If everything works fined, you should see some dependencies installed, and you should be able to do:

    harlequin -a datafusion
    
    Copier après la connexion

    Congrats! You have built a Python library. Now it is time to share it with the world.

    Publishing to PyPI

    The best practice before publishing to PyPI is to actually publish to the Test Python Package Index (TestPyPI)

    To publish a package to TestPyPI using Poetry, follow these steps:

    1. Create an account at TestPyPI if you haven't already.

    2. Generate an API token on your TestPyPI account page.

    3. Register the TestPyPI repository with Poetry by running:

      poetry config repositories.test-pypi https://test.pypi.org/legacy/
      
      Copier après la connexion
    4. To publish your package, run:

      poetry publish -r testpypi --username __token__ --password <token>
      
      Copier après la connexion

    Replace with the actual token value you generated in step 2. To verify the publishing process, use the following command:

    python -m pip install --index-url https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple <package-name>
    
    Copier après la connexion

    This command uses two key arguments:

    • --index-url: Directs pip to find your package on TestPyPI.
    • --extra-index-url: Allows pip to fetch any dependencies from the main PyPI repository.

    Replace with your specific package name (e.g., harlequin-datafusion if following this post). For additional details, consult the information provided in this post.

    To publish to the actual Python Package Index (PyPI) instead:

    1. Create an account at https://pypi.org/ if you haven't already.

    2. Generate an API token on your PyPI account page.

    3. Run:

      poetry publish --username __token__ --password <token>
      
      Copier après la connexion

    The default repository is PyPI, so there's no need to specify it.

    Is worth noting that Poetry only supports the Legacy Upload API when publishing your project.

    Automated Publishing on GitHub release

    Manually publishing each time is repetitive and error-prone, so to fix this problem, let us create a GitHub Action to
    publish each time we create a release.

    Here are the key steps to publish a Python package to PyPI using GitHub Actions and Poetry:

    1. Set up PyPI authentication: You must provide your PyPI credentials (the API token) as GitHub secrets so the GitHub Actions workflow can access them. Name these secrets something like PYPI_TOKEN.

    2. Create a GitHub Actions workflow file: In your project's .github/workflows directory, create a new file like publish.yml with the following content:

       name: Build and publish python package
    
       on:
         release:
           types: [ published ]
    
       jobs:
         publish-package:
           runs-on: ubuntu-latest
           permissions:
             contents: write
           steps:
             - uses: actions/checkout@v3
             - uses: actions/setup-python@v4
               with:
                 python-version: '3.10'
    
             - name: Install Poetry
               uses: snok/install-poetry@v1
    
             - run: poetry config pypi-token.pypi "${{ secrets.PYPI_TOKEN }}"
    
             - name: Publish package
               run: poetry publish --build --username __token__
    
    Copier après la connexion

    The key is to leverage GitHub Actions to automate the publishing process and use Poetry to manage your package's dependencies and metadata.

    Conclusion

    Poetry is a user-friendly Python package management tool that simplifies project setup and publication. Its intuitive command-line interface streamlines environment management and dependency installation. It supports plugin development, integrates with other tools, and emphasizes testing for robust code. With straightforward commands for building and publishing packages, Poetry makes it easier for developers to share their work with the Python community.

    At LETSQL, we're committed to contributing to the developer community. We hope this blog post serves as a straightforward guide to developing and publishing Python packages, emphasizing best practices and providing valuable resources.
    To subscribe to our newsletter, visit letsql.com.

    Future Work

    As we continue to refine the adapter, we would like to provide better autocompletion and direct reading from files (parquet, csv) as in the DataFusion-cli. This requires a tighter integration with the Rust library without going through the Python bindings.

    Your thoughts and feedback are invaluable as we navigate this journey. Share your experiences, questions, or suggestions in the comments below or on our community forum. Let's redefine the boundaries of data science and machine learning integration.

    Acknowledgements

    Thanks to Dan Lovell and Hussain Sultan for the comments and the thorough review.

    Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

source:dev.to
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal