ppet for this but it used five or six different ways to try and detect the standard library and it fell back to checking whether site packages is in the path of the file so at this point it boils down to risk versus reward it might not be safe to do this in all cases what happens if your project is called site packages for whatever reason and if you make a mistake then it's going to frustrate users the autoreloader won't work in all cases and that's just not a nice place to be in so whatever autoreloader I could find does this so other games could be huge you could reduce the number of packages or modules you're searching for by 70, 80% it's not safe to do in the general case but it doesn't get done but what you can do is use fast system notifications so calling stat repeatedly is kind of wasteful, you're just asking are we nearly there yet, are we nearly there yet it'd be nice if the operating system can tell you or the operating system can tell you when a file is modified and then you just wait and the operating system will tell you so each platform has different ways of handling this Watchdog is a Python library and it implements five different ways and it's 3,000 lines of code and all file system notifications on operating systems are directory based whereas we care about files which makes it a little bit harder because you get notifications for any file in a directory which has changed and you need to filter them out notifiers are also potentially expensive they're generally designed for longer term monitoring they're designed for a demon that's watching a bunch of files and it performs an action when a change is made in our flow we're going to create and destroy them quickly every time a Python process shuts down Django restarts it, it has to create a new watch thing with a kernel and it's going to use more resources than it should so this is the actual feature that we wanted to add to the Django water reloader it was using a system called Watchman from Facebook so Watchman is a demon that runs on your machine and it handles all of the icky differences between platforms for you you register watches with it it does the right thing and it returns changes to you over a socket and it handles git changes which is one of the reasons you want to add Watchman in the first place if you check out a new branch in git you're going to have hundreds of notifications flying at your process everything's been changed but with this it will wait until all of the checkout has finished and then it will send one single bulk update telling you that the process is finished otherwise what might happen is your process receives one file has been changed mid checkout is going to restart and it's going to be in an inconsistent state if the checkout is still happening after the Django process has restarted and the demon can be shared with our projects so if you have like a JavaScript project that also uses Watchman, quite a few of them do they can share the watches so this is how we do it in pseudo code with Watchman we connect to some kind of Watchman server we tell it what files to watch and in the while true loop we just tell it to wait this waits on a socket for a message from the Watchman demon and if there are any changes we exit with exit code 3 and this way we don't write any platform specific code and we don't have any issues regarding weird OSX versions that don't use a particular library or something like that cool, so we made it efficient as well so the after month the code was much more modern and it's easy to extend it was faster and it can use Watchman if available, there were 72 tests this is in Django and it's no longer a dark corner of Django I might be a little bit biased in saying that seeing as I wrote it but it was certainly in my opinion a little bit better so it's all good, I'm a genius work first time, tests for green, ship it etc everyone's happy these are all issues from the Django Ticket Tracker after we released the Inversion 2.2 the new Autoreloader there were quite a few unfortunately so more tests doesn't always mean that it works so this is my favourite issue and the issue is it doesn't work on Windows essentially, without using Watchman so it doesn't work intermittently so I want to highlight this because this is a great example of how you can make what seems to be a really simple automation that makes sense and have it completely backfire in a way that you don't know why so in the Django implementation that I discussed before we might not be watching for a file that doesn't exist yet some files, Python files in Django if they are there that's a change so for example the models.py if you were to create a directory with a models.py and add that file the stat reloader would the first tick, the first time it attacks the file is there it doesn't pick that up as a modification because it's the first time it's seen it only the second modification where it can compare the modification time of the previous time to the current time does it reload so I was like okay, that's the corner case need to fix that so we store the last time of a loop and if the previous end time I've done this before and the modification time of the file is greater than the time of the last loop then we reload okay this doesn't work on Windows 25% of the time and I could never work out why so you would restart the process would restart and it just wouldn't work but then you would restart it manually and it would work and on all other platforms it worked fine if you know Windows and you want to tell me why this is please, because it keeps me up at night but the point here is you get all kinds of strange behavior across different operating systems across different disks, different configurations and simple optimizations can bite you so keep it simple if you're writing your own and keep it really simple in conclusion don't write your own autoreloader use this library this is the library from Pylons called HAPA and this is a fantastic library in the abstract of this talk you may have seen I was going to present a library that I wrote myself that took all of this knowledge and distilled it into a library this is that library that someone else has written probably better than I could so check it out if you are writing your own framework and you want to add an autoreloader it's really good cool, I'd just like to thank Onfido, who's the company I work for they're paying for me to come here and give this talk we are in the business of identity verification it's a really interesting problem space from the theoretical like what is an identity to the more interesting how do you handle millions of identity checks as fast as possible with as little forward as possible so if you're interested in any of this Onfido specifically, come talk to me afterwards send me an email or check our careers page any questions we have time for a couple of questions does your autoreloader handle it properly if editors do weird stuff when saving files like creating a copy first and then we name it can you save it again, I'm sorry many editors nowadays do like save-saving so it doesn't overwrite the files but rather create a new one so Watchman handles that for you quite nicely as well so it looks at common patterns where you create a separate file and then you do an atomic move the stat reloader handles that as well because it doesn't watch for the new file the .new file which is then moved so as far as it knows the individual path has been changed so I'm going to go back to the other one okay, thank you hi if restarting the process isn't really an option let's say you have plugins for an application and you can still kind of control how the code in the plugin looks because you're defining the API would you say reloading without restarting is possible or just don't so the exclusion to a hot reloader is a plugin system where you have access to that plugin or you control the plugin and you can safely or you know that you can safely delete the reference and re-import it it doesn't always work if you have for example a C module extension module that plugin relies on it might have some initialization code you can't really safely hot reload those at all so it depends, you can write a hot reloader in some specific cases a plugin one in general but it's safer if you find into weird issues to just restart the process so a good implementation might be both, if you can detect a change if you can somehow diff the changes and work out what needs to be updated you could hot reload simple changes and then fall back to a restart if needed thank you one super quick question there you go I tried Watchmen years ago when it just came out, is the API better now or easier to use? the API is better but it's still a little bit harder than I would have liked to use the simplistic code that I showed where you register a file is nothing like you need to do you need to work out, it's directory based so you need to work out the set of files which common directories do you want to watch minimizing the amount of directories that you do watch it doesn't take care of any of that for you but in general it's quite nice to say watch this and you just get notifications on a socket and it provides utilities for filtering out specific files regular expressions on the files etc in a way that's quite cross-platform and takes a lot of code off you but it's definitely more complicated than I would have liked alright, let's thank Tom again and I think it's coffee time welcome to the second half of the afternoon talks okay we're almost ready to start okay, we have Mark here and without a kilt sorry? without a kilt oh yeah, I know and he's going to tell us about how to publish this is difficult, publish a perfect python package on pypi let's welcome Mark thanks very much this is a slight joke though I started writing a relatively normal title and then I realized it had a lot of peas in it so I thought I would add a few more just to make it difficult for the session chairs to pronounce so, sorry okay, so there's a lot to get through so I will hurry on quite quickly but in a moment I'm going to show you how to build perfect python packages from scratch I won't be taking questions because honestly this is like a tight squeeze for 30 minutes anyway but I still have to talk about something first more important than python packaging and that's me so my name is not gg2k but this is my handle more or less everywhere online feel free to follow me on twitter I tweet about python and brexit occasionally angrily so yeah, my real name is Mark Smith I'm a developer advocate for Nexmo one of the conference sponsors I would be remiss if I didn't at least briefly talk about Nexmo we are a software as a service company that deals with best APIs that allow you to do telecommunications and various other forms of communication including video streaming online to mobile devices and web apps if that sounds interesting come and talk to us at the Nexmo booth or send me a tweet or come and talk to me around the conference I'm happy to talk about that another time so, now I've talked about Nexmo let me talk about JavaScript so, in March 2016 a developer removed a library called called LeftPad from NPM, the NodeJS equivalent of PyPI. It's a big web service, holds packages, when you need to pull down those packages and install them into your JavaScript application, you run NPM and it downloads them and installs them so that you can access them from your program. LeftPad, so it broke lots of packages that depended on LeftPad. It turns out that quite a lot of packages on NPM depended on LeftPad. In fact, it had been downloaded 2,486,696 times in the month before it was removed from the NPM repository. It was just one function and it was 11 lines of code that padded a string to a certain length by adding characters to the start of that string. And lots of people thought that this made the JavaScript community look kind of silly. Why would anybody publish a package that only consisted of 11 lines of code? Why would anybody use a package that only consisted of 11 lines of code? I don't think it made the JavaScript community look silly. I think, actually, it made the JavaScript community look pretty awesome. Obviously, there's some problems with the fact that people can remove a package that everybody's depended on and kind of break the entire JavaScript community's software, but in general, why was this package published? So if you don't agree that this made the JavaScript community look awesome, feel free to fight me on Twitter. So the LeftPad is not a problem. LeftPad was a solution. So because the JavaScript standard library is relatively small and doesn't contain lots of useful functions, say the Python standard library does contain, like the ability to LeftPad a string with some characters, a developer wrote a solution for it himself. And because NPM makes it easy to publish small items of code, he did. And he made that code available to other developers so that they then didn't have to reinvent the wheel. And that means that people can bug fix in one location, they can submit PRs to improve these 11 lines of code, and then ultimately people can, well, ideally, depend upon it. Now, the alternative to this is copy and paste. Copy and paste, I think you can agree, is not how you should share your code. Because it's really easy to share with NPM, people do, and even with really small libraries. And I don't think that's really the case with Python, because people find Python packaging slightly fiddly. There are some slightly odd things which we'll go through about pushing your first Python package to PyPI. So I made it difficult for myself to say some of these sentences as well. So people are a bit afraid of setup, Py. There is good documentation out there, lots of it conflicts with each other. But there is, I think, a growing movement to bring some of this stuff together and make it easier to find current best practices. Hopefully this talk will help a little bit. So what I really want everybody in this room to feel at the end of this talk is confident to publish packages to PyPI. Relatively small packages, maybe ideally pure Python packages, which is what the example is going to be. So I would like you all to make a package. What we're going to do in this talk is I am going to show you how to make a package. So the first thing, the assumption is that you already have some code, which is general enough or close to general enough that you think it would be useful for other people. So let's take some useful general purpose code, like a function that prints hello world. Now who in this room hasn't written this program in some form? Exactly. Now that is totally wasted time. Everybody in this room has written this program. Wouldn't it be so much better if you could pip install it and call that code from somewhere else? So that's what we're going to do. Also note there's an F string here. F strings are awesome. You should use them. So the idea is you've written some code that you're proud of. You would like to share it with the world. So the first thing to do is extract it from your code base so that it is independent of that code base. That's your problem. I'm not going to show you how to do that. In this case, we're going to extract this code into a file called hello world.py as a Python module. Next, we're going to put that module in a source directory. And I will explain towards the end of the talk why we did that. For the moment, just assume that Hinnick is excitedly clapping for the second time today. Awkward. So I'll explain why later, but for the moment, just take this as correct practice. And then in the same directory as the source directory, the container source directory, we are going to create our setup py file. You can open that up in your favorite text editor or Python IDE. And we will enter something like this into the file. So the first thing to note here is that we're importing from setup tools not to distutils. Distutils, you will still find documentation online that recommends importing from distutils. Don't do that. It's not that powerful compared to setup tools. PIP already is distributed with setup tools. So if you're installing packages with PIP, you have setup tools. It's not a third-party dependency anymore. And then we have this function underneath it. We call setup that we've imported from the setup tools module. It's a bit weird. For now, just don't think of it as a function call. Think of it as configuration. Each of those parameters is essentially a line of configuration that you are giving to PIP to tell how to install your package. So this is pretty much the bare minimum setup information you need to provide. So we start with a name. Name is what you PIP install. So this is the name on PIP that it will be uploaded under. So people will PIP install it. It doesn't have to be the name of the Python code that people will import. It's a separate thing. Usually they're the same. Sometimes they're different. We need to pick a version number. Here I've just started with 001. 00x version numbers imply that it's unstable. There is a good chance that the first few times you upload this to PIP, there will be a minor packaging mistake. So this is a good stage to start to upload packages to PIP while you've still got this unstable version number. So you're not worried about people seeing instability. It's not actually your code base. It's actually your packaging configuration. Then we have a description. This is usually a one-liner at this point. Say hello. It's not a very useful description. But we'll leave it at that. Then we have pi modules, which is a list of the actual Python code modules. So we have a file called hello world.py. So in here we're saying this is the code that we want to distribute. So that's what people import, not what they PIP install. And then finally, again, this is a kind of cargo copy and paste setup config. We have this package deer line, which is a map that sort of said empty string and a source. All that is doing is telling setup tools that our code is under a source directory. So don't worry. Put it in your code and forget about it after that. So now we've built a package. So let's build it. Potentially we could distribute it. So we run the setup file we've just created with the beedest wheel command. This tells it to create a wheel file that's something that is appropriate for uploading to PyPI. It will spit out a load of output, most of which I've deleted from here. But the line that I've highlighted in bold up here is the one that's important. So what that's saying is that it's just copied our Hello World Py code file into the lib directory, which means that it will end up in our wheel. If that's not there, then essentially there will be no code. It will have an empty, an empty wheel file and it won't work. So we can now look at what's been created as that part of that beedest wheel command. So here are the directories and files. So remember, we've only actually created two files so far. Hello World Py and setup Py. So everything else here was created by setup tools. So I have a few things here. It's created an egg info directory in our source directory. You'll want to get ignore this. I'll show you how to do that at the moment. This is horrible. I wish it didn't do this.  Then we have a build directory. So this is where setup tools kind of moved our files to in the process of building our wheel file. You will see the Hello World Py file in there. So again, validated that our code is actually going to be in our wheel. And then finally we've got the actual wheel file here that it's put in our disk directory. So that is our final distribution. So now we can install it locally. So this is just effectively testing our packaging. So it's not testing our code but it's testing our setup Py file. So here we are going to pip install and then with the minus E flag and the full stop period dot whatever you want to call it. This can be confusing to people if you haven't seen this before. Just out of interest, who hasn't seen this before? Yeah, I thought so. This is actually an essential command if you are building Python packages or rather they're essential flags. So the minus E normally when you install a Python package it installs it into your site packages folder inside your Python distribution. It copies the code into your Python distribution. We don't really want to do that. While we're working on our project we wanted to just work with the code that's in our source directory. So that's what minus E does. It essentially links to the code that you're working on instead of copying code into another location. So that means once we've installed this package we can continue to work with it, continue to run it, continue to write code against it without having these two copies of that code that is just going to cause us problems further down the line. The full stop at the end means install the package in the current directory. So it's looking at the setup Py file and so it's saying install this package by linking to the code that I'm working on. You run this every so often.  So bear in mind our code is under a source directory at the moment. So if we run Python in our current directory we can't import Hello World yet because it's not in our path. So let's, in theory, let's test it. So here we run Python, the REPL and then we do our from Hello World import say hello. Because we've just installed our code into our current virtual environment, this will work now. Even though our code is under the source directory, Python has been told where our code is by the setup Py file. So we can execute the say hello function, we can execute it by passing at the optional parameter. Everything works as we would hope. So that's, it's some rough testing, we'll get on to better testing at a moment but it's just a confirmation that our code is installing correctly. So at this point we have a working package with some useful code in it. So we could upload that to PyPI immediately but I would say that there's a few things that we really need to do before we get to that point. That's documentation and testing but also just a little bit of housekeeping which I'll run through now. So as I said there's some files created that you really don't want to add to your Git repository. So it's useful to have a Git ignore file. This website is fantastic. They make it easy to get hold of GitHub's standard Git ignore files that they publish for different language and operating system communities. So you would write Python in that textbox, hit create and it will just spit out a text file into the web browser that you can copy and paste into a .gitignore file. So now we're ignoring all the main files that Python creates.  If we're going to publish this code we also need a license. If we don't have a license we haven't given permission to people permission to run our code. They can look at it but they can't copy it or use it which is not greatly useful. So we need a license.txt file. And a good way to if you don't know the ins and outs of the different licenses and the restrictions and freedoms they grant the software that you're publishing, this website chooseallicense.com is incredibly useful. It essentially asks you lots of questions and then gives you your options and how they compare to each other. So it's a good way, it's a human way for non-legal people to understand the differences between different software licenses. We need to add some classifiers to our setup PY file so that people can find a project in PyPI by searching or filtering on common criteria. So here we say that this is Python 3 code. It runs under Python 3.6 and 3.7. We haven't really tested that yet but we know that it only runs under those versions of Python because there was an F string in the code as I pointed out. I chose the GPL v2 so put that in there. That was a bit of an arbitrary choice. These can all be looked up in this URL at the bottom.   Then you need some documentation. But before you write some documentation you need to work out what format you're going to write your documentation in. You basically have two choices at the moment. One is restructured text which is written in Python. It's used widely in the Python community. All of the Python core documentation is written in it. A whole bunch of the libraries you use have a written in restructured text. But it is a Python solution and if you're working on a project that has some Python code and maybe some Rust code or some C code or something like that, those people will probably not have encountered restructured text before but they will probably have encountered Markdown. Markdown is a valid choice. It is simpler but also less powerful. You're making some compromises here. Both of them allow you to use tools like Sphinx for restructured text or MakeDoc for Markdown to compile a directory of Markdown or rest files into a directory of documentation that's all linked together. Both of these are supported by Read the Docs. You can publish either of these documentation sites to Read the Docs and then not have to worry about hosting them yourself. Once we've decided and I've chosen Markdown again kind of arbitrarily, we need to write a Read Me. That's pretty much essential for any modern project. Here we have a title of the project. We have a small paragraph describing what the project does. We should have a section describing how to install the project with some sample command line code for pip-installing this project. We should have some sample code just to tell people how to use the useful code that we've published to PyPI. And then once we've written this, it's nice to have this also published on PyPI. So as well as publishing on, say, GitHub or GitLab or wherever you're publishing your code, it would be really nice if we could make this essentially the official description of our project. And we can do that. So this, again, this is even if you've published packages before and you used restructured text to write your Read Me, this is now a new feature in PyPI as of about a year ago. PyPI supports Markdown directly. So you don't need to convert your Markdown to restructured text before pushing it up to PyPI. So here we're taking advantage of the fact that setuppy file is code and not configuration by opening the Read Me file, reading in this block of Markdown. And then we apply that string to our setup call. So we use the long description parameter, just provide this string value that we put into a variable. And then very importantly, we need to tell PyPI this is Markdown and not restructured text, which we do by providing this MIME type as this content type parameter at the end. I wanted to talk about dependencies. I've cut this talk down a bit. So we won't actually show any code that uses blessings. But for example, if we use this terminal coloring library called blessings, this is how we would add it to our setuppy file. So we have an install requires parameter. It's a list of these specifiers that describe the library and the versions we're prepared to accept. I will talk a little bit more about those in a moment. If we change the library dependencies or anything else, as I said, we should run our pip install minus e.command again, just to reinstall the package and just make sure it actually pulls down the dependencies and that these things work together. And then we should run some tests. But we don't have tests and we shouldn't just keep on opening up the REPL and randomly calling functions to make sure that things work. I would recommend you write your tests with PyTest. PyTest is awesome. But in order to write tests with PyTest, again, we need more dependencies. But this time, we're not talking about a dependency of our library like blessings. So we're not saying this is needed to run. We're saying this is a development dependency. So this is something people need to install in order to develop code with our library. And in order to declare dev dependencies, I recommend you add them as extras into your setup py. But a lot of people here I suspect are using requirements.txt for this. If you have a setup py file, I would argue you do not need a requirements.txt. You can do all of this within Python standard packaging framework and you get some advantages. Because again, this is code, not configuration. So the way this works, it looks a little bit like our install requires, but it's got an extra layer of indirection. So you'll see that it's a dictionary rather than a list. But you still see that list in there as the first value. So the key is the name of your extra. So in this case, we're saying dev. We will tell people that they need to install the dev extras in order to work with our project. And then after that, it is just a list of dependencies. So in this case, we're saying py test above or equal to the value of 3.7. And then we can tell people how to use it. So again, we update the readme. We have a section saying if you would like to help develop Hello World, this is how you install the development dependency so that you can run the tests. And it looks very similar to before, but you'll see we have the word dev in square brackets afterwards. It's saying we're installing our current module with the dev extras. You may have used this with other packages, maybe not seen how that was specified. I stole this straight from Atters, which I think is why Hinnick is here. So yes, if we install the extras, you'll see that it installs a whole bunch of other stuff, basically dependencies for py test. So the difference between install requires and extras requires is that install requires is for production dependencies, things like flask, click, non-py, pandas, and the version should be as relaxed as they possibly can be. So you should be testing against multiple versions of each dependency, in this way you're not locking your users into a specific version of a shared dependency. So if both you and your user are using Atters, ideally you need an overlap there. So if you're all using version 3, they're using version 4, they're not going to be able to use your package unless it makes some changes. Extras require is different. It's for optional requirements for development or testing or whatever extra groups of extras you want to create. And the version should be, in my opinion, as specific as possible because you're trying to get your developers up and running as quickly as possible. And so creating an identical environment to yours and the other developers who have been working with the code is just going to make everybody's life easier rather than trying to debug like minor variations in your development dependencies. Requirements.txt still has a place, but I would argue it's for apps that you deploy onto machines that you control. So in this case you're pinning every single production requirement to a specific version so that you're producing a well-tested collection of code on a destination machine. So use fixed version numbers with the double equals operator and you use PIP-freeze to just spit out all of the things that are currently installed straight into your requirements.txt. So here we write some tests. I'm going to zoom through this a bit because I'm running slower than I would like. But yes, we run our code. Now we just need to run PyTest to actually test our code each time. It's much easier than actually executing the code by hand.  So now what we've done so far, this is what we've produced. We've got a license file, our readme file, setup file, source directory with our code and a test. You can obviously stick your tests in the test directory if you have more test files. It's good to distribute source distributions as well as binary distributions for various reasons. People can check the code before they run it. They may not have access to GitHub to access the code. They may just need to verify the code before they run it. When you run Estist against our setup Py file, we actually get some warnings saying it would like some more data. For some reason, Estist would really like to know the maintainer and maintainer email or the author email. So it's told us that. So we can just add those in. That's three lines. We add the URL of the project, a link to GitHub in this case, my name and my email address. Excuse me. So now we need to test that. Make sure that the source distribution contains all the files that we want it to. So it just when you run Estist, it just creates in this case a gzip table. And we can use the tar command to unzip that and have a look at the stuff inside. And when we have a look at it, we notice that it hasn't got our license TXT file or test hello world file. Ideally, our source distribution should contain everything that is in this snapshot of code. So everything we're distributing, everything that gets built into the binary distribution. In order to add those missing files into our source distribution, we need to write a manifest input file. They are fiddly and annoying. Fortunately, there's a tool called check manifest that does pretty much all of this for us, or at least we'll get us started quickly. So you can pip install it, you can add it to your development dependencies if you like. You run it for the first time with this create flag, and then it will create you a manifest.in. I recommend having a look at it. It's just things like includes and excludes lines for various files that it's found in the project that it tries to make sure that everything you have in Git ends up in your source distribution. So it's finding these files and adding them to the manifest input file. So then if we build our source distribution again, we can unzip it, and then we see that now, just out of the box, the check manifest has created a manifest file that includes the files that we're missing. So now let's publish it. It's good to publish earlier rather than later. If you try to perfect everything, you will really never publish the package. So as soon as at the point you have something useful, not necessarily perfect, try and get it up. Apart from anything else, it will register your package name on PyPI to your project. So you're not letting somebody else just kind of come in in the months while you're working on your project. You used to be able to register your project before you uploaded code. Now you need to actually upload the code in order to register a name. So here we run a setup Py with the bdisk wheel and the sdisk command. And in our disk directory, we will now have our wheel file and our source distribution. In order to push to PyPI, you need to use twine for various reasons. It separates the build step from the upload step, which means that you can do these manual checks of your distribution files before you upload to PyPI. Otherwise it's a single command to kind of build and push up your code. If you get it wrong, it's going to mess things up for you. So here we install twine. We use the twine upload command. It also uses HTTPS, whereas for a while, PIP didn't. So it's safer. Sorry, setup tools didn't. If you get to PyPI, the website, quickly enough, you will see the name of your project on the home page as the most recently updated package. And that's kind of cool. If you click on it, you will then get to the project page. You can see our readme file is essentially duplicated here. There's a GitHub link that I've just cut off at the bottom. I had to change the name of the project, by the way, because there is a Hello World package on PyPI. Obviously somebody has done that. So there's still some more stuff that we need to do. I would recommend using TOX. I really am running out of time, so I apologize for running through these. I recommend using TOX for testing against different distributions of Python and different versions of the libraries that you depend on. Here we're just testing against Python 3.6, 3.7. You install TOX. You have that TOX configuration file. It spits out loads of output when you run TOX.  Here's why we use the source directory. So our root directory is the directory I've been working in. If our code was in this directory, if we import Hello World while running the tests, it will run the code in our source directory, sorry, in our current directory. But we don't want it to do that. We want it to test installing the package and using the code from there. By having a source directory, you are forcing it to use the version that was just installed into the virtual environment. You should also build on test machines. In the past, I've used Travis for this. I am probably moving my stuff to Azure Pipelines, depending on when Hinnick gets his stuff stabilized. Yes, I won't talk about that anymore. For extra credit, you can add badges to your readme, for code coverage, for quality metrics. You can manage versions with bump version. That's quite nice. You can test on different operating systems. You can write more documentation. You can always write more documentation and tests. You can add a contributed section to your readme. You can implement a code of conduct. There's lots that you can do, but I recommend that you don't do any of the stuff that I've described in this talk. So there's a project called Cookiecutter that generates sets of files from templates and people have already created template projects for PyPI, for Python projects. So if you install Cookiecutter and then you run this command to download Yonals, there's a few of them out there. I quite like Yonals. It's similar to my own way of thinking of these things. This Cookiecutter library, it will then, it will download the template from GitHub. It will ask you lots of questions because it's much more flexible than all the, I've given you one option for each step. He offers you lots of options, different testing libraries and things like that. And then, at the end of it, you're done. In theory, you will probably have to go and tweak some of these files because they won't be quite the way you want, but it took me five minutes to get up and running using this process. And then it created all of this. So you will recognize some of the stuff in here from the tutorial that we've been through. There is extra stuff in there. There is a Sphinx directory of documentation with just boilerplate documentation in there at the moment, but just waiting for you to fill it out. You copy in your code and then you're done. So that took me about five minutes. Could have cut this talk down to the last two slides if I'd wanted instead of wasting all of your time for half an hour. But hopefully this gives you an overview of good packaging practice and all the things that you need to do to kind of build a well-rounded package. There's obviously different directions you can move in, but this is a really good core understanding of the things you should do for a professionally released package. There are other projects for distributing libraries these days that are very interesting, but don't use setup PY or use it in different ways. I would really recommend having a look at them if you're struggling with setup PY. Poetry is getting a lot of mindshare at the moment. I haven't really used them, so I can't really recommend them. I'm trying to push current most common best practice. If you are interested in the slides or the code for this talk, they are available on this bit.ly link. Follow me on Twitter. If you have any questions, feel free to grab me at the conference, come to the next MoBooth, tweet at me. Preferably not abuse. But thank you very much for coming to my talk. Well, actually, we have time for one question. OK, go on. We have less than 60 seconds. So very quick question, anybody? Otherwise, I will ask you to just put the thing about cookie cutter, the slide with cookie cutter. Yeah, I can do that. That's a good kind of question. So is it which slide was it? You wanted this one? Yeah, yeah, yeah. Yeah, that's it. So I never used cookie cutter before? It's awesome. It's really easy to fork other people's templates as well.  It's that simple. It's just a directory of Ginger2Fights. It's seriously easy. If you look for... All right, we can start. Well, we have Christian here. And he is going to tell us about C++ with Python. And I'm unleashing the power of C++ in Python. Let's welcome Christian. Hello, everyone. This is one room more that I was expecting for, because I know that there's also amazing talks that I would like to go to at this moment. So if you want, we can all go to the other talks or we can stay here for some fun with C++, of course. And I know it's just the last talk from all the tracks. So bear with me. There will be no weird things here. And we will not like be trying to understand obfuscated C++ or something else. So it's a really light talk. With advanced topics. So let's go for it. So as you heard, my name is Christian. Currently, I'm working as a software engineer in the Acute Company, which one of the companies that support the Acute Project. Maybe you heard about it. Later, I will have one slide to explain the motivation behind this talk and why I'm talking about C++ on Python. So first of all, don't worry about the examples or the slides or whatever. Just go to that GitHub repository. There is a link to the slides. And you can get all the source codes. Oh, my God, I feel like a star. Everyone taking pictures of it. Stop it. As you can check it out. And at the end of the talk, also, is my GitHub username. So you can check it out. It's called Unleached CBP. OK. So first of all, the Acute Project in general is a C++ framework, huge framework. And with starting to do some Python stuff, you need to have the mandatory comparison between two languages. First of all, we know that both languages are general purpose. Also, you have multi-paradigm. You can do many things with them.  Dynamically typed, vertically typed, compile, interpret. And then memory management and about also code reliability. So I know this is kind of if we have just raise your hand, who is currently writing C or C++ code? OK, good. So I feel your pain too. So I know that sometimes C++ could be complicated, but it's just want to show you that it's not and you can even make things in Python better. So first of all, everyone knows that Python is beautiful. I remember the first time that I typed that on a console when I was studying computer science and I was, whoa, everything works. But if you think about it, I mean, C++ is not so different, right? I mean, you can write something like maybe you need to run an external compiler or something, but you achieve the same thing, right? So, OK. After all, C++ is simple. It's not. Because then you have things like meta-programming and you start, you know, templates over templates. And this is one of the reasons that people get scared of C++. But C++ is not so ugly and this is some extreme cases of people with a lot of time, a lot of effort and try to do these complicated things like compile time, if. But let's go about one of the goodies, a couple of goodies that C++ and the latest standards being 11 on has. I mean, if you're familiar with C++, now there is this amazing auto-type that kind of detects the variable that you have, which is kind of a similar, like a more dynamic language, but not. You can even use some functions to get the declarative time of a different variable to declare another one and stuff. And then again, we have the for loops that with the time it has been improved. I mean, this is kind of the more dumb, old version that we have in C++ to kind of like go in a vector. I know that you can do also with an iterator too, but it's kind of like going element by element, but it's too complicated. So then you can do more fun things like this. And if you remember the other one, then you can kind of go like, which is not so complicated to understand. Also, if you're a fan of Python lambdas, you can also do it in C++ with the latest standards and so on and so forth. And you can have this for each handling a nice lambda there to just sum it up some values. But the most interesting things about C++ are coming in my opinion in C++ 20, which is, I don't know, I have this relationship with love and hate with C++ 20. There are some things that are really nice and some things that I have no idea why people is doing it. But one of the things that I like is this one. So you have this amount, sorry, this type of ranges that you can use now. And if you see the four, the kind of like the type of the four there is kind of similar that you can have there. So after all, I mean, it's not so crazy different, right? The same with a more example. I mean, I know that this mod way, maybe is the first line that is commented out, but you can write the function, maybe like the second line that you see there, which is also quite similar what you can achieve in C++ 20. So after all, I mean, it's just adding some semicolons and yet, right? So the idea is that now it's not about like, which language is best, but how to make both languages to improve each other and try to collaborate in a more efficient way. So I want to propose now a new language that is, no, no, it's not, but I'll just talk to extending Python with C++. And for this, we will go through a couple of examples, really simple ones. And the first of all, who here didn't know before the conference that Python was written in C? We had some, okay, we have some people, okay. So it is something that also was kind of shocking to me because I thought that it was some black magic assembly stuff, but it was written in C. So if you learn some C, you could understand it. And then you can understand other things like this joke, for example. I know that is really bad, but it's the only joke that I have on the slides, but so I'm really sorry, but I needed to do it. So let's take a look at how we can create an amazing module based in pure C Python. And okay, let's go for it. So the first thing that you need to know is that you just need to see a C file. And we will go through these examples with the most simple thing that I would think there was a hello world function that just returns the char star or string, whatever. So I hope that everyone can read. If you don't know C or C++, it's kind of that you get the idea. It's kind of a function declaration that returns some message, which is hello, EuroPython 2019, okay. So for building a C++, I will just sum out. Don't be afraid just to show you. So that's all the code that we required to create a new Python module written in C Python, which one function that is just printing hello world. It's not so scary, right?  You just copy some stuff and it works. So if you are brave enough after this talk, just go to the C Python directory and play with it. And maybe you can write other sophisticated models with it. So this is a simple case, right? And this is just one example, one simple function and we have this. So what's the motivation behind this Qt thing? So Qt is just a C++ framework that is like huge and one of the main functionalities was to offer the way of developing user interface, graphical user interfaces for people. And also Qt implements many of the things that we have for free in Python in C++, which is like a lot of abstractions for different classes to interact with more, for databases or maybe doing command line or scripting alike in C++. And even other advanced things that different way of creating user interfaces, actions, notification, threats, all these things. So they are providing a lot of goodies to the C++ world. And at some point, the project was, but you know what, which I mean, this thing need to be maybe available in other languages. So people started to wonder about Python. So maybe you are aware, there is already a set of binding which is really old, it's called PyQt. And this was developed by a different company, some people doing a lot of work there and this was fantastic. And in the Qt project, they wanted to kind of have an official adoption of these things. So they decided maybe we can create a new set of bindings and you know, just put it there and see it's an open market. So people can decide which to choose. At the moment, they are at the same level, one is really old and there's a lot of examples and tutorials. But the Qt project at that point had a couple of options to do this with this huge C++ framework. So they could write raw C Python, they could write a SWEAK, I mean maybe you heard about SWEAK or they could use boost Python. So if you take a look at the SWEAK implementation, so with SWEAK, we just, just for you to believe me, we have here our difficult function to understand. And the only things that we need to do for the SWEAK is just to create an interface. So this interface is in an I file but also nothing really scary or something at the moment. So we have a couple of instructions to build it.  And then we have the message, nothing too fancy. With boost Python, it's kind of a similar story. We go there, again, we have the simple CBP file, with our function there and then we just need to define boost Python module, the name, the name space and then we define the function. Nothing too scary at the moment, right? So this was looking at a really nice solution, right? I mean, we were achieving the same thing but the problem lied that many things that we do in C++ need to be specially treated inside Python. For example, ownership of objects. If you are wrapping an interface that is in C++, who owns the objects? Some cases will be Python, some cases will be C++. So you need to deal with all these things, okay? So the option that at that time the developer had was, okay, this is just one of the generator and we can maybe modify the wrapper generated code. So let's take a look of the code that SWEAK generates. So just for you to have an idea. So this is kind of the code that generates and I will start to go down. We are in 2%, 3%. Okay, we'll just page down, four, five, seven, two. So I understand it. It's a little bit too much with this small function, right? So that, okay, that's all. And there is kind of a motivation to say, okay, I know that they need to set up many things to get for granted and to automate many process and it's a really smart solution. But if you want to modify this file, it will be embeddable. I mean, you cannot do it. So there was a lot of motivation behind this. I see Python and SWEAK and Boost Python. I don't have the source code from the Boost Python here, but the shared library is roughly the same size. So you can imagine that there are a lot of black magic there. So what did they say? Okay, they started the development of this new tool based in Boost at the moment. They said, no, it's too heavy. Let's write our own thing. Okay, everything was released properly. Then there was the project to continue the development and the good news was that last year officially it was released this new set of bindings of Qt in Python and then their name of a new project was called Qt for Python. So maybe you heard about this or PySide tool. It was all this story behind. But okay, this is just a story, but what was the important part, at least in my opinion? How do we do it? So this tool that you see here in the center called Givoken2 is kind of like the response for writing our own code generator tool to expose all this huge C++ framework to Python. So there is a module inside that kind of extracts all the API information from Qt based in Clang. Of course, if you want to do smart things in C++, you need to use Clang. And then we have a support type system which is nothing else than XML file. Then then you get, wait, something is being weird, an XML file where you can define all these things that I told you about ownership or for example, what do we do if a function has a void star argument in Python? We need to have a special or type or treatment or do some casting or something around. So this tool graphs this type system, the information from the framework and generates some wrapper that the one that you saw from Swig, but of course more reduced and it makes more sense and it's more clean, in my opinion. And then with this, we can just compile it and have the same Python module that we have. So this tool is called Givoken, the documentation is there and I don't know what is happening, I haven't been doing anything and the slides are coming, okay. So the Japanese Ganges doesn't mean anything if we have some Japanese speaker there here, it's just three words that make no sense, but let's take a look of the Givoken thing. Okay, so again, we will go first for you to believe me that we have here the implementation and we are like cheating a little bit because of course we are working with strings from the standard library. Then we define a complex header for this, which is just that. And for this type system that I just told you, it's nothing else than this. So we've had TTML, we said this would be a package called simple, it will have a primitive type, there's a string from standard library and a hello function. After all the compiling and stuff, we will get something like this. Let's go to build. And it's inside simple and here you have the module wrapper. I will zoom out just for you to show you that I'm not lying. It's long, but it's not so long as the other one. So here you have it, I don't expect to you to read the code, I just want to show you the magnitude of the code. So at least this has been code automatically generated, calling this C++ function and exposing everything with C Python to be able to use it from Python. So it's way shorter than the option that we had. Of course this translates into having a more lightweight shared libraries and you can achieve the same things. So there are other nice options out there and for this I kind of tend to recommend people to take a look of all the solutions that you have out there because it's unfair to say, yeah, this is the best solution, no it's not. I mean there are many things that you can complement to each other. I don't know if you have the chance and or maybe know one of these ones. The last one for example is the one that the other set of binding called PyQt uses which is called SIP, PyBind 11. It also is a really nice project that appeared in the, I think in a couple of years ago even I think at two Euro-Python's ago there was also a talk about PyBind 11. So let's take a look of like how do you achieve the same things with the other options? I think that I am good with the time at the moment. So this is the case of PyBind 11. So let's open again the file. If you see the motivation here is clearly from Boost Python. I mean it's again a kind of a macro that kind of defines a module. Then you have the definition of the function, some documentation and so on and so forth. And then you can do the same thing. I mean after you compile it and everything you have your simple main that you can achieve the same. So it's kind of like same idea as Boost Python but they are doing way more things and there is a lot of nice support there that I encourage you to check it out. CFFI, well this is again not really fair comparison because CFFI, we had some talks already that we explained about this thing. It's not kind of like generating code but it's just kind of loading something. So we can have, this is the one here. This is the code that is being generated. Yes, so we go to the simple build and then you have like inline raw string that contains the function that we want to expose and then we just compile this thing in some share library that we can easily load from Python. So if you check here for example, the main is the same thing that we were seeing in the other examples. Just calling this nice function and in this case we are casting it to string and so on and so forth but it's kind of the same idea but again I mean it's not like you can write inline code or kind of read lots of C++ code to kind of expose it in this way. The other option that I had there, ah, okay. CFFI is kind of focused on C when they support C89 and I don't remember which one, the other standard but for playing with C++ you have a similar idea which is CBPYY, kind of fine right, CBPYY. And then it's kind of the same idea. So you declare everything like in a string and then they have this declaration that you can use this from the GBL. Again, same idea and nothing too scary. And the last one is kind of similar. It was a zip that I show you, the one that is using the PyCute bindings. I will just show you, this is just there. So yeah, here we have the simple, again same idea but the only difference that they require to define a zip file and it's nothing like the other set this. I mean it's also quite simple. I mean you just need to define a module and then you have some include and then the signature of the function. So there are many options out there to achieve the same thing, right? But what's the idea of doing this, right? I have been having some conversation with people sometimes that they say, ah, yeah, but I mean I use Python for everything. I mean you don't need to C++ and they say, okay, what do you use? No, I do everything with numpy because it's amazing and it's fast and it's Python, you know?  So okay, there's even some people that is not aware that many of the popular libraries out there are using C++ or C. So in this case you have a case of numpy, I just downloaded the source code. The first line is all the Python files that you have that are not test and then you have the C files there which is 96, which is still a lot of things that they are doing and if you want to maybe refer to a more modern module, the case of PyTorch is a little bit more extreme then if you look there, we have, no, this was, this is. So here we have 547 C++ files inside the PyTorch because of course it's based in Torch and Torch is C++ so everything is C++ inside. So it's kind of a nice motivation of using all these tools to start to write things to improve the Python. We are all here, if we know C or C++, we kind of have some responsibility in our hands to improve things and one of the examples that just out of curiosity and please don't blame me about the things that I will show you is that simple case, I was helping someone that I was listing some files in Python and getting all different absolute path and what do you use there? Glob, right, when you use Glob or if you are more like up-to-date person you use the bat leaf and then also you have the Glob access there. So for this, you know the deal, I mean writing Glob is, things are kind of simple. This is a hard coded thing just to play with the recursion thing but you know import Glob and then you need to double stars there and specify if it's recursive, no. At the same way with bat leaf is kind of the same idea. And then I thought, let's look at the implementation and see if we can kind of do something smarter in C++. So the first thing that came to my mind that in C++ 17, maybe you know there is a new adoption in the C++ standard which is the module called file system. This is based in the boosts file system.  So again, same idea, I will just replace all the simple and hello and the only difference is this. If there is any CPython core developer in the audience please forgive my CPython but this is just to show how simple we can achieve things. Of course it's a and save. There's memory leaks there because when you append that increase the ref counts and I am not taking care of anything but just taking one argument which is the recursive to see true or false and create an empty list and then just doing some dumb appends. So the magic here from the C++ site is that I am using the file system module and I am using C++ 17 and there is luckily some directory iterator that you can kind of do recursively or not and that's it. I mean, if you don't know CPython you just need to, this is just a function that will take here some arguments. We create an empty list and then if it's recursive enough we are appending, well, you know how append works some stuff and then we are returning this list. Nothing else. So I thought, okay, let's see how this thing was working and then I wrote a really, really simple batch script because yeah, I was growing up with bash and I thought I would just have this scenario when I have 1,000 directories with 1,000 files inside of each empty files and just to list them. So I just create a shell script to measure this as you can see here, the non-recursive option which is just listing the directories inside this fake environment is 0.05. I was expecting glove to take so long but I think it should be something about 20 something seconds. I mean, in the meantime, I can tell you that I was afraid that maybe I was using user being time and maybe it's not the proper way of doing it. So okay, there you have it. Recursive 33 seconds. We're talking about all these files. Then I tried a bad leave. Again, it was a little bit more and it was slower than the Glob file than the other cases, the recursive way. It will be roughly, I guess at the same if I'm not wrong, I should have have this prepared. Okay, there you have it, 20 seconds. And then the fast glove implementation that I have there, it's less than a second. I mean, I know I'm not taking care of cache or the, I don't know, releasing the GIL to use parallel computer or something fancy, just the simplest thing that you can think. And then you have it, I mean it's, and then I thought maybe it's the same thing I am doing it wrong. So let's do the same performance in Python with the time module or something and after all the tries it was more or less the same result and it's not like I want to say, yeah, this should be the new Glob but this is how easy you can improve things there. And maybe you are thinking in the next numpy, the next pandas, the next PyTorch or something like that. Well, I will not wait for the results there but it's roughly the same, believe me. So yeah, this is a summary. It's okay if you cannot read everything because you can check the slides afterwards about the version that you can use, the licenses, the compatibility with Python. Here I just want to highlight Chiboken, the thing that I am working with and also SIP because there is something that is called stable ABI. Maybe you heard about it? Yes, yes, stable ABI. Good, so this is just for developers to release wheels that are compatible with Python 3.5 onwards. And I don't need to have different wheels with different Python versions. So this is really tricky, it's just the way that you create objects that are more dynamic way but it's really hard and it's implemented in those two options. So there you can have information from the Python project. You can find me here also, you can check my social networks and all the information and you can just type make. I add some make files there just for you to know the process of building all these wrappers so you can start playing around today about it. And just as a PSA that it's always good to support with your local groups. So if you, at any moment you come to Berlin, I mean we have, I think, one of the most amazing Python communities out there. We have PyLadies, Python users Berlin, PyBerlin and PyData Berlin. So that's it. Thank you very much. All right, thank you very much. We have time for some questions. We have actually five minutes, so a couple of questions for sure. And if you don't like your voice on a microphone, maybe you can find me outside. I will be here until Friday or we can hang after a couple of beer, we can discuss the truth behind C++. So if you have questions, yes. Did you ever look into performance, overhead differences between those options? No, I haven't and I wanted to, but then I thought, that's not a half an hour talk. So I was really considering for the meetups or conference to kind of do this kind of thing because I want to measure code length performance, which is also critical. I mean, I have noticed some stuff different between the SIP and the Shiboken, for example, that there was an issue that Shiboken was way slower because we were using lists in C++ and the SIP was using verctors and then we have, for example, in some tables, or cases like this, they were kind of different. But yeah, it's a good question and I will try to maybe next year, I will have one performance. Thank you, welcome. Any more questions? Oh, excellent. You can shout if you want. I'm just going to take it so, too, one thing at a time and pause. Yes, lately there was something that fixed that because I wanted to implement breaking the QTBI, having, for example, for Qt settings to have explicit cast in types and I needed to do the name arguments. So now it's implemented and it's out there, so you can do it and now there's a new notation, which is the at, so you use the at between the name that you want to use and then you have nine arguments and you can parse it like a normal dictionary for the arcs and the, so yeah. You can ask me to leave it to you and I can show you how to do it. Okay, any more questions? Do you hear me? Yeah. Yes. Does the Shiboken uses some, does it have some CMake integration? Yes. It's CMake. It's CMake and you can make a C++ project and use CMake integration in your project. Okay. Yes. And does it, for example, you want to override LAN or some other Python features? Can you override it in XML file for bindings? Can you name one, I mean the only override that came to my mind is that for example you can kind of like remove functions and replace it with a whole new Python equivalent. Okay. So signature-wise or functions. We can remove arguments sometimes. Yeah, but items like square brackets, override operators. Yes, I mean we have some special treatment for a few operators. I don't know how much you can modify this thing but at least I know that you can manually modify for example the lower, lower operator in C++ and in Python to do different things. So you kind of like override the Python's default stuff. Yeah, so for example I have C++ method size and the other one is operator for accessing it and I want in Python to just use square brackets for operating. As long as you define this operator inside the type of the available it will be possible because underneath it will call this specific rewriting that you have. Okay, thank you. You're welcome. Any other question? Any other question? I will ask you a question then. Okay. So how is it to wrap a C++ class? It's kind of the same thing that you saw there. You need to just, the class will be an object so you declare a new object and then inside you have any function that you want to modify. If you don't want to modify it you just close the tag and that will automatically go to your header, see the class, take all the signature and expose everything. If everything is normal in the sense of like there is no void star or weirds, kind of like the pointers working around, so yeah. And can you then subclass that class from within Python as you would normally? Yes, totally because you are exposing some new type in Python. So for example, the simple things that you can have in Qt is a Q-widget and then this is C++, you expose the Python and the recommended way of doing it is to use this as a meta class for your new class in Python that is called MyWidget or something like that. So you can do it. Oh, very nice. Any question? If not, we can thank the speaker again.


Because some publications conflate the terms reflexivity and positionality somewhat, the relationship between reflexivity and positionality is often poorly understood. However, it may help to think of reflexivity as a private process whereas positionality is the public end result of that process. Reflexivity then is you as a researcher making sense of who you are, of what your beliefs are and what therefore you bring to your research. In the positives as well as the negatives. Yes, biases and assumptions play an important role here but reflexivity is also about recognizing your strengths such as your subject expertise, your professional skills and knowledge and or your lived experience. This sense making happens in your private sphere and most of us engage in research journaling activities for this reflexivity work. When you do this private reflexivity work, you will come to a point where you say to yourself, right, this is who I am, this is what I have brought to my research and this is how my being me has shaped my research and you will make a note of that in a one or two paragraph summary. In short, you have achieved some sort of endpoint. This endpoint is where the private reflexivity work turns into public positionality and the one or two paragraph summary becomes your positionality statement. Now naturally as human beings we consistently develop. We are impacted by our life experiences by conversations we have or over here by the relationships we build in our personal and professional lives. So with that regular identity work at a personal and professional level, our assumptions and beliefs will also change. In addition, the ideas and perception we bring to one research project may not be exactly the same ones we bring to another research project. Depending on the research questions, for example, we may select participatory and egalitarian approaches to data collection in one research whereas in another project we use surveys. Our underlying principles and foundational thoughts are therefore different even though we are still one and the same researcher at that particular point in time. The result of this is that the positionality statement will be different for those two projects. So although positionality is sort of an endpoint to the reflexivity process that endpoint is not permanently fixed or set in stone and many researchers will have written different versions of positionality statements to make them truly relevant for the respective research process on hand. In effect it is this malability of positionality that adds to the confusion around reflexivity and positionality and that leads to the conflation of the terms. I always suggest that reflexivity is an ongoing process in private that is very comprehensive and involves the whole of who we are as researchers whereas positionality is the public facing part that matters for the research we are currently reporting on.


Peter, it's my understanding that the unique uniqueness of SilverBullet is about the processing. Talk to us about this. We made a, hey, by the way, good morning, Tracy and Highclint. We made a production decision in May of 2020 that we could get this into production without a PEA, without a feasibility study. We don't need a resource estimate, just go do it. And one of the reasons we did that is we have John Carter as our CEO. John is a process guy. He has built over 100 mils in processing facilities around the world. So we've been able to take shortcuts that were efficient to get a mil in production. In September of 2021, that was an empty field. In September of 2022, there is a bull mill producing Silver in that field. And to a large extent, that's John Carter. Speed to production is part of your uniqueness. Yes. Absolutely. That means an efficient use of capital. We didn't have to go raise $100 million to get in production. That mill cost us less than $3 million Canadian. And it is a fully functional 125 tons per day mill. And it's working. I tell people this and they look at me like, no, less than $3 million to buy and build the mill. And it's pushing out 125 tons or chewing through 125 tons of ore a day. So what kind of revenue are we looking at? Because investors out there going, oh, I can barely conceive of this particular plan of action where we're not listening to 15 years of we're exploring and we're drilling and we're exploring and we're drilling. We explored, we found the Silver and we are producing. Did I hear you correct? Even better, we didn't really explore the property. The family that we're working with in Globe, Arizona has known about this asset since around 1980. The Murphy family is wonderful. There's cousins, there's nephews, there's uncles, there's aunts, and they've all worked the property. They all know it. We're looking at a two-mile-long vein that expresses itself at surface, then it goes into an adit that the old-timers chased, then it comes out again. So the Murphy family knowledge has been wonderful. We have not had to waste money on drilling. Drilling is a really, really expensive test theory. Maybe I think there's something there. I don't know. Let's drill it. In Northern Ontario, it's currently about $200 a meter to drill a hole. That's an expensive testing of a thesis. So down in Arizona, we know where the vein is. You can stand at our adit and look down the hill.  And on our Twitter feed, I publish pictures of this and a video. You can follow the vein. We have not had to drill. Drilling is expensive. All we've done is follow the vein. So at the Buckeye Silver Mine, we've pulled ore. We process the low-grade material to get the mill working correctly. And as of last week, the mill is working perfectly. So we're processing the higher-grade material now, and we're going to generate revenue and cash flow. So based on this kind of speed to production, can you tell us, Peter, what we as shareholders should anticipate in the upcoming quarter or two? Sure. I meet with the CFO on a daily basis to talk about what we can disclose. Without a PEA, without a resource estimate, we have to be very careful under 43-101 to make sure we don't say anything that we're not supposed to say. We can only disclose things that have actually happened. So we're going to wait for a couple of weeks to produce so we know braid, we know volume. We've announced that we've had our first purchase order for 50 kilograms, which is about 1,800 ounces, which is about 30,000 USD, which is not a huge amount of money, but it's a sample run from a purchaser in Europe who has put up its hand and said, we will buy everything that you produce. If you make it, we will buy it. Now it'd be foolish for us to have only one purchaser, but that's the kind of demand that we have for a silver. So as long as we can make it, we're going to have people buying it, and we will report that as soon as we can. I know that's a bit of a vague answer, but it's the best one I have right now.  So I recommend for anybody interested in Silver Bullet, follow Peter Clausi on Twitter. Peter, thank you for your update today. And for more information, please go to the Silver Bullet website. Thank you. Thank you, Tracy. Always nice to see you.


Get these speaker notes up. All right. Hi. Yeah, like Liam said, my name is Jordan. I Come to you from Colorado in the US My daytime job I work in fintech But I don't use wise web assembly there. We all of my experience has really come from curiosity we're going in and Yeah, there's the big disclaimer. I've never done this before so Prepare to laugh at me. It's cool However, I did do that for a decade. So I'm pretty confident myself So if you need tips on parking a 35,000 ton ship, I can do that This is much more intimidating though. So I appreciate you all and bear with me The story I'm going to share with you all day is really a story about how accepting this community has been how it's been to Learn web assembly not from a day-to-day job But really going in the docks reading the code and then hopefully building an application with it that actually works Here's my rule resume I'm going to circle to a Lot of my frustration and I decided to share this with y'all because a lot of my frustration actually started when I was more in the cybersecurity field a Lot of the a lot of the work we did was you pull data out of the sim you analyze the data You try and find the outliers you shingle it you try and do all the stuff But after doing it for almost five six years I found out that me and my Tier one tier two analysts we had scripts that we ran we emailed or select each other those scripts I might change something they might change something ultimately the scripts diverged and Sometimes they got stuck in source code management sometimes they didn't and It got extremely hard to to know like what the real truth was and that's kind of where it comes in what to trust And how if I must have here the next job I got was in the Kubernetes space Which eventually land me as a go developer which I do today, and I love a lot so Some of the challenges that I've met Trying to introduce this new technology, and we've all been there Alpha beta libraries, you know things at that level they break. It's okay. That's what we expect However, it's really hard to get buy-in from leadership when I said hey, this is worth the time pay my salary I promise you we'll get something on this It's gonna break and like well. We're not there yet And that's kind of and then those are a lot of things I've run into Documentation the one of the hardest things I've been is this this ecosystems primarily in rust I don't speak rust. I don't understand rust. It's very much over my head. I do go But I spent a lot of my time reading rust code and trying to port it over and the real way I've learned is I've taken a lot of rust code ported it to go We'll never go anywhere pun not intended But that's how I learn But then I had my co-workers. I also have to motivate if I want to get leadership on board Maybe I need like a cadre of co-workers behind me. How do I motivate them like team? There's this thing. It's coming It'll board. It'll be awesome But I can't really convince a lot of them to spend their free time learning it because you know family everyone has their reasons But like family other obligations. It's hard to get that by in I Have them All right, so what will we be talking about today? We're gonna be talking about all these things in the terms of like what they mean to me What do they what does zero trust mean? What is secure software to me? How does web assembly help and then we're gonna get into wasm cloud Which is really how I cut my teeth on web assembly how I learned it So I use it and quite frankly the experience has been Really great with some you know bumps along the way, but they have a team behind them that helps Bar nine hands down anytime of day and they've been pretty amazing. They're all sitting over here if y'all want to meet them And then we're gonna wrap in tail scale and wire guard for fun really You'll see my stack here in a minute and you'll understand why and then can we do this with the role of application and Spoiler we can So again, what is secure software? This is secure software to me as it relates to the application. I'm gonna show you here in a minute So a lot of people talk about sandboxing today one of my favorite things about web assembly as You put code in the sandbox if it's not allowed outside the sandbox It doesn't go outside the sandbox and that's really powerful and we'll see a short demo of that in a minute Then can we distribute it? My first few god years in kubernetes Just trying to understand all the intricate parts of that because I came in in like 2018 kubernetes I wasn't early all the pieces all the moving parts. It was mind-blowing being an early being early to web assembly and early these frameworks has really allowed me the time to go slow and understand where they're coming, you know what they're doing and Specifically distributed framework in wasm cloud. I've had a lot of opportunity to really take the time to understand it That's not really secure software because I wrote it, but I wanted to put a dog on there All right, so then for my requirement a piece of secure software needs to be needs to have access Authentication and authorization. We're gonna really lean on gnats and tell scale for that and Then obviously at the high level we're gonna wrap it with TLS But what you're gonna what you're gonna witness in this is what I'm gonna write is About 20 lines, you know 20 lines of code plus the front end the front end doesn't count But it's it's not much because I'm really gonna lean on these pioneers in the space to to empower me All right, so these are the textbook definitions of zero trust and what it means I read them all I distilled it to what I could and Assented and I was sitting in our the wasm cloud slack channel one day when one of my co-worker Z Said this and I finally realized yeah, that's what I agree and zero trust is not about mistrust it's actually about segmenting trust and That really opened my eyes and provided me with like I see a pathway I now see how WebAssembly wasm cloud and these other pieces will really Tie this together. It's not that I don't trust any one of them or don't trust this. It's that Security is an onion you have to wrap the onion as many layers as you can Semaining trust is a way to wrap that onion all right so this is straight from WebAssembly's website, so I don't need to read it to you but The the feature I'm really gonna lean on in this demonstration is the sandboxing We're gonna look at this piece of code so this piece of code has two parts My boss said you need to write the best hello world app in the world and I did I wrapped it in pink and then Someone came along the way and decided I'm going to Hijack your code. You're not gonna see it because you're working too hard it slips through the You know code review and we're gonna we're gonna hijack your application So over here we have the exact same as code segment running And I don't know why the gifts are so slow. I apologize But we're gonna run it straight and then we're gonna compile it to wazzy and run it with wasm time And you very much see that over there Not only did the Xfill server which is this bottom half the screen get the data, you know We can also see at the top Then you know the the request was successful over here. I'm actually not printing the error We still get our business logic of hello world But if I were to print that error what you would see is you're you know, you do not have access to you Do not have authorization to do that You know Perform this I should have printed up there. You can't do that Which is really powerful because essentially at this point. We're running a Segment of code that was hijacked, but it's stuck in the sandbox and can't get out So moving on to the next Lego block of wasm cloud Now I need to distribute my app. I want it portable Polyglot polyglot something we'll see in a minute. Kelsey brought it up earlier if everyone if we need 50 postgres drivers How annoying that being how how likely are we to bring in you know You know Attract all these people we're actually gonna see that in wasm cloud. It's written once it's gonna be read us not Postgres, but it's written once it's written in rust It works. I don't have to use it I'm gonna do everything else and go and we're just going to interact via the RPC with this You know reddest driver That's an entire actor. So that is what business logic looks like it takes in an HTTP request It does not care from what I can have an HTTP server written and go I can have it in zig I can have it written in rust it doesn't care it takes the request It performs your business logic, and then it puts it back on the RPC That's really powerful to me.  You know database drivers And it equates the hundreds a line of code that don't really matter to me when Ironically enough, I'm writing one H. You know API endpoint that has like seven codes seven lines of code And the whole project has 300 lines of code. It's just maddening so While well it was some club does all these pieces. We're really focused it on on those four so Sign modules so one of the awesome things I Love about this platform is Once you compile your web assembly module down right tiny go rust whatever you want to do go soon You have this web assembly module you can run in wasm time You cannot take that way saying web assembly module and run in wasm cloud and the reason being it only invokes Signed modules so right out of the box. I know that without proper access to a key set This module that I'm running can't actually run And what you're gonna see is actually two keys an account key that says hey This person or this organization they sign this so if you were to look at for example the wasm cloud repo they have a whole you know list of Supported actors supportive providers and you can Guarantee that that team wrote that and provide and publish them because that key is also published and you can compare them And then we have a module key Which says this module in a succession so version one version two version three is the same module So they can't for example take this echo actor and Just slip a new vert you know a new You know new business like same echo actor, but it does it in a different way No, if you don't want to do that we check the module key. It's always that lineage of model and then Not only do we get this the power of the sandbox from wasm time or you know the wasm runtime We also get with a second layer of of capability control security in Wasm cloud because what they're gonna say is when you're signing it you sign it with the contract That it's allowed to do so for example here this actor can Take requests and that's it. It cannot use that same connection to you know Require you know Instigator requests from itself, so it can't reach out to the internet for a note on its own It can only do a single receive requests, so Now we're gonna see it in action. What you have is Can you see my mouse? Yeah These are the exact same actor, but you'll note that this side has this HTTP server piece here That's me telling the The platform that hey this this actor it's allowed to talk over the RPC bus and receive HTTP calls Over here. You'll see a 500 error on The exact same set of code the only difference is when we signed it signed it with the same keys signed it with the same Actor and module key, but we forgot to give it a capability and If we were I think I actually have it There you go if we were to actually look at the error you can see Invocation fails simply because we haven't signed it with the right claim Again adding to that layer, you know that layer of security. That's pretty powerful Then we get to another layer of security policies This is also very powerful because Policies are nothing more than a wasm cloud actor itself. It's still signed. It still has the same invocations But we can say If we look at my the example here, we're gonna say in our cluster only official wasm cloud as Dictated by their public key is allowed to run here. So again over here. We have the exact same actor running twice On the bottom. I freshly compiled it and on the top. I'm using the one out of the OCI registry Same code same everything We get denied by policy again Very powerful because we're not learning a new technology. I'm not bringing in like OPA or anything. I'm I'm staying within Actor small understandable units of code and then lastly The last security feature I'm gonna talk about our invocation. So when one actor talks to a provider a provider to an actor They speak over an RPC bus like this for example what I've done is we have the echo I invoke the echo and these three messages Whatever go over the RPC the request the response and number two is The runtime saying hey, we logged this your invocation was successful because You know we checked to ensure that the signatures are correct We checked to make sure that you know the hashes inside the claims are correct. Everything's happy And if we actually blew up The jot that's inside of that invocation You know we get we get this and this is a go representation of the rust code that does the verification Which you can see? We take the origin we take the target we take the operation which in this example is handling HGP server handle request We hash it we hex it and then we stick it back in there And then when it gets to the other side not only does it check to make sure that it's coming from a valid source It actually checks to make sure that the payload has not been Edited along the way so our onions just getting more and more layers of security And now we're at the point with can we do something real with this? And this is kind of where the demo is not that impressive, but it almost took me six seven months to figure it all out Because it's all new. I you know you learn how Actors are invoked you under you understand how web assembly modules run in the runtime Man, oh, yeah, there's Jim And a quick note on telescope. You know what it is. It's a it's an open-source VPN built on wire guard essentially They have a really robust feature set one of them is this TS net What TS net let's us do is it actually allows us to Create a telnet node so a machine out of an HD a go HTTP server So what we're actually to see is I'm going to take a wasm cloud HD server provider, which has Been upgraded to a tell scale node, and we're actually going to run our application on our telnet In wasm cloud with no external well one external Redis, but no external resources That's not important Alright, so ultimately if you've never seen the wasm cloud dashboard. This is what we're gonna end up looking like We're gonna start an API gateway We're gonna start two providers one for Redis one for tails tail scale or so an HTTP server and From Joe's talk earlier, you'll notice these contracts in the middle These are not wazzy contracts because wazzy Is so new and the team will happily tell you that wazzy is coming to to wasm cloud soon But for now they are Extremely similar in their capabilities their contracts that that decide what capabilities These providers can do and then the actors at the same time will be signed with those capabilities Oh one thing I like to point out because I find it very interesting So this is a view application actually There we go That was a view application. The view application is actually compiled Built and then compiled into a rust act rust wasm Actor so Within our web assembly module. We're actually hosting an entire view application Which kind of blew my mind the first time I saw it So that when you see this, there's no there's no like separate HTTP server serving web pages somewhere We're going to hit our provider Providers gonna route all the traffic to the gateway the gateway has two endpoints for often and I'll see if it doesn't want either Those endpoints it's going to forward it to another wall web assembly Module that will then in turn serve web pages. I think that's kind of fascinating Okay Here this goes. I am cheating. I will be copying pasting these commands. I'm not brave enough to do it live Let's find them cool All right, so No tricks up my sleeve. I'm actually going to start wasm cloud right in front of you There is nothing running already Life demo Except that all right so at this point I have the host running if we were to look at the dashboard You'd see an empty dashboard We're going to start our two actors So our UI and our API gateway both web assembly modules And if you're interested in ever playing with this these all of these artifacts have been added to GitHub container registry for All right, and then we're going to start To providers so this will be the way we ingress via HTTP and access our red a server That is an actor. That was the wrong section And the last thing we're going to do is actors and providers. They talk over an RPC bus But it's not automatic. We can start these they're running. They're sitting there idle. What we're actually going to do is Provide a link To the on to the bus that says this actor and this provider are allowed to communicate All right, so now we're going to So this is what it looks like just like the picture from earlier We have two actors we have two providers and they're linked together and if we go This is the nerve-wracking part Very cool So now what I'm showing you is from my laptop. We're accessing my telnet, which is the Minotaur hammerhead Ui via wasm cloud, which is so cool because these web pages are in a web assembly module I'm accessing it over Tail scale. I know this kind of blew my mind when I did it. So that's part one but Just hosting our application, you know Isn't enough we need to be able to turn the knobs of things like reliability sustainability and scalability And I've got a fine minimize Sorry Which is the next thing we're gonna actually show so at this point we have an application that's running on my local machine That only I can access because I'm the only one With access to my telnet, but if we use a tool like Cosmonic, which is a Platform for wasm cloud. This is the same exact application running But The powerful thing is it's running on Three different hosts and I think two different clouds. So we have a gateway that's running in AWS We have a to-do app running in GCP. We have a tel scale also running in AWS And what's really cool is this Redis provider is still running on my laptop So There we go So what's mind-blowing about this is if you can see the URL to do that Minotaur hammerhead TS net all of you have Access to this right now. It is live. It's on the internet by way of Tel scales funnel capability. It's being hosted from a Redis server on my laptop a Ui in one cloud a gateway in another cloud It's all tying it together with the power of this RPC bus called, you know, the wasm clouds lattice And a few things that I want to point out on this page because they might go overlooked is You'll notice that I'm authenticated I'm authenticated because By way of traversing that telnet Tel scale knows who I am So within my gateway and my gateway says if Jordan from this telnet access Then he's clear to use the application and then the little green dot that can be completely ignored is Another piece of the gateway actor providing authorization So that's actually providing a JWT By way of Authentication of tail scale that gives me the power to actually interact with this app So you can know I can sit here and and do all the things now What's cool is Tell scale offers things like well I need my I need my shell back um tail scale offers Ackolist that says You don't even have to be in my telnet if I share this piece this node with you you can access it So I actually have a Let's see I Have a second tell scale account That I'm gonna switch over to And if everything goes right I'm not a front-end developer. So sometimes you have to hit refresh You'll see not only did I just switch authentication. It's gonna add a new picture if you hover over it. I've got a New user But this user even though that he's authenticated to the account to the application is not authorized So that green dot will never turn green and you'll note that means I can never actually interact with this app But I can access it And whatever logic I want to so Now we have in my opinion a secure distributed application that By power of cause you know wasm cloud and cosmetic should have no downtime and this is a real-world application I could let people sign up and interact with it and I have no overhead of users you all you know You you access it, you know, if you're connected to your telnet you have access to the to the application and then The last thing I want to say is With zero trust I found that doesn't actually exist. You've got to trust something right we trust in keys for which is Given to us by the folks over at Senadia by way of gnats. It's an add 255 19 way for doing things like Signing and and that that type of stuff Tail scale gives us access control list. We trust them. They're the experts. I don't need to roll custom roll access control list wasm time gives us module sandboxing and then wasm cloud gives us distributed You know way to ensure my invocations are from who I want them to and policy so I can lock it down if I feel like it and After a year of not knowing what WebAssembly was to now This has been a really amazing journey where actually most of you in this room has probably helped me at one point If you get slacked by either Captain America the Hulk, it's me But yeah amazing community The potential here is endless and I really see how we can build some amazingly secure and fun things with it That's all I really have Thank you Jordan, thank you very much. I'm questions for Jordan Hi, I'm Christoph. Thank you for the talk. I really think that the world needs another to-do application So I will post your link on Hacker news and all of a sudden millions of people will use your application To phrase the question differently. What about like performance application of like this distributed application? Yeah, so I will say I'm a happy hacker, but what I have found is in my testing I have actually run this exact application on Raspberry Pi's and then giving it access to the entire wasm cloud slack channel with like a few hundred people and I really and At my home over a 5g connection and I really haven't seen any latency or Problems with it and no one's complained. So I don't have any formal statistics or metrics on it, but my experience has been Even on like the worst possible network and device. I've given it. It's it's held its own so Yeah Thanks for the talk In hindsight, what would you like to have known one year ago when you started your journey with West Web assembly? That I need to understand rust No a Year ago, I think the the one thing I want to know is I never really jumped into a project where It's on me to run down Solutions right we have an amazing team Amazing people in this community But if you really want to understand like what wasm time is doing how wit works, you know We have documentations. It's not always complete. You have to go look at the code and kind of grok it yourself I've spent many many hours Trying to understand code segments and if I couldn't then porting it to a language. I did understand Only because that's how my mind learned it and now that we get thrown away because you don't you don't want my code and production other questions Jordan I think you kind of under sold some of the neatest things of your demo the go and rust code working together We're gonna have more of that later today in the component talk with Peter Hewlin and God Bedford from Fastly. I really appreciate you coming out today. Thank you so much for sharing your time with us Thank you for having me


He really believes in himself I brought him out. I baited him out Enemy has been slayed. That was nasty the massacre is and I was staying there