<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: simlay</title>
    <description>The latest articles on DEV Community by simlay (@simlay).</description>
    <link>https://dev.to/simlay</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F455600%2F4d0d0575-9ed3-4c46-9fc7-6dc7518f4662.png</url>
      <title>DEV Community: simlay</title>
      <link>https://dev.to/simlay</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/simlay"/>
    <language>en</language>
    <item>
      <title>How we built our Python Client that's mostly Rust</title>
      <dc:creator>simlay</dc:creator>
      <pubDate>Fri, 27 Aug 2021 17:30:16 +0000</pubDate>
      <link>https://dev.to/infinyon/how-we-built-our-python-client-that-s-mostly-rust-3p63</link>
      <guid>https://dev.to/infinyon/how-we-built-our-python-client-that-s-mostly-rust-3p63</guid>
      <description>&lt;p&gt;This week, we're happy to announce the addition of a &lt;a href="https://github.com/infinyon/fluvio-client-python"&gt;Python client library for Fluvio&lt;/a&gt;. Using the Python client is just as easy as using our other clients. Check out the &lt;a href="https://infinyon.com/tutorials/python/hello-world/"&gt;hello world in Python tutorial&lt;/a&gt; or &lt;a href="https://infinyon.github.io/fluvio-client-python/fluvio.html"&gt;documentation&lt;/a&gt; for usage.&lt;/p&gt;

&lt;p&gt;In this post, we'll talk about how we were able to leverage some of the great Rust tools to build a Python client without writing much Python itself.&lt;/p&gt;

&lt;h2&gt;
  
  
  Overview
&lt;/h2&gt;

&lt;p&gt;In short, we will:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;use &lt;a href="https://github.com/Dushistov/flapigen-rs"&gt;flapigen&lt;/a&gt; to define how our Rust structs will go across the FFI.&lt;/li&gt;
&lt;li&gt;use the &lt;a href="https://github.com/dgrunwald/rust-cpython"&gt;rust-cpython&lt;/a&gt; extension in our Python project and call it.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Setup
&lt;/h2&gt;

&lt;p&gt;To get started, we'll create a new project folder that's set up for both&lt;br&gt;
Rust and Python, using &lt;code&gt;cargo&lt;/code&gt; and &lt;code&gt;venv&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;cargo new &lt;span class="nt"&gt;--lib&lt;/span&gt; my-python-lib
&lt;span class="nb"&gt;cd &lt;/span&gt;my-python-lib
python &lt;span class="nt"&gt;-m&lt;/span&gt; venv venv
&lt;span class="nb"&gt;source &lt;/span&gt;venv/bin/activate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above creates a Rust crate named &lt;code&gt;my-python-lib&lt;/code&gt;, then sets-up a Python &lt;a href="https://docs.python.org/3/tutorial/venv.html"&gt;virtual environment&lt;/a&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: You'll need to have the &lt;a href="https://rustup.rs/"&gt;rust toolchain&lt;/a&gt; and &lt;a href="https://www.python.org/downloads/"&gt;python 3.6&lt;/a&gt; or above installed.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Rust glue
&lt;/h2&gt;

&lt;p&gt;We'll need to add this to your &lt;code&gt;Cargo.toml&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;[&lt;/span&gt;lib]
crate-type &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"cdylib"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;

&lt;span class="o"&gt;[&lt;/span&gt;dependencies]
cpython &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; version &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"0.5"&lt;/span&gt;, features &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"extension-module"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="o"&gt;[&lt;/span&gt;build-dependencies]
flapigen &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"0.6.0-pre7"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;crate-type = ["cdylib"]&lt;/code&gt; tells Rust to build our crate as a C-compatible &lt;a href="https://en.wikipedia.org/wiki/Dynamic_linker"&gt;dynamic library&lt;/a&gt; rather than a typical crate. This crate type will allow our Python code to interact with our library as if it were compiled C code rather than Rust.&lt;/p&gt;

&lt;p&gt;Now we'll create a &lt;a href="https://doc.rust-lang.org/cargo/reference/build-scripts.html"&gt;build script&lt;/a&gt; in &lt;code&gt;build.rs&lt;/code&gt; by adding the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;flapigen&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;LanguageConfig&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;PythonConfig&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nn"&gt;path&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Path&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;in_src&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Path&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"src"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"glue.rs.in"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;out_dir&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;env&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"OUT_DIR"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;out_src&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Path&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;out_dir&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"glue.rs"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;python_cfg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;PythonConfig&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"my_python_lib"&lt;/span&gt;&lt;span class="nf"&gt;.to_owned&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;flap_gen&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
        &lt;span class="nn"&gt;flapigen&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;Generator&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;LanguageConfig&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;PythonConfig&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;python_cfg&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="nf"&gt;.rustfmt_bindings&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;flap_gen&lt;/span&gt;&lt;span class="nf"&gt;.expand&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"python bindings"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;in_src&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;out_src&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"cargo:rerun-if-changed={}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;in_src&lt;/span&gt;&lt;span class="nf"&gt;.display&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The code sets up &lt;code&gt;flapigen&lt;/code&gt; to run on our project. At build time, it will read the "glue code" we write in &lt;code&gt;src/glue.rs.in&lt;/code&gt;, and generate Rust code to interact with Python and place it in &lt;code&gt;${OUT_DIR}/glue.rs&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Now we'll add a &lt;code&gt;src/glue.rs.in&lt;/code&gt; file with something like the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;Foo&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;val&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;i32&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;impl&lt;/span&gt; &lt;span class="n"&gt;Foo&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;val&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;i32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Self&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;Self&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;val&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;set_field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;new_val&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;i32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="py"&gt;.val&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;new_val&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;val&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;i32&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="py"&gt;.val&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nd"&gt;foreign_class!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;class&lt;/span&gt; &lt;span class="n"&gt;Foo&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;self_type&lt;/span&gt; &lt;span class="n"&gt;Foo&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;constructor&lt;/span&gt; &lt;span class="nn"&gt;Foo&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;_&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;i32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Foo&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nn"&gt;Foo&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;set_field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;_&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;i32&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nn"&gt;Foo&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;val&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;i32&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This simple example was published in the &lt;a href="https://dushistov.github.io/flapigen-rs/foreign-class.html"&gt;flapigen book&lt;/a&gt; and we can copy and paste it here.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;src/lib.rs&lt;/code&gt; should currently have some basic tests. We'll change it to the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="nd"&gt;#![allow(non_snake_case,&lt;/span&gt; &lt;span class="nd"&gt;unused)]&lt;/span&gt;

&lt;span class="nd"&gt;include!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;concat!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;env!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"OUT_DIR"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="s"&gt;"/glue.rs"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is a typical Rust pattern when using build scripts. The code takes the file in &lt;code&gt;${OUT_DIR}/glue.rs&lt;/code&gt; and includes the contents into &lt;code&gt;src/lib.rs&lt;/code&gt; in the build directory. The result will be as if we hand-wrote the generated code in&lt;br&gt;
our &lt;code&gt;lib.rs&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;This section uses flapigen to expand the &lt;a href="https://dushistov.github.io/flapigen-rs/foreign-class.html"&gt;&lt;code&gt;foreign_class&lt;/code&gt;&lt;/a&gt; macro into many &lt;a href="https://github.com/dgrunwald/rust-cpython"&gt;cpython&lt;/a&gt; functions as an &lt;a href="https://docs.python.org/3/extending/extending.html"&gt;extension module&lt;/a&gt;, and cargo compiles it as a &lt;a href="https://doc.rust-lang.org/cargo/reference/cargo-targets.html#library"&gt;&lt;code&gt;cdylib&lt;/code&gt;&lt;/a&gt;. If you want to see what that looks like, install &lt;a href="https://crates.io/crates/cargo-expand"&gt;&lt;code&gt;cargo-expand&lt;/code&gt;&lt;/a&gt; and run &lt;code&gt;cargo expand&lt;/code&gt;. You'll get a lot of generated rust code.&lt;/p&gt;
&lt;h2&gt;
  
  
  Python Glue
&lt;/h2&gt;

&lt;p&gt;In the &lt;code&gt;setup&lt;/code&gt;, we created a virtual environment, and now we'll need to install some Python tools via:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;source &lt;/span&gt;venv/bin/activate &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; pip &lt;span class="nb"&gt;install &lt;/span&gt;setuptools-rust
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now to create a python package, you create a file called &lt;code&gt;setup.py&lt;/code&gt; with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;setuptools&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;setup&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;setuptools_rust&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Binding&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;RustExtension&lt;/span&gt;

&lt;span class="n"&gt;setup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"my-python-lib"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;version&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"1.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;rust_extensions&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;RustExtension&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"my_python_lib"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;binding&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;Binding&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RustCPython&lt;/span&gt;&lt;span class="p"&gt;)],&lt;/span&gt;
    &lt;span class="c1"&gt;# rust extensions are not zip safe, just like C-extensions.
&lt;/span&gt;    &lt;span class="n"&gt;zip_safe&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the most basic &lt;a href="https://github.com/PyO3/setuptools-rust#setuppy"&gt;setuptools-rust&lt;/a&gt; setup, except for using &lt;a href="https://setuptools-rust.readthedocs.io/en/latest/reference.html#setuptools_rust.Binding"&gt;&lt;code&gt;RustCPython&lt;/code&gt;&lt;/a&gt; as the binding.&lt;/p&gt;

&lt;p&gt;To build the Rust and the Python packages just run &lt;code&gt;python setup.py develop&lt;/code&gt;. Python calls &lt;code&gt;cargo&lt;/code&gt; and moves &lt;code&gt;cdylib&lt;/code&gt; into your local directory.&lt;/p&gt;

&lt;h2&gt;
  
  
  Testing it all out
&lt;/h2&gt;

&lt;p&gt;Create a &lt;code&gt;simple.py&lt;/code&gt; script with the following in it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;my_python_lib&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Foo&lt;/span&gt;
&lt;span class="n"&gt;foo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Foo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;val&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="n"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set_field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;val&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Running the script via &lt;code&gt;python simple.py&lt;/code&gt; should result in:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;python simple.py
1
11
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And there you go, you've called Rust from Python!&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;You can get the source for this post in our &lt;a href="https://github.com/infinyon/fluvio-demo-apps-rust/tree/master/my-python-lib-blog-post"&gt;fluvio-demo-apps-rust&lt;/a&gt; repository.&lt;/p&gt;

&lt;p&gt;These are just the basics for setting up a Python wrapper. In the Fluvio Python Client, the Rust crate is &lt;a href="https://github.com/infinyon/fluvio-client-python/blob/c6d82d63a001376325d8583c75319c41fd5bfcd5/build.rs#L10"&gt;&lt;code&gt;_fluvio_python&lt;/code&gt;&lt;/a&gt;; a private python module that wraps the rust structs with python classes, giving us nice &lt;a href="https://infinyon.github.io/fluvio-client-python/fluvio.html"&gt;documentation generation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Packaging, testing, and publishing on &lt;code&gt;pypi&lt;/code&gt; is beyond the scope of this blog. Checkout the &lt;a href="https://github.com/infinyon/fluvio-client-python/blob/main/Makefile"&gt;&lt;code&gt;Makefile&lt;/code&gt;&lt;/a&gt; and the &lt;a href="https://github.com/infinyon/fluvio-client-python/blob/main/.github/workflows/publish.yml"&gt;github publishing workflow&lt;/a&gt; for additional information.&lt;/p&gt;

&lt;p&gt;This blog was first published &lt;a href="https://www.infinyon.com/blog/2021/03/python-client/"&gt;here&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>rust</category>
      <category>python</category>
      <category>showdev</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
