Transcript #164: Use type hints to build your next CLI app
Return to episode page view on github00:00 Hello and welcome to Python Bytes, where we deliver Python news and headlines directly to your earbuds.
00:04 This is episode 164, recorded January 9, 2020.
00:09 And I'm Brian Okken.
00:10 And I'm Michael Kennedy.
00:11 And this episode is brought to you by Datadog.
00:14 We'll talk more about them later.
00:16 But speaking of data, data-driven journalism.
00:19 Yeah, let's start there.
00:20 So there's this project called CJ Workbench, or just Workbench, something like this.
00:25 And this recommendation comes to us from Michael Palowski.
00:29 Sorry if I kind of mispronounced your name there, but thank you, Michael.
00:32 And it's data-driven journalism as a service, as a platform, along with training on how to use it.
00:42 Not training on journalism, but training on basically how to do data journalism.
00:46 So it's a pretty cool idea.
00:48 That is neat.
00:49 Yeah.
00:49 And so what you do is you can go and say, point it at, I don't know, some website.
00:54 And say, I want you to scrape this from the website.
00:56 And then you go and you fill in, like, this UI.
00:59 You fill in and say, okay, now I want to filter out the empty columns.
01:03 And now I want to do this and that transform and other transforms and so on.
01:07 And so it basically lets you do kind of what you might do with a Jupyter notebook.
01:13 But there's no code for the journalist, which is pretty cool.
01:16 And so you might wonder, well, if there's no code, why are we talking about it?
01:21 There's all sorts of software that does interesting stuff that we don't talk about.
01:25 Well, one of the things you can do is if you find that the built-in features are not enough,
01:30 then you write a few lines of Python and you start extending it for the journalist using Python,
01:35 which is a pretty cool way.
01:37 So instead of you worrying about the UI and all the basic stuff like loading CSVs
01:41 and working with data frames and all that, you just say, use this.
01:44 And if we got to write a little Python code, we will.
01:45 You can use their system and just add your own little code snippets to it?
01:50 Yeah, exactly.
01:51 So if you look at the features, it has modules to scrape, clean, analyze, and visualize data.
01:55 It's got built-in training, like it'll teach you how to use the feature that you've got built in.
02:01 It connects to things like social and Google Drive and APIs, like JSON endpoints, I think.
02:07 It has recorded workflows, so it's really repeatable.
02:10 Versioning.
02:11 But finally, you can write custom modules in Python and then add them to the little drop-down module library that you can use.
02:18 Oh, that's neat.
02:18 Yeah.
02:19 Yeah.
02:19 Plus, this is all in GitHub, so that if you really want to hack the back end, you can also.
02:25 Yeah, exactly.
02:25 It's open source.
02:26 It's on GitHub.
02:27 You can go grab it, download it, and run with it.
02:29 But they also have it online as a service.
02:31 So you can decide, do you want to run your own server?
02:33 Do you want to use their public server that's in beta?
02:36 Or whatnot.
02:37 So I covered this partly because I think it's really cool, and I also covered it because, boy, I think the world needs journalism right now.
02:44 Yes.
02:44 And, yeah, more people saying, I don't know if I believe your analysis.
02:48 I want to do my own analysis on it.
02:50 Yeah, and here you don't have to commit to a huge amount of work.
02:52 It's cool you pointed all these live sources.
02:54 Like, you can point it at some website, and it can, like, real-time refresh the live data that it's scraping for your article so it can evolve over time and whatnot.
03:04 It's pretty cool.
03:04 I might have to try this.
03:05 Yeah.
03:06 Yeah, nice.
03:07 Have we covered GUIs yet on this podcast?
03:09 I think I do remember way back when at some point we talked about GUIs, right?
03:12 Yeah, at least once.
03:14 Yeah.
03:15 So...
03:15 What do you got for us this time?
03:16 Well, so here's another one, another GUI.
03:18 This one's called Remy.
03:20 The Remy comes from Remote Interface Library.
03:23 I'm not sure why it's called that.
03:25 All GUIs are essentially...
03:25 Why is it not Remy?
03:27 Remy, I don't know.
03:28 No, no, it's cool.
03:29 But Remy, a platform-independent Python GUI library for your applications.
03:34 And yes, we've covered things like this a lot of, like, okay, I want to just scrap the idea of a native user interface, and we'll just use web user interfaces.
03:43 The thing that I liked about this, it's so small.
03:47 There's no dependencies.
03:48 I'm not sure why they're pointing you to do a pip install from their GitHub repo, but I'm guessing they're not really that great about...
03:55 updating the PyPI version, because it's there also.
03:58 But anyway, I did this morning.
04:01 Grabbed a...
04:03 Just did a pip install of Remy, but from their Git repo.
04:06 And then I tried their little sample basic app, and I'm like, is it really this easy?
04:11 And yeah, this is like 30 lines of code or less to just write.
04:16 And if you run it, just Python bloop.
04:19 Oh, first of all, when you pip install it, it installs the package, and then that's it.
04:23 It doesn't install anything else.
04:25 Because it's only dependent on the standard library, which is cool.
04:28 And then you start it up, and it runs a little server on your thing, and it's really easy to throw buttons together and stuff.
04:36 It looks pretty good enough, and the code is simple enough that I thought I'd include it, because there's a lot of cases where, like in an internal team, where you have...
04:47 If you want to throw something together where people have access to some Python data or some Python analysis with a user interface, and something like this would be cool.
04:57 And it's neat.
04:58 Yeah, it's pretty neat.
04:59 It's like a Python-only electron.js-ish type of thing without the HTML part.
05:07 So you define your app, and you programmatically define, like, I want a button here, and I want a label there.
05:14 And when I click the button, I want it to call this other Python function.
05:17 So you just write pure Python, and then it turns the GUI definition into HTML, shows that in a server, and then calls back to your code, something like that, which is pretty cool, right?
05:28 Yeah, and it feels similar to working with TK back in the day.
05:33 Within the Python code, you create a label object and a button object, and then you put them in a container.
05:40 There's no packing so far that I can see, but it has different types of containers that you append them, and then just throw those in a box.
05:49 So, yeah, like you said, you don't have to write any of the HTML.
05:52 It's just all Python code.
05:54 So, yeah, for what it's worth, it's kind of simple.
05:58 Yeah, it's a nice, simple little thing, and it looks pretty cool, and yeah, I kind of like it.
06:02 One of the things I was thinking about doing was, sorry, was we have a switch box that's controlled through.
06:10 We've got a Python thing that controls the switches, and sometimes it'd be nice to be able to just see what the current setup is and just have a web page that just shows that.
06:19 It'd be really easy to write in Python, kind of hard to do.
06:22 I don't want to deal with a whole user interface sort of thing, but having that, I think I could probably throw that together with this tool in like half an hour.
06:31 Yeah, and it's a proper local application, so it can look around on the system and do what it needs to do.
06:38 It needs to be really a web server.
06:40 Yeah.
06:40 Although you can expose, I saw there's a way to tell it to listen on the network, broader interface, not just local host.
06:47 So you can't expose this thing to sort of the world, for what that's worth.
06:51 I don't know if it's a good idea or not, but you could.
06:52 Like I said, we would do it within our internal network, so there's no malicious code flying around internally.
06:58 Yeah, yeah.
06:59 Yeah, cool.
07:00 Anyway.
07:01 You know, I'm starting to get excited again about Qt after Ogie Moore's presentation at the last PDX Python West meetup.
07:09 Like that looked pretty compelling, actually.
07:11 Yeah.
07:12 What a slick program that was.
07:14 And zippy.
07:14 Very zippy.
07:16 Nice.
07:16 Speaking of slick, Datadog.
07:18 Yeah.
07:19 Python Bytes today is sponsored by Datadog, a cloud-scale monitoring analytics platform that unifies metrics, logs, and distributed traces from your Python application.
07:31 The Datadog tracing client auto instruments popular frameworks and libraries such as Django, Flask, Postgres, and AsyncIO even, so you can quickly get deep visibility into your application.
07:44 Trace requests across services boundaries with flame graphs.
07:48 I like flame graphs.
07:49 Correlate traces with logs and metrics and plot your application architecture with the service map.
07:55 Sign up for free for a free trial at pythonbytes.fm/Datadog and you'll receive a free t-shirt.
08:02 Nice.
08:02 Yeah, they're doing good stuff.
08:04 Thanks, Datadog.
08:04 This next one, Brian, you wanted it, but I got it.
08:08 Yeah, you got it first.
08:09 It's cool.
08:10 I'm excited about it.
08:11 Yeah, so there's a couple of cool libraries for building CLIs.
08:16 Click is probably the most prevalent one.
08:19 We've got argpars.
08:21 But people who do FastAPI, the cool new API framework, these folks have now gone, let me just double check that it's actually the same organization.
08:32 Yep.
08:33 Yes, good.
08:33 Yeah, same work.
08:34 Perfect.
08:34 Perfect.
08:34 So they've gone and created a CLI definition library like Click.
08:40 And I believe it's actually based on Click.
08:43 Yeah, it's based on Click.
08:44 So you might wonder, well, what does it do?
08:47 The name gives you a little bit of a hint.
08:49 It's based on Python type hints.
08:51 So Typer looks at the various hints.
08:53 It can, you can say like, I have a function.
08:56 It takes a name, which is, you know, name colon stir.
08:58 It takes a string.
08:59 And then you just use it.
09:01 And when you go run it, it'll say, hey, this thing that we ran, in order to call it, you have to specify a name and the name has to be a string and so on.
09:09 So it just looks at the arguments and the types of the methods you're trying to run, in the simple case at least, and it uses that.
09:15 That's pretty cool, huh?
09:16 It's super cool.
09:17 Yeah.
09:17 And then you can grow in more complexity.
09:20 Like you can have sub commands.
09:21 You can have help on all the commands.
09:24 You can actually get autocomplete.
09:26 You can install autocomplete in your shell, all kinds of cool stuff.
09:30 So you can create a little app.
09:31 You say, here's a command and here's a command.
09:33 And then, of course, the commands are functions.
09:35 Those functions take arguments.
09:37 The arguments have types.
09:38 They can have default values, all that kind of stuff.
09:40 So you can try to run it.
09:42 It'll give you help pretty much automatically, which, yeah, this really speaks to me the way this works.
09:47 I could definitely see myself using it.
09:49 Yeah.
09:49 So a really good, clean command line interface that has, if you're writing a tool with a command line interface,
09:56 you're going to want help associated with it.
09:58 You're going to want description of the different methods and what they do.
10:02 But also, with as little boilerplate as possible, you don't want to clutter up your code.
10:07 And as far as I'm concerned, right now, typer wins.
10:11 There's hardly any extra overhead that you have to add to make this work other than type hits.
10:17 And if you're not using a main or something, you have to put a little decorator on the different entry points in your program.
10:23 But really clean.
10:25 I'm totally going to start using this.
10:26 It's really nice.
10:27 And because it can leverage so much of the natural program itself, right?
10:32 The argument names, the fact that it has arguments, the argument types.
10:36 That's really helpful for it, yeah.
10:38 So you can also integrate things like Colorama and click, which is based on, will automatically start using color for its output.
10:47 If you just have Colorama around, you can also use click completion.
10:50 And typer, this is the part I was talking about, will automatically configure it to provide completion for all the shells.
10:56 That's really cool, too.
10:57 So the one thing I was concerned about is it's based on click.
11:02 And one of the things I love about click is that it has a good testing interface.
11:06 You can write tests against your command line app as if you're writing from the command line,
11:11 but you don't actually have to spawn a new subpros to test things.
11:15 And yes, typer has the same sort of model where you can write your tests against the interface and not have to do a subprocess.
11:23 Oh, that's really cool.
11:24 Yeah, nice.
11:25 Because, yeah, you don't have to start it basically shell out and see what happens, right?
11:29 Or like issue the command line directly to the shell to see what happens.
11:33 Yeah, really good job.
11:34 Yeah, the other thing I like about this is you could say, well, we don't want the API of click.
11:39 So we're going to start from zero and rebuild our version of what this whole world looks like.
11:44 But what they did is said that we're going to build a new interface for writing against this, but on top of click.
11:50 So things like Colorama and the completion just plug in seamlessly.
11:54 I think that's a cool lesson.
11:55 Yeah, definitely.
11:56 Also, it's a smaller project for them to have to maintain, too.
11:59 Yeah, exactly.
11:59 Yeah.
11:59 Exactly.
12:00 Cool.
12:01 All right.
12:01 This next one that you got here is from Chris Moffitt, right?
12:04 Yes.
12:04 And this is actually...
12:06 So I'm hoping this is completely still accurate.
12:08 I imagine it is.
12:10 The interface for Matplotlib hasn't changed too awfully much.
12:14 I know they've had some cool releases, but I want to talk about an article called Effectively Using Matplotlib.
12:20 And this is a 2017 article.
12:22 But in the middle of the introduction, he says, at first, I think I was a little premature in dismissing Matplotlib.
12:28 To be honest, I did not quite understand it and how to use it effectively in my workflow.
12:33 And I think that matches my understanding of Matplotlib as well.
12:37 I mean, when I first needed to put charts or graphs or something, of course, you try Matplotlib.
12:43 And then you're...
12:43 You kind of hit in the face with the complexity of the interface.
12:47 And you know you can do the simple thing simple, but how to do something a little bit more less than simple or more than, you know, more complex is a little daunting.
12:56 And then I went out and looked for other alternatives.
12:58 But now I think the alternatives have their issues too.
13:02 So I'm ready to go back and take a serious look at Matplotlib.
13:05 This article is a really good look at kind of understanding it and at least Chris's workflow, how to use it.
13:13 And one of the things I like is the description that one of the reasons why Matplotlib's interface might be a little confusing is because it's coming from...
13:22 It's really got two interfaces.
13:23 It does a Matlab-like state-based interface.
13:27 And I'm not a Matlab user, but I know that a lot of people have come from Matlab to Matplotlib.
13:33 And so that sort of interface is important to have that transition be easy for a lot of people.
13:39 But then there's also an object-based interface that makes a lot more sense.
13:43 And that's Chris's recommendation is to use the object-based interface instead.
13:49 And so now after he's gone through it a few times and he has some recommendations.
13:55 And his recommendations are to first learn the basic Matplotlib terminology, specifically what is figure and axes and around those.
14:06 And what's difficult for me is that those are just normal words that I think I already understand them.
14:12 But I need to make sure I understand what Matplotlib thinks those things are.
14:16 Yeah, sometimes it's just hard to work with Matplotlib unless you find an example, right?
14:21 A lot of times what I...
14:23 My goal is to hunt the internet for something that looks like I want.
14:26 Figure out if I can find the Python code that created it.
14:29 And then I'm good.
14:30 Yeah.
14:30 He does have an example in this, which is kind of walks through at least one example.
14:35 But if you really want to kind of get your head around it to start with using pandas with Matplotlib.
14:41 So yeah, you start your visualization with basic pandas plotting and then add, if you want it more complex, try Seaborn.
14:49 And then if you want to customize it a little bit more, he said use Matplotlib native stuff to customize the visualization.
14:57 And I wouldn't have thought to use that workflow.
14:59 So that's kind of nice.
15:01 It also includes this really kind of cool handy reference that there's a little graphic that he created that has like all the different...
15:09 What all the axes are and if you want to customize a certain part of a graph, what that name is within Matplotlib so you know how to look it up.
15:16 And that's often...
15:17 The secret of programming anymore is to know what specific word to Google.
15:21 So I think that's a good thing.
15:23 Nice.
15:23 And also I want to remind folks, long-time listeners of PyLustrator.
15:29 I'm not really sure about the pronunciation like Illustrator, but Py for the first two words.
15:35 I'll put a link in the show notes.
15:36 And what it is, is it lets you take a basic Matplotlib plot.
15:40 It launches a GUI where you customize the look and feel and then it'll output the code that would have done that for you.
15:45 Oh, cool.
15:46 Yeah.
15:46 We talked about that in episode 137, which is like a year ago or something.
15:50 But anyway, still good stuff.
15:51 So I'll put a link in there for that.
15:52 I'm also including a link in a almost related section.
15:57 Maybe there's an article about this, but I haven't found it.
15:59 There's a Stack Overflow answer that has a little...
16:03 The code you need to stick a map...
16:06 Generate in a Matplotlib graph and put it in a Flask file on the fly without having to save it to a file.
16:14 Oh, yeah.
16:14 Like a live dashboard type thing.
16:15 That's cool.
16:16 Yeah.
16:16 Nice.
16:16 Speaking about doing stuff on the web, if you're using Django, there's a cool little library that'll let you do stuff in the background.
16:23 Maybe you want to do some query and update some kind of report or you want to send out a bunch of emails or recompute some indexes or recompute some search results or something like that.
16:36 And it's going to take a little while and you don't want to just have it block on your main request.
16:42 There's a bunch of different things you could do.
16:43 You could set up a separate server with like Celery or RabbitMQ or something like that.
16:49 But that's a whole other set of servers and it just gets way more complicated.
16:52 Sometimes you want to just run it in the background just in the same process, right?
16:56 It's easy to share data because you just pass the pointers.
16:59 So there's this thing called Django Simple Task.
17:02 And it allows you to run background tasks in Django 3 without requiring any services or workers.
17:09 Oh, cool.
17:09 Yeah, basically the reason it has to be Django 3 is it's based on AsyncIO.
17:14 And Django 3 is the first version that uses ASGI.
17:18 And so you actually need to run it in ASGI server like UV, Acorn or something like that.
17:24 So be really aware that you have to run it in its async way for this to work.
17:28 But basically when it starts, when the web app starts, there's a queue created and some workers to listen to the queue.
17:35 And then you just go to any function you want to run and you just call defer on it and that'll kick it off in the background.
17:41 And you could do that now.
17:43 Like you could create a thread and just launch it as a background thread.
17:46 But one, you don't get like a thread pooling.
17:49 But the other is when it's time for the worker process to shut down, like you're doing a new deploy or something, it'll actually wait until its background work gets done before it allows you to restart it, at least in a friendly way.
18:01 So that's cool.
18:03 And you can either give it a asyncio coroutine or just a function and it delegates it, either runs it or delegates it to a thread pool if it's not async, things like that.
18:12 So it's pretty cool and it's really easy to use, like ridiculously easy.
18:15 Oh, that's neat.
18:16 Yeah.
18:17 So there's a simple little example I put in the show notes where it just imports the deferred operation method.
18:23 It has two tasks, one of them which uses time.sleep that requires threading.
18:28 And one uses asyncio because it's an async method.
18:31 So it would run on the async event loop.
18:33 And in the view, you can just say defer one, defer method one, defer method two, and then do your regular work.
18:39 And that kicks it off but doesn't wait for the response.
18:41 But does it in a slightly more durable, better way than just like launching threads or kicking it off on its own little background thing to go run unmonitored.
18:50 So in this example that nobody can see, but they will if they look at the show notes, will the HTTP response happen and the view return before the defer tasks get run?
19:01 They might get started, but because in both of them they sleep for a second to kind of, that's their work, right?
19:08 They're sleeping for a second.
19:09 So certainly the response would be sent back to the user before those are done.
19:14 And this is a cool interface because the two tasks, one of them is async and one is not.
19:19 And the defer call doesn't, you can't tell.
19:22 Right.
19:22 You don't have to treat it differently.
19:23 But if you can do async, great.
19:25 It'll do that on the async event loop, I think.
19:27 Otherwise, it just puts it into a thread pool, which is pretty cool that you don't have to worry.
19:32 You can just kind of go, here's some background stuff.
19:34 If it's IO driven, we'll do it this way.
19:37 Otherwise, just do it that way, which is, I like it.
19:38 It's nice.
19:39 Yeah, really nice.
19:40 Cool.
19:40 Cool.
19:41 All right.
19:41 What's this last one you got for us?
19:43 Well, so something happened recently.
19:45 I've got a handful of, I don't open source, work on open source projects really as much
19:52 as I'd like to.
19:52 I'd like to work, do some more work on open source projects.
19:56 But I have a few that I maintain myself.
19:59 But project is in air quotes I'm doing because they're really pretty small projects.
20:04 And a couple of them, cards and submark are things that I just created to help with teaching
20:11 people how testing works.
20:13 They're not really intended to be useful projects.
20:16 And then another one was a plugin for pytest.
20:19 Actually, I do use it and it's useful for me.
20:23 But I started getting, like in the last handful of months, I started getting pull requests and
20:29 issues and stuff.
20:30 And I didn't know anybody was using it at all.
20:33 So this was surprising to me.
20:34 But I wanted to highlight, I don't know if, I can't believe we haven't covered this or maybe
20:38 we already have.
20:39 There's a website called PyPI stats.org.
20:42 Yeah, that's news to me.
20:43 I hadn't heard of it.
20:44 It's just a simple interface.
20:46 Now, the backend might be complicated.
20:48 But in the interface, it just has like a little box and you plug in a Python package and it
20:55 tells you what the download stats, actually quite a bit of history too, of different packages.
21:00 And so I use that for all of my different projects.
21:04 And sure enough, cards was downloaded like, I don't know, less than 400 times in the last
21:09 month, submark less than 70 times in the last month.
21:13 And then pytest-check, which is a little app or a plugin that lets you have multiple failures
21:20 per test, but keep going during the test.
21:22 That was downloaded just a little less than 20,000 times in the last month.
21:28 So clearly that one's more.
21:29 And that's the reason why I'm having more people try and tell me what's wrong with it.
21:34 So I guess I have to start maintaining.
21:36 Yeah, this is a super cool interface.
21:39 You get all kinds of graphs and ability to slice it by dates and whatnot.
21:43 And yeah, I like it.
21:45 And there's also a top 20.
21:46 So you can look at like really what are the top 20 packages on PyPI.
21:50 And that's why I say that mine are small peanuts because at the most, it's like 19,000 a month.
21:57 But the top 20 all get over 1.3 million downloads per day.
22:02 Wow.
22:02 Yeah.
22:03 And you can look at them, look at the trends.
22:05 That's pretty interesting.
22:05 There's probably some cool stuff to go through here.
22:08 And I guess if you were trying to do predictive stuff or analytics, there's probably a lot of
22:14 things to be done here.
22:14 Yeah, definitely.
22:15 Also, just occasionally, I'm just the top 20.
22:18 I like because I was occasionally I'm curious about that of like, what are the top packages
22:24 on PyPI?
22:24 What do people use it?
22:25 Yeah.
22:26 They weren't what I expected.
22:28 I mean, some of the ones I obviously expected were, but I think right now URLlib was the top
22:33 top.
22:33 And I didn't expect that.
22:35 So yeah.
22:36 Yeah.
22:36 URLlib 3 specifically.
22:37 But yeah.
22:38 It must be used by a whole bunch of other stuff.
22:40 Like 6.
22:41 I don't think people are specifically downloading 6.
22:44 It's the 2 or 3.
22:46 Like I think Request uses both of those and Certify and that like hits the top 4.
22:51 So Python.
22:53 DateUtil is a good one up there.
22:54 Boto Core.
22:55 Pretty interesting.
22:56 I use Boto 3, which depends on Boto 4, but it kind of makes me frustrated because Boto 3 won't
23:03 use the latest version of Boto Core, but it's all made by the same people.
23:07 Anyway, there's a bunch of interesting stuff up here.
23:10 Yeah.
23:10 I think I'm going to have to look at this some more.
23:12 pip is in the top 20.
23:13 Nice.
23:15 Got to get started somewhere.
23:16 Yeah.
23:17 All right.
23:18 Well, that's it for all of our main items.
23:19 What you got for the extras?
23:20 Well, I wanted to actually just ask for some help.
23:22 The last episode we put out was a live recording of the January Python PDX West meetup.
23:30 Actually, not the entire meetup, but just a-
23:32 Flash in case people haven't been paying attention.
23:34 They're near Portland.
23:36 There's a second Python meetup, which runs out in Hillsborough.
23:39 Much better for Westside folks.
23:41 So yeah, you put that together.
23:43 Good job.
23:43 Yeah.
23:43 And one of the things that we wanted to do with this one was to, I got this from a lot
23:47 of people.
23:48 And in the tech community, well, the Westside has a lot of high-tech stuff.
23:53 There's a lot of people coming from other languages to Python.
23:56 And so they might not be beginner programmers, but they're beginners at Python.
24:01 We've had this before, people saying some beginner-friendly content per at least one topic per meetup so
24:08 that people aren't lost with everything.
24:09 And yeah, we kind of forgot this last time, but I enjoyed the topics.
24:14 I'd like to hear from other people as to what sort of topics would be good at a meetup for
24:19 Python beginner-friendly.
24:20 And just let us know.
24:21 I think that'd be cool.
24:22 Yeah.
24:22 Well, it's easy to get super into focusing on what's the most latest, coolest, hottest
24:28 thing.
24:29 But there's a lot of folks who really just appreciate setting the ground, a good foundation.
24:35 And so, yeah, I think that's a good topic.
24:36 Yeah.
24:37 And one of the things I'd like to do is possibly get a list of those sorts of things so that
24:41 we can try to ask people to put together something.
24:45 Like one of the meetups I did, like just describing how pip and virtual environment work and how
24:52 to use those.
24:52 And there's a lot of basic stuff that people don't even think about maybe that they should
24:57 talk about.
24:58 And it'd be good to hear more.
25:00 I also want to try to get other people to do it because you and I could probably do
25:03 those sorts of beginner-friendly ones.
25:05 Sure.
25:05 It'd be fun to have other speakers too.
25:07 Yeah, absolutely.
25:07 It would be very fun.
25:09 If people are willing to get to Portland on a Tuesday evening, then they can come give a
25:14 presentation.
25:14 Yeah.
25:15 One more thing.
25:16 I want to do a shout out to PyCascades 2020.
25:19 I can't remember when.
25:20 It's in February coming up.
25:21 February, I believe.
25:22 I believe it's like 8th and 9th.
25:25 Let me double check.
25:25 It is February 8th and 9th in Portland, Eastside.
25:29 Wonderful.
25:29 So people should get tickets so they could come.
25:31 And if you haven't bought your ticket yet, check the show notes because we've got a discount
25:36 code for 10% off.
25:37 Yeah, absolutely.
25:38 Yeah, it's right there at the bottom.
25:39 I don't really have anything this week for extras to share.
25:43 But one thing that did come out and caught my attention yesterday that I think I might as
25:47 well just throw out that's kind of cool is Firefox 72 is out and it has come with anti-fingerprinting,
25:54 which is pretty exciting.
25:56 So I don't know how many people are aware.
25:58 I don't know if you're aware, Brian.
25:59 That even with ad blockers and blocking like tracking cookies and stuff, there's all these
26:04 weird things that you can do to figure out.
26:07 Actually, it's that same person, right?
26:09 Like you can ask, what are all the installed fonts and what version of OS do you have?
26:15 And here's a canvas thing.
26:17 Let's run some stuff on there and like try to detect weird CPU cycles and other kinds of
26:22 there's all these like weird things you can do in browsers and pretty much uniquely identify
26:26 everyone running a web browser.
26:28 Oh, that's lame.
26:29 Even without cookies.
26:30 Yeah.
26:31 So Firefox is trying to fight back against that.
26:33 So I think that's pretty awesome and worth checking out.
26:36 I'll actually link to ours Technica article about it.
26:38 Okay, cool.
26:39 Yep.
26:40 Well, I guess that leaves us with a joke, doesn't it?
26:42 Yeah.
26:43 Last time we did a joke about describing different software programming jobs.
26:47 This one, you're going to have to imagine that people who are fans of various programming
26:52 languages are in like a literature course and they have to write an essay.
26:57 Okay?
26:57 Okay.
26:58 Okay.
26:58 Have you pulled up the picture?
27:00 Yes.
27:00 I'm already laughing.
27:01 All right.
27:01 Cool.
27:02 So basically there's professor looking person with glasses trying to read like a paper, a
27:07 physical paper and a student looking at it, getting the feedback from the professor.
27:12 This is important because at the end it gets interesting with the pictures.
27:15 So for Python, it says, this is plagiarism.
27:19 You can't just import essay.
27:20 For Java, it says, I'm two pages in and I have no idea what you're saying.
27:28 Assembling.
27:29 Assembling.
27:30 Pretty appropriate.
27:30 Yeah.
27:30 Assembling.
27:31 Do you really have to redefine every word in the English language?
27:34 With C, it says, this is great, but you forgot to add a null terminator.
27:39 Now I'm just reading garbage.
27:40 I don't really know if I understand the C++ one, but it says, I asked for one copy, not
27:47 400 and the professor's buried in books.
27:49 Oh, I don't get that either, but.
27:51 Yeah.
27:51 Okay.
27:52 Unix Shell.
27:52 This one's pretty good.
27:53 I don't have permission to read this.
27:55 LaTeX, which you often use to describe scientific papers and super elaborate mathematical formulas,
28:02 says, your paper makes no sense to me, but it's the most beautiful thing I've ever laid
28:07 eyes on.
28:08 And the final one is the HTML programmer.
28:11 And instead of holding a paper, the professor's holding a pot and they just say, this is a flower
28:18 pot.
28:19 What is it?
28:21 I don't get it, but it's funny.
28:23 Yeah.
28:23 I don't either.
28:24 All right.
28:25 So anyway, I thought that was pretty fun.
28:26 You all can check it out.
28:27 The comic is linked in there, but it's pretty fun.
28:30 You can't just import essay.
28:31 This is plagiarism.
28:32 All right.
28:34 Well, thanks a lot, Michael.
28:35 Yeah, you bet.
28:36 Thanks, Brian.
28:37 Good to be here.
28:37 Thank you for listening to Python Bytes.
28:39 Follow the show on Twitter at Python Bytes.
28:42 That's Python Bytes as in B-Y-T-E-S.
28:45 And get the full show notes at Pythonbytes.fm.
28:48 If you have a news item you want featured, just visit Pythonbytes.fm and send it our way,
28:53 where I was on the lookout for sharing something cool.
28:55 This is Brian Okken, and on behalf of myself and Michael Kennedy, thank you for listening
28:59 and sharing this podcast with your friends and colleagues.