WEBVTT

00:00:00.001 --> 00:00:04.600
Hello and welcome to Python Bytes, where we deliver news and headlines directly to your earbuds.

00:00:04.600 --> 00:00:10.460
This is episode 321, recorded January 30th, almost the end of January.

00:00:10.460 --> 00:00:11.920
And I am Brian Okken.

00:00:11.920 --> 00:00:13.260
And I am Michael Kennedy.

00:00:13.260 --> 00:00:14.000
Hey, Michael.

00:00:14.000 --> 00:00:14.720
Hey, hey.

00:00:14.720 --> 00:00:16.400
Excited to be here today again.

00:00:16.400 --> 00:00:17.440
Absolutely.

00:00:17.440 --> 00:00:22.480
Before we jump too far into it, I want to thank Microsoft for Startup Founders Hub.

00:00:22.480 --> 00:00:24.580
Please listen to their spot later in the show.

00:00:24.580 --> 00:00:26.140
How are we going to start the show?

00:00:26.140 --> 00:00:27.440
What do you have for us, Michael?

00:00:27.440 --> 00:00:34.440
You may wonder, some folks have publicly expressed the bewildering thought that maybe we live in a simulation.

00:00:34.440 --> 00:00:35.900
I don't think so.

00:00:35.900 --> 00:00:37.460
Do you think we live in a simulation, Brian?

00:00:37.460 --> 00:00:39.220
Sometimes, yeah.

00:00:39.220 --> 00:00:40.520
No, I don't.

00:00:40.520 --> 00:00:42.500
When I'm playing a game, maybe.

00:00:42.500 --> 00:00:49.260
But what if you were working on Git and you wanted to see how things were working, simulate some operations,

00:00:49.260 --> 00:00:53.620
and try to understand how Git works without actually making those changes?

00:00:53.620 --> 00:00:58.320
Because there's always the, you know, Git is full of good jokes, right?

00:00:58.320 --> 00:01:01.900
Like, in case of fire, Git commit, Git push, run.

00:01:01.900 --> 00:01:03.340
You know, things like that.

00:01:03.340 --> 00:01:03.460
Yeah.

00:01:03.460 --> 00:01:03.800
Those jokes.

00:01:03.800 --> 00:01:07.200
But the other one is, you know, you don't need to know Git that well.

00:01:07.200 --> 00:01:12.340
If you mess it up, you just delete the repository and clone it again and start over, right?

00:01:12.460 --> 00:01:19.760
So, you know, ideally, you would be able to run some operations to help you understand what Git is going to do without consequence.

00:01:19.760 --> 00:01:20.420
Okay.

00:01:20.420 --> 00:01:23.280
And so I introduced to you this tool called GitSim.

00:01:23.280 --> 00:01:28.320
And GitSim will visually simulate Git operations in your repos with a single command.

00:01:28.320 --> 00:01:36.120
So what it is, is instead of saying, like, Git merge branch, you would say Git-Sim merge branch.

00:01:36.120 --> 00:01:40.100
Now, how best to explain what's going to happen?

00:01:40.100 --> 00:01:45.200
Like, if it just says, we would have merged this branch into that branch with seven changes.

00:01:45.200 --> 00:01:47.680
You're like, okay, maybe that's fine for merge.

00:01:47.920 --> 00:01:50.640
But there are many other things that are more complicated.

00:01:50.640 --> 00:01:58.500
And so, as you and I are fans of, this will simulate, it will show you the visual behavior changes that are going to happen.

00:01:58.500 --> 00:01:59.420
Isn't that cool?

00:01:59.420 --> 00:01:59.760
Yeah.

00:01:59.760 --> 00:02:02.440
So, by default, you get a JPEG image.

00:02:02.440 --> 00:02:09.360
And the top one you see here, you can see all the commits, their SHAs and their message.

00:02:09.360 --> 00:02:11.000
And you can see two branches.

00:02:11.000 --> 00:02:13.420
It'll see where head and main are and where dev is.

00:02:13.460 --> 00:02:19.780
And it'll show you, if you do a commit or actually a merge, you're going to take these changes from dev, push them forward, right?

00:02:19.780 --> 00:02:22.920
And the resulting shape or behavior of the repository.

00:02:22.920 --> 00:02:23.540
Yeah.

00:02:23.540 --> 00:02:25.620
So, that one's pretty straightforward.

00:02:25.620 --> 00:02:27.780
I'll show you some really cool ones in a minute.

00:02:27.780 --> 00:02:31.940
So, use cases include visualizing Git commands to understand them.

00:02:31.940 --> 00:02:33.540
It's kind of what I was talking about.

00:02:33.540 --> 00:02:39.240
Also, my joke, prevent unexpected working directory and repository states by trying it out first.

00:02:39.520 --> 00:02:46.080
But there's also a whole, I'm creating blog posts, tutorials, courses, whatever.

00:02:46.080 --> 00:02:52.180
So, sharing visualizations of your Git commands with your team, maybe for documentation, right?

00:02:52.180 --> 00:02:54.140
In our wiki, like, this is our workflow.

00:02:54.140 --> 00:02:58.840
You probably don't understand what this weird Git thing is that we're doing because it's non-standard.

00:02:58.840 --> 00:03:03.660
Please watch this little animation so you know why we're doing it or something like that, right?

00:03:03.660 --> 00:03:04.200
Yeah.

00:03:04.200 --> 00:03:07.820
Internal documentation, that's a great use for that.

00:03:08.200 --> 00:03:09.060
Yeah, absolutely.

00:03:09.060 --> 00:03:19.060
So, basically, the supported commands at the moment are log, status, add, restore, commit, stash, branch, tag, reset, revert, merge, rebase, and cherry pick.

00:03:19.060 --> 00:03:21.040
And then sub commands of those, right?

00:03:21.040 --> 00:03:22.040
Install.

00:03:22.040 --> 00:03:26.800
It's got some steps to install it, some ways to run it.

00:03:26.800 --> 00:03:31.060
But then you can see, if you scroll down far enough, you'll start to see some of the examples.

00:03:31.060 --> 00:03:35.220
So, there's a bunch of examples that are pictures, like a git sim-log.

00:03:35.220 --> 00:03:40.040
It'll simulate the output showing the most recent five commits on the active branch.

00:03:40.040 --> 00:03:40.540
Yeah?

00:03:40.540 --> 00:03:43.600
And it sort of shows you the tags and various things.

00:03:43.600 --> 00:03:50.380
You can see status, and it does like a rich style sort of tree, not tree, a table view.

00:03:50.380 --> 00:03:52.000
Really nice there.

00:03:52.000 --> 00:04:02.660
You can see a lot of the different, almost Kanban flow of your files going from untracked to tracked and modified locally and staged and all that.

00:04:02.660 --> 00:04:04.500
Which is, actually, I think it's pretty helpful.

00:04:04.500 --> 00:04:10.500
Even with little arrows showing, you know, it moved from here in this one of those columns to this other column.

00:04:10.500 --> 00:04:11.100
Yeah.

00:04:11.540 --> 00:04:13.620
I don't think I've ever used git restore.

00:04:13.620 --> 00:04:14.480
I don't think so.

00:04:14.480 --> 00:04:15.960
I don't make mistakes, so it's fine.

00:04:15.960 --> 00:04:18.220
Isn't that delete and reclone?

00:04:18.220 --> 00:04:20.120
Yeah, exactly.

00:04:20.120 --> 00:04:20.840
Oh, my God.

00:04:20.840 --> 00:04:21.560
Don't commit that.

00:04:21.560 --> 00:04:22.160
Don't push that.

00:04:22.160 --> 00:04:22.500
Please.

00:04:22.500 --> 00:04:23.200
Just delete it.

00:04:23.200 --> 00:04:24.460
Let's see.

00:04:24.460 --> 00:04:27.660
But if we go down further, you'll get more interesting examples.

00:04:27.660 --> 00:04:29.640
The merge one is there.

00:04:29.640 --> 00:04:30.180
Let's keep going.

00:04:30.180 --> 00:04:31.960
But we get to the video one.

00:04:31.960 --> 00:04:34.460
This is where it gets to be pretty awesome and pretty unique.

00:04:34.460 --> 00:04:35.080
Animate.

00:04:35.080 --> 00:04:37.560
We could do a git sim reset.

00:04:37.560 --> 00:04:38.440
So, check this out.

00:04:38.440 --> 00:04:45.200
So, over here, you have this visual diagram showing how this stuff is changing over time.

00:04:45.200 --> 00:04:50.680
So, it's like, all right, what we're going to do is we're going to reset this and you'll see, like, the head pointer and the branch pointer move over.

00:04:50.680 --> 00:04:52.100
And what do you think, Brian?

00:04:52.100 --> 00:04:53.000
Isn't this cool?

00:04:53.000 --> 00:04:54.160
This is really neat.

00:04:54.160 --> 00:04:54.620
Yeah.

00:04:54.620 --> 00:04:55.120
Yeah.

00:04:55.120 --> 00:04:56.780
I'll just pick one or two more.

00:04:56.780 --> 00:04:57.640
So, we got merge.

00:04:57.640 --> 00:04:58.400
That's pretty straightforward.

00:04:58.400 --> 00:04:59.380
Rebase.

00:04:59.380 --> 00:05:01.320
Let's animate a cherry pick.

00:05:01.320 --> 00:05:06.580
So, you'll see it coming along here, building up the git repo status.

00:05:06.580 --> 00:05:07.860
And then what's going to happen?

00:05:08.180 --> 00:05:09.440
It's going to show us a branch.

00:05:09.440 --> 00:05:13.900
And we want to take some of those changes and cherry pick them over to the main.

00:05:13.900 --> 00:05:14.500
Yeah.

00:05:14.500 --> 00:05:14.840
Anyway.

00:05:14.840 --> 00:05:18.720
If you trained on that one, but that's okay.

00:05:18.720 --> 00:05:19.220
I am too.

00:05:19.220 --> 00:05:20.960
That's not a great animation, to be honest.

00:05:20.960 --> 00:05:25.940
Anyway, it shows you a bunch of examples, a bunch of cool things.

00:05:25.940 --> 00:05:27.360
I think this is really nice.

00:05:27.360 --> 00:05:34.380
It's like I said, primarily documentation internally, like your internal wiki, your onboarding docs, or for, say, blog posts.

00:05:34.380 --> 00:05:37.700
You want to talk about what something looks like, then run this.

00:05:38.020 --> 00:05:40.620
And it's not just what does a git merge look like.

00:05:40.620 --> 00:05:44.320
It is, what does the git merge look like on this repo in this state, right?

00:05:44.320 --> 00:05:44.480
Yeah.

00:05:44.480 --> 00:05:46.500
It applies to your working repo, which is cool.

00:05:46.500 --> 00:05:46.980
Yeah.

00:05:46.980 --> 00:05:49.360
The applying to the working one, that's really cool.

00:05:50.400 --> 00:05:55.720
I mean, you said that mergers are pretty easy, but actually, I think I'll probably use this for mergers the most.

00:05:55.720 --> 00:06:00.280
Because there's a lot of times where I have a mental model of what my repo looks like.

00:06:00.280 --> 00:06:03.360
And a merge shows a conflict or something.

00:06:03.360 --> 00:06:05.080
And I'm like, why would it be a conflict?

00:06:05.080 --> 00:06:06.580
That's a good point, actually.

00:06:06.580 --> 00:06:11.640
And it's probably because my mental image of what the repo looks like right now is wrong.

00:06:11.640 --> 00:06:15.820
That something has moved forward since I branched off of it or something.

00:06:15.820 --> 00:06:16.140
Yeah.

00:06:16.140 --> 00:06:16.740
Yeah.

00:06:16.740 --> 00:06:17.340
Very good point.

00:06:17.340 --> 00:06:19.440
Actually, I end up confused sometimes.

00:06:19.440 --> 00:06:22.200
That should have gone a clean merge.

00:06:22.200 --> 00:06:22.940
No problem.

00:06:22.940 --> 00:06:28.540
And now I'm in some situation where it's asking me to describe the changes, and I actually don't know what they are.

00:06:28.540 --> 00:06:30.300
So let's start digging in.

00:06:30.300 --> 00:06:32.860
And then sometimes you've got to like, manual merge?

00:06:32.860 --> 00:06:33.680
What is this?

00:06:33.680 --> 00:06:34.400
1980?

00:06:34.400 --> 00:06:35.800
Exactly.

00:06:35.800 --> 00:06:36.440
What are we using?

00:06:36.440 --> 00:06:37.080
CVS?

00:06:37.080 --> 00:06:37.480
Come on.

00:06:37.480 --> 00:06:37.880
Let's go.

00:06:37.880 --> 00:06:40.580
Anyway, this is what I got.

00:06:40.580 --> 00:06:41.100
Git.

00:06:41.100 --> 00:06:42.460
Git Sim.

00:06:42.460 --> 00:06:42.900
Nice.

00:06:42.900 --> 00:06:46.800
Well, so I guess we're kind of doing a tools thing, at least for now.

00:06:46.800 --> 00:06:48.960
I'd like to talk about Nox.

00:06:48.960 --> 00:06:51.280
So have you used Nox?

00:06:51.280 --> 00:06:52.220
I have not.

00:06:52.220 --> 00:06:52.600
Okay.

00:06:52.600 --> 00:06:56.280
So there's Nox, and then there's Tox.

00:06:56.280 --> 00:06:59.500
And I have used Tox a lot.

00:06:59.500 --> 00:07:04.200
So both of them, I guess, they do have different things that you can use them for and stuff.

00:07:04.200 --> 00:07:05.480
What do I use them for?

00:07:05.560 --> 00:07:09.340
I use them primarily to run pytest on multiple versions.

00:07:09.340 --> 00:07:14.560
So the general, one of the workflows that works on both of them is I want to create a virtual

00:07:14.560 --> 00:07:20.040
environment with like Python 310, 311, 39, a bunch of different Pythons, create a virtual

00:07:20.040 --> 00:07:25.580
environment, install my package that I am trying to test, and then run that, and then all the

00:07:25.580 --> 00:07:30.200
dependencies, and then run that test suite within that environment.

00:07:30.720 --> 00:07:33.500
So that's kind of a standard thing.

00:07:33.500 --> 00:07:41.240
So my first thought, first when I saw Nox was, so one of the benefits of Nox, Tox uses

00:07:41.240 --> 00:07:43.240
any files for the settings.

00:07:43.240 --> 00:07:47.520
You can also use, it supports Toml now, I think, maybe.

00:07:47.520 --> 00:07:49.960
I think you can do it in PyProject Toml also.

00:07:49.960 --> 00:07:51.180
If not, sorry.

00:07:52.780 --> 00:07:57.360
But the Nox uses just a Python file.

00:07:57.360 --> 00:08:02.180
So you have a Python, I think it's Nox file.py or something like that.

00:08:02.180 --> 00:08:05.620
But it just uses, I could use the example.

00:08:06.180 --> 00:08:09.100
Anyway, it does similar things.

00:08:09.100 --> 00:08:12.040
So Hynek, I'm going to get it wrong, sorry.

00:08:12.040 --> 00:08:19.300
Hynek wrote an article called Why I Like Nox, and he specifically calls out of like, I'm not

00:08:19.300 --> 00:08:20.080
bashing Tox.

00:08:20.080 --> 00:08:23.040
Tox is still awesome, a great team supporting it, and I agree.

00:08:23.040 --> 00:08:25.440
I know a lot of the people that support it.

00:08:25.440 --> 00:08:27.980
But Nox's might be for you as well.

00:08:27.980 --> 00:08:33.460
So here's a person that likes both tools, comparing them, and it's refreshing.

00:08:33.460 --> 00:08:36.060
So first off, it's the file format.

00:08:36.400 --> 00:08:39.520
So Any, Tox uses AnyFiles, Nox uses Python.

00:08:39.520 --> 00:08:44.820
And I got to admit, even for a simple example like this, then the example I'm showing is

00:08:44.820 --> 00:08:49.620
running Python 3.10 and 3.11 and being able to pass in arguments to pytest.

00:08:49.620 --> 00:08:56.160
Both are not terrible, but I think maybe the Nox one's a little bit more readable just because

00:08:56.160 --> 00:08:56.660
it's Python.

00:08:56.660 --> 00:09:00.920
It's definitely more flexible because you could run arbitrary Python code in addition to

00:09:00.920 --> 00:09:04.860
some sort of setup, teardown, beyond pytest itself.

00:09:05.100 --> 00:09:05.580
Similar.

00:09:05.580 --> 00:09:12.520
And then he gets into another example, which is a little bit more involved, which is I've

00:09:12.520 --> 00:09:18.920
got a test matrix, but I also, different Pythons, but I want to be able to run the oldest adder's

00:09:18.920 --> 00:09:23.320
version against whatever Python environment I'm running.

00:09:23.760 --> 00:09:29.380
And he claims that he, and I haven't tried this out, that it's actually, he doesn't know why

00:09:29.380 --> 00:09:31.540
it isn't working, but it's just, it doesn't work.

00:09:31.540 --> 00:09:35.220
And I'm, you know, I can't help him out there.

00:09:35.220 --> 00:09:42.500
But then he switches to Nox and it's a lot longer example, but it works great.

00:09:43.160 --> 00:09:50.600
And the longerness, the longerness I kind of like, and Hinnick points out in terms of

00:09:50.600 --> 00:09:55.360
number of lines, it's longer than the Tox equivalent, but that's because it's more explicit.

00:09:55.360 --> 00:10:00.600
And anyone with a passing understanding of Python can deduce what's happening here, including

00:10:00.600 --> 00:10:01.780
myself a year from now.

00:10:01.780 --> 00:10:03.580
Explicit can be good actually.

00:10:03.580 --> 00:10:07.620
So I kind of like that, that the, it's okay that it's longer.

00:10:07.620 --> 00:10:11.740
You're not reading it all the time and having it more verbose might help.

00:10:11.740 --> 00:10:13.260
So I like that.

00:10:13.260 --> 00:10:16.200
And then of course you brought this up, the power of the snake.

00:10:16.200 --> 00:10:19.260
You can run, you can run anything you want.

00:10:19.260 --> 00:10:20.180
It's Python code.

00:10:20.180 --> 00:10:21.460
So that's nice.

00:10:21.460 --> 00:10:27.240
And then one bonus thing is apparently it's a little easier to specify versions that Nox has

00:10:27.240 --> 00:10:31.000
a --Python and you can pick the version you want to use like that.

00:10:31.000 --> 00:10:31.980
And it just looks normal.

00:10:31.980 --> 00:10:38.740
You can do that with Tox too, but the normal way to do it is to say what, like PI 310, which

00:10:38.740 --> 00:10:40.360
you just have to know the syntax.

00:10:40.360 --> 00:10:41.860
It's not terrible, but whatever.

00:10:41.860 --> 00:10:42.640
Yeah.

00:10:42.640 --> 00:10:45.540
So good, good overview of Nox.

00:10:45.540 --> 00:10:46.080
Yeah.

00:10:46.080 --> 00:10:50.080
It didn't really, I guess I didn't realize that Nox was playing Python.

00:10:50.080 --> 00:10:52.980
I'm sure that I knew that at one point, but forgot about it.

00:10:52.980 --> 00:10:54.900
That looks, that is an interesting advantage.

00:10:54.900 --> 00:10:55.460
Yeah.

00:10:55.460 --> 00:10:55.920
Yeah.

00:10:55.920 --> 00:10:57.500
So I think I want to play it with a little bit more.

00:10:58.080 --> 00:11:03.360
And I, the, he points out as also that he's not switching completely over to Nox,

00:11:03.360 --> 00:11:06.540
but he does have some projects using Tox and some using Nox.

00:11:06.540 --> 00:11:06.880
It's good.

00:11:06.880 --> 00:11:07.240
There's two.

00:11:07.240 --> 00:11:07.580
Yeah.

00:11:07.580 --> 00:11:08.320
And they rhyme.

00:11:08.540 --> 00:11:08.840
All right.

00:11:08.840 --> 00:11:10.960
How about our sponsor this week?

00:11:10.960 --> 00:11:11.840
Oh, yes.

00:11:11.840 --> 00:11:13.060
Thank you to Python.

00:11:13.060 --> 00:11:17.320
This episode of Python Bytes is brought to you by Microsoft for Startups.

00:11:17.320 --> 00:11:22.300
Microsoft for Startups has built Founders Hub to help startups be successful.

00:11:22.300 --> 00:11:27.260
Founders Hub provides founders at any stage with free resources to help solve startup challenges.

00:11:27.780 --> 00:11:36.100
The digital platform provides technology benefits, access to expert guidance, skilling resources, mentorship, networking connections, and so much more.

00:11:36.100 --> 00:11:37.900
It is truly open to all.

00:11:37.900 --> 00:11:50.020
Along with free access to GitHub and Microsoft Cloud, with the ability to unlock credits over time, Founders Hub has also partnered with other innovative companies to provide exclusive benefits and discounts, including OpenAI.

00:11:50.520 --> 00:11:56.120
And we've heard from one of our listeners that he's taken advantage of this already, and the discounts are awesome.

00:11:56.120 --> 00:12:02.960
You'll also have access to their mentorship network, giving you access to a pool of hundreds of mentors across a range of disciplines.

00:12:02.960 --> 00:12:08.220
You'll be able to book a one-on-one meeting with the mentors, many of whom are former founders themselves.

00:12:08.220 --> 00:12:14.600
Make your ideas a reality today with the critical support you'll get from Microsoft for Startups, Founders Hub.

00:12:14.600 --> 00:12:19.060
To join the program, visit pythonbytes.fm/foundershub 2022.

00:12:19.620 --> 00:12:20.800
The link is in your show notes.

00:12:20.800 --> 00:12:21.320
Ooh.

00:12:21.320 --> 00:12:21.920
Indeed.

00:12:21.920 --> 00:12:22.620
Indeed, indeed.

00:12:22.620 --> 00:12:23.220
Thank you, Microsoft.

00:12:23.220 --> 00:12:23.880
All right.

00:12:23.880 --> 00:12:24.680
Ready for the next one?

00:12:24.680 --> 00:12:25.320
Yes.

00:12:25.320 --> 00:12:26.220
Not that one.

00:12:26.220 --> 00:12:30.320
So this comes from Tom's corner of the internet.

00:12:30.320 --> 00:12:31.860
Tom's got his own corner.

00:12:31.860 --> 00:12:33.380
Yeah, got a very own corner.

00:12:33.380 --> 00:12:36.580
There's a lot of corners of the internet, to be honest.

00:12:36.580 --> 00:12:40.820
I don't know how many dimensions that is, but many, many corners exist in the internet.

00:12:40.820 --> 00:12:42.320
And here's one of them from Tom.

00:12:42.320 --> 00:12:49.280
And Tom says, don't think the tools he's using here are exactly about Python, but what he is.

00:12:49.440 --> 00:12:51.300
applying them to certainly is.

00:12:51.300 --> 00:12:58.520
It says, I scanned every package on PyPI and found 57 live AWS keys.

00:12:58.520 --> 00:13:01.580
Not just, oh, that looks like a string that could be an AWS key.

00:13:01.580 --> 00:13:03.480
He logged in as that person.

00:13:03.480 --> 00:13:04.520
Oh.

00:13:05.000 --> 00:13:06.200
This is not on GitHub.

00:13:06.200 --> 00:13:08.320
I want to emphasize, this is on PyPI.

00:13:08.320 --> 00:13:09.840
So pip install.

00:13:09.840 --> 00:13:13.340
Hey, look, thanks for shipping me a version of your keys.

00:13:13.340 --> 00:13:14.200
Weird.

00:13:14.200 --> 00:13:15.280
Weird indeed.

00:13:15.720 --> 00:13:22.940
So it says, after I inadvertently found that Infosys leaked AWS keys on PyPI, I have thought,

00:13:22.940 --> 00:13:26.220
well, if it's once, it's probably many times, right?

00:13:26.220 --> 00:13:27.440
They're probably not the only one.

00:13:27.440 --> 00:13:32.240
So after scanning, get this, all 430,000 published.

00:13:32.240 --> 00:13:35.560
Well, no, actually, I think that's releases.

00:13:35.560 --> 00:13:40.540
There's 430,000 packages, but there's 4.1 million releases.

00:13:40.660 --> 00:13:44.000
So I think he scanned all the version history as well.

00:13:44.000 --> 00:13:44.460
Okay.

00:13:44.460 --> 00:13:45.760
Somebody found them and took them out.

00:13:45.760 --> 00:13:51.820
Anyway, after scanning those, I found 57 valid access keys from, you know, organizations.

00:13:52.140 --> 00:13:56.120
I'm sure that they're new at working with the cloud and especially AWS.

00:13:56.120 --> 00:13:56.940
It is tricky.

00:13:56.940 --> 00:14:06.320
So these organizations may not be familiar with the rules, but Amazon leaked their own AWS keys.

00:14:06.320 --> 00:14:08.120
That was the joke.

00:14:08.120 --> 00:14:09.060
The rest, not so much.

00:14:09.060 --> 00:14:13.580
But Intel, Stanford, Portland, and Louisiana universities, keeping it local.

00:14:13.580 --> 00:14:14.960
The Australian government.

00:14:14.960 --> 00:14:16.000
Thank you for that.

00:14:16.000 --> 00:14:20.240
General Atomics Fusion Development, Teradata, Data Lake.

00:14:20.780 --> 00:14:23.600
And yes, your gloves too have been leaked.

00:14:23.600 --> 00:14:26.200
Top Glove, the world's largest glove manufacturer.

00:14:26.200 --> 00:14:27.700
I love the emoji.

00:14:27.700 --> 00:14:29.460
A little glove.

00:14:29.460 --> 00:14:31.420
There's a glove emoji at the end of that title.

00:14:31.420 --> 00:14:32.540
So here, like, check this out.

00:14:32.540 --> 00:14:40.020
If I click on Australian government, it takes us to inspector.pypi.io, which I didn't really know anything about.

00:14:40.020 --> 00:14:46.620
Then it links to data cube dash OWS version 186.

00:14:46.620 --> 00:14:50.160
And pulls it down into WSGI local PyPI.

00:14:50.700 --> 00:14:53.620
Brian, what does the comment say?

00:14:53.620 --> 00:14:54.560
Do not commit.

00:14:54.560 --> 00:14:56.800
AWS Qs do not commit.

00:14:56.800 --> 00:14:58.320
Not only are they committed.

00:14:58.320 --> 00:14:59.320
You know what?

00:14:59.320 --> 00:15:01.320
Here's the thing that's interesting, okay?

00:15:01.320 --> 00:15:09.740
They may not be committed to GitHub, but they may have forgotten to take them out when they did the build step to build the wheel.

00:15:10.020 --> 00:15:13.280
And then they comment them out or somehow remove them from going to GitHub.

00:15:13.280 --> 00:15:14.320
And that's...

00:15:14.320 --> 00:15:16.820
Oh, I could totally see how this could be easily done.

00:15:16.820 --> 00:15:22.300
Because you have to go through an extra step to push from GitHub to PyPI.

00:15:22.840 --> 00:15:28.580
A more natural beginner state is you publish to GitHub and you publish to PyPI.

00:15:28.580 --> 00:15:29.920
Yeah, exactly.

00:15:29.920 --> 00:15:31.100
It's very...

00:15:31.100 --> 00:15:36.260
If you haven't set up full end-to-end automation that does the publish for you, which I think a lot of people haven't.

00:15:36.260 --> 00:15:36.640
Yeah.

00:15:36.800 --> 00:15:39.120
You know, it's easy to have this happen.

00:15:39.120 --> 00:15:39.600
All right.

00:15:39.600 --> 00:15:40.880
So let's go through this real quick here.

00:15:40.880 --> 00:15:41.980
So how do we do this?

00:15:41.980 --> 00:15:44.740
Detecting AWS keys is actually pretty simple.

00:15:44.740 --> 00:15:50.040
Did you know that there's a regular expression that is a valid match for AWS keys?

00:15:50.040 --> 00:15:52.840
I thought there was kind of random business, but no.

00:15:52.840 --> 00:15:55.160
There's a certain format that they take.

00:15:55.160 --> 00:15:57.800
So you can tell this is not just A key.

00:15:57.800 --> 00:15:59.540
It is an AWS key ID.

00:15:59.540 --> 00:16:00.480
Oh, cool.

00:16:00.480 --> 00:16:03.100
So now I know how to search for them in other people's repos.

00:16:03.100 --> 00:16:06.300
I feel like this would be a pretty awesome pre-commit hook.

00:16:06.300 --> 00:16:16.180
And, you know, there's tools like Twine and others that people use to build their packages that get shipped to PyPI.

00:16:16.180 --> 00:16:16.640
Yeah.

00:16:16.640 --> 00:16:18.000
And PyPI itself.

00:16:18.000 --> 00:16:22.240
All of those could start applying checks for this kind of stuff, right?

00:16:22.460 --> 00:16:25.800
Because GitHub access keys have a certain pattern now.

00:16:25.800 --> 00:16:26.360
I don't remember.

00:16:26.360 --> 00:16:30.200
There's like, there's some prefix that they seem to have that looks like it's predictable.

00:16:30.200 --> 00:16:36.820
I feel like maybe, maybe this could be put into the supply chain pipeline, as they call it.

00:16:36.820 --> 00:16:40.300
But anyway, there's a regular expression you can run against to find them.

00:16:40.300 --> 00:16:41.160
And here we go.

00:16:41.160 --> 00:16:45.600
So we can use the amazing ripgrep to search packages for this pattern.

00:16:45.600 --> 00:16:46.500
And look at that.

00:16:46.500 --> 00:16:47.060
Here we go.

00:16:47.060 --> 00:16:52.060
You pull down this, this gzip file, and then you ripgrep it.

00:16:52.060 --> 00:16:54.720
And boom, out comes the access keys.

00:16:54.720 --> 00:16:55.320
Whoopsie.

00:16:55.320 --> 00:16:58.320
Apparently Amazon pay at this point here.

00:16:58.320 --> 00:17:02.240
But just because the keys are present, are they valid?

00:17:02.240 --> 00:17:03.000
I don't know.

00:17:03.000 --> 00:17:10.320
So the next step shows you how to execute the AWS CLI command to get the caller identity to see if it's actually valid.

00:17:10.320 --> 00:17:11.140
Right?

00:17:11.400 --> 00:17:11.540
Okay.

00:17:11.540 --> 00:17:13.820
So it says, now the devil's in the details.

00:17:13.820 --> 00:17:16.960
The Z dash Z flag doesn't support searching zips.

00:17:16.960 --> 00:17:18.800
So let's go.

00:17:18.800 --> 00:17:20.920
Let's go and tear this up.

00:17:20.920 --> 00:17:27.940
And points out, you can get the entire over at GitHub.com or F PyPI dash data.

00:17:28.060 --> 00:17:30.560
You get the entire static dump of PyPI data.

00:17:30.560 --> 00:17:31.160
Oh, nice.

00:17:31.160 --> 00:17:31.800
Did you know this existed?

00:17:31.800 --> 00:17:32.780
I had no idea.

00:17:32.780 --> 00:17:33.860
So I'm like, wait a minute.

00:17:33.860 --> 00:17:34.640
Let's go check this out.

00:17:34.640 --> 00:17:35.860
PyPI dash data.

00:17:35.860 --> 00:17:37.580
This is automatically updated.

00:17:37.580 --> 00:17:40.620
PyPI API data available in bulk.

00:17:40.620 --> 00:17:43.140
So the contents of the entire.

00:17:43.140 --> 00:17:43.780
How big is this?

00:17:43.780 --> 00:17:46.640
It's not small.

00:17:46.640 --> 00:17:50.140
See the shallow checkout, perhaps.

00:17:50.140 --> 00:17:57.220
The contents of the entire PyPI JSON API for all packages updated every 12 hours.

00:17:57.220 --> 00:17:57.760
Wow.

00:17:57.760 --> 00:17:58.480
Yeah.

00:17:58.480 --> 00:18:03.160
So it says, for example, here's the JSON for Django.

00:18:03.160 --> 00:18:05.600
So anyway, I didn't know that exists.

00:18:05.600 --> 00:18:07.360
That's pretty awesome.

00:18:07.360 --> 00:18:10.320
Then he set up a GitHub action to pull those down.

00:18:11.180 --> 00:18:13.060
Then GitHub actions.

00:18:13.060 --> 00:18:13.920
Let's see.

00:18:13.920 --> 00:18:20.100
GitHub secret scanning service will kick in and let AWS know that the keys are leaked.

00:18:20.100 --> 00:18:24.740
This will cause AWS to open a support ticket with you to notify that your keys are leaked,

00:18:24.740 --> 00:18:28.320
which is kind of an interesting chain of events that happens here.

00:18:28.320 --> 00:18:32.440
But it talks about how old the keys might be.

00:18:32.440 --> 00:18:35.520
The oldest one is from 10 years old from 2013.

00:18:35.520 --> 00:18:38.400
And different reasons this happens.

00:18:38.640 --> 00:18:42.000
It's hard, for example, to test against AWS.

00:18:42.000 --> 00:18:46.720
Another reason that they say is like there's legitimate and quote uses.

00:18:46.720 --> 00:18:49.560
One of the things they talk about is, you know, why is this happening?

00:18:49.560 --> 00:18:55.900
And Python being super heavily used in data science and ML, a lot of folks come from that

00:18:55.900 --> 00:18:59.620
side of the world without super strong software engineering practices.

00:18:59.860 --> 00:19:05.540
And so maybe, you know, coming from economy and being an economist, you're like, oh, I got

00:19:05.540 --> 00:19:06.100
this thing working.

00:19:06.100 --> 00:19:07.760
Let me publish this up to help people.

00:19:07.760 --> 00:19:08.260
Right.

00:19:08.260 --> 00:19:12.160
It's really easy that you didn't really think about some of these things.

00:19:12.160 --> 00:19:12.460
Right.

00:19:12.680 --> 00:19:15.660
But basically, don't put your secrets in your source code.

00:19:15.660 --> 00:19:16.860
Don't put them in GitHub.

00:19:16.860 --> 00:19:20.500
And, you know, don't buy the transitive property.

00:19:20.500 --> 00:19:21.700
Put them in PyPI either.

00:19:21.700 --> 00:19:22.140
Yeah.

00:19:22.140 --> 00:19:22.540
Yeah.

00:19:22.540 --> 00:19:24.060
So anyway, what do you think?

00:19:24.700 --> 00:19:28.300
I think it's a head shaker, but interesting.

00:19:28.300 --> 00:19:31.900
We need like stickers made up for laptops.

00:19:31.900 --> 00:19:33.060
Do you know where your keys are?

00:19:33.060 --> 00:19:34.560
Exactly.

00:19:34.560 --> 00:19:35.980
It's 10 p.m.

00:19:35.980 --> 00:19:37.120
Do you know where your keys are?

00:19:37.120 --> 00:19:39.040
Yes.

00:19:39.040 --> 00:19:41.180
They said they're sleeping at their friend's house.

00:19:41.180 --> 00:19:42.280
They're actually at a frat party.

00:19:42.280 --> 00:19:43.300
Okay.

00:19:44.140 --> 00:19:44.300
Yeah.

00:19:44.300 --> 00:19:49.040
So the article is like missing one step and that's how to how to set up a Bitcoin miner

00:19:49.040 --> 00:19:50.460
on all these keys that you.

00:19:50.460 --> 00:19:54.880
That's left as an exercise to the user.

00:19:54.880 --> 00:19:58.360
By the way, nice little Hugo website here.

00:19:58.360 --> 00:19:59.940
Got to give a little shout out to that.

00:19:59.940 --> 00:20:01.100
And I know we both like our Hugo.

00:20:01.100 --> 00:20:01.720
Okay.

00:20:01.720 --> 00:20:02.820
That's it for this one.

00:20:02.820 --> 00:20:03.200
Okay.

00:20:03.200 --> 00:20:05.040
What's your final one for us?

00:20:05.040 --> 00:20:06.800
I've got a hypothesis.

00:20:06.800 --> 00:20:09.140
So I get actually asked this a lot.

00:20:09.140 --> 00:20:11.820
I do like hypothesis, but it's a little overwhelming.

00:20:11.820 --> 00:20:15.700
I get asked, so what do you think about hypothesis or something like that?

00:20:15.700 --> 00:20:16.480
Or do whatever?

00:20:16.480 --> 00:20:17.020
Yes.

00:20:17.020 --> 00:20:17.920
I use hypothesis.

00:20:17.920 --> 00:20:20.860
I do like it, but it is, it can be overwhelming.

00:20:20.860 --> 00:20:25.260
So we're going to take a look at an article called getting started with property based testing

00:20:25.260 --> 00:20:28.080
in Python with hypothesis and py test.

00:20:28.080 --> 00:20:33.420
And this is from Rodrigo and I'm not going to try the rest of the name.

00:20:33.420 --> 00:20:34.780
Rodrigo.

00:20:34.780 --> 00:20:35.160
Maybe.

00:20:35.160 --> 00:20:36.160
Yeah, I'm not.

00:20:36.160 --> 00:20:36.600
Sorry.

00:20:36.600 --> 00:20:37.620
Cool name.

00:20:37.620 --> 00:20:39.260
Saro.

00:20:39.260 --> 00:20:40.160
Yeah.

00:20:40.160 --> 00:20:42.400
Anyway, it's on the semaphore blog.

00:20:42.400 --> 00:20:46.940
And there's a lot of what I like about this article.

00:20:46.940 --> 00:20:54.460
And the, well, first off, what I really like about property based testing is not that, I

00:20:54.460 --> 00:20:58.300
mean, it can find some bugs in your code and that's, that's kind of what it's for.

00:20:58.300 --> 00:21:00.680
And it's good, but it also makes you think about it.

00:21:00.680 --> 00:21:06.460
So thinking about a few examples to test your code and corner cases and all that stuff is

00:21:06.460 --> 00:21:10.660
good to say, you know, how do I, how do I know if my code's working, but with property

00:21:10.660 --> 00:21:15.580
based testing, especially, and I think a good place to focus this on is algorithmic

00:21:15.580 --> 00:21:16.000
stuff.

00:21:16.000 --> 00:21:21.900
So you've got like some type of some algorithm and insider in a function, and you really want

00:21:21.900 --> 00:21:25.260
to make sure that that's just solid, no matter what you throw at it.

00:21:25.260 --> 00:21:27.500
And so that's a great place for property based testing.

00:21:27.500 --> 00:21:32.320
But how, what you do is you think about, you have to think about what properties are true

00:21:32.320 --> 00:21:36.360
because what hypothesis is going to do is it going to throw a bunch of input at your function.

00:21:36.360 --> 00:21:41.660
And you, so you have to think, how do I tell if I don't know what the input is, if the answer

00:21:41.660 --> 00:21:42.260
is correct?

00:21:42.260 --> 00:21:47.760
Because if you know the input, you, you can like calculate it yourself, whether the answer

00:21:47.760 --> 00:21:49.060
is correct or not or something.

00:21:49.460 --> 00:21:52.400
But without that, you're thinking in properties.

00:21:52.400 --> 00:21:54.380
And so I love this article.

00:21:54.380 --> 00:21:58.200
The first, the script, the example, it goes through two examples.

00:21:58.200 --> 00:22:05.860
The first example is a greatest common denominator in math problem of like thinking about, I mean,

00:22:05.860 --> 00:22:11.400
you can just like have some known problems that you know the answer to and pull those out.

00:22:11.400 --> 00:22:11.940
That's great.

00:22:12.100 --> 00:22:14.580
But how would you test like for every number?

00:22:14.580 --> 00:22:19.800
And so going through a couple, thinking about what to test is great.

00:22:19.800 --> 00:22:21.120
What did he talk about?

00:22:21.120 --> 00:22:25.340
For greatest common denominator, your answer is going to be positive.

00:22:25.340 --> 00:22:31.400
And the answer needs to divide both, both of the numbers, right?

00:22:31.400 --> 00:22:32.980
That's kind of the point of it.

00:22:32.980 --> 00:22:35.340
But then how do you know if it's the right one?

00:22:35.340 --> 00:22:40.660
Well, no other number larger than your answer is going to be able to divide N and M.

00:22:40.660 --> 00:22:44.660
So it's kind of you're going to end up doing kind of an exhaustive search a little bit.

00:22:44.660 --> 00:22:45.640
But that's OK.

00:22:45.640 --> 00:22:47.160
It's it's it's source code.

00:22:47.160 --> 00:22:48.120
It'll run.

00:22:48.120 --> 00:22:49.120
Shouldn't be too long.

00:22:49.120 --> 00:22:54.200
And the other thing hypothesis do does, which I didn't know at first, is it's pretty good

00:22:54.200 --> 00:22:56.580
at picking numbers that will probably break your code.

00:22:56.580 --> 00:22:59.640
And by default, it only picks 100 numbers.

00:22:59.640 --> 00:23:01.680
It only picks up 100 test cases.

00:23:01.680 --> 00:23:09.060
And the limit is important because often your your sample size that you could test is infinite.

00:23:09.220 --> 00:23:11.700
So you don't want it to just run forever.

00:23:11.700 --> 00:23:15.140
You want it to be some constraints on it.

00:23:15.140 --> 00:23:20.000
So the it goes through this example coming up with how to test that.

00:23:20.000 --> 00:23:22.040
So it writes a test and then how to plug.

00:23:22.040 --> 00:23:24.180
How do you plug hypothesis into it?

00:23:24.180 --> 00:23:28.180
So you've got given and strategies is often used.

00:23:28.600 --> 00:23:36.020
And so you you put a decorator on your test, say, given strategy integers for both the input

00:23:36.020 --> 00:23:39.520
and of N and M test to make sure.

00:23:39.520 --> 00:23:43.740
And then you run you run your your function and then test stuff around it.

00:23:43.740 --> 00:23:46.820
And the test is listed up higher in the code.

00:23:46.820 --> 00:23:50.200
And then quickly, you're going to find problems.

00:23:50.200 --> 00:23:55.140
And I like I like the greatest common divisor because there are test cases that you that don't

00:23:55.140 --> 00:23:56.500
work, which is great.

00:23:56.500 --> 00:24:03.460
Like zero zero, you know, by definition, we don't if both of them are zero, it's undefined.

00:24:03.460 --> 00:24:08.580
And if one of them zero, it's defined to be the other one, which I actually didn't know.

00:24:08.580 --> 00:24:10.100
I'm like, really, is that true?

00:24:10.100 --> 00:24:10.980
I looked it up.

00:24:10.980 --> 00:24:12.440
And I didn't think about that either.

00:24:12.440 --> 00:24:12.740
Yeah.

00:24:12.740 --> 00:24:18.740
So apparently, if you the greatest common divisor of zero and five is five, which who knew?

00:24:19.140 --> 00:24:25.540
But aside from that, so coming up with edge cases is probably good for algorithmic type

00:24:25.540 --> 00:24:26.320
of code anyway.

00:24:26.320 --> 00:24:30.220
And then the example of zero zero, how do you get rid of that?

00:24:30.220 --> 00:24:34.480
So in this, I guess this is one of my caveats about this article.

00:24:34.480 --> 00:24:38.320
He talks about limiting the range, which it's good.

00:24:38.320 --> 00:24:41.560
It's a good example, because you're going to want to do this in a lot of your test cases

00:24:41.560 --> 00:24:42.660
is limit the range.

00:24:42.660 --> 00:24:45.120
So you can put a min and max on different things.

00:24:45.120 --> 00:24:46.480
And there's a lot more than numbers.

00:24:46.480 --> 00:24:49.040
You can do text and you can do all sorts of stuff with hypothesis.

00:24:49.280 --> 00:24:51.720
But I think good starting with numbers is a good one.

00:24:51.720 --> 00:24:54.300
I just don't like the solution that he came up with.

00:24:54.300 --> 00:25:00.360
The solution he came up with is limit one of them from one to 100 so that you're never

00:25:00.360 --> 00:25:01.300
going to have zero zero.

00:25:01.300 --> 00:25:06.860
And I'm like, I personally would have used a different mechanism.

00:25:06.860 --> 00:25:11.280
So my recommendation is a there's a strategy called.

00:25:11.280 --> 00:25:15.000
So, oh, not strategies, making assumptions.

00:25:15.000 --> 00:25:17.880
So there's a thing in hypothesis called assume.

00:25:18.180 --> 00:25:23.460
And you can say within a test, you can say assume something.

00:25:23.460 --> 00:25:26.860
Assume it's just like an assert, but it doesn't fail your test.

00:25:26.860 --> 00:25:31.140
If it fails, the it rejects the test case is how it works.

00:25:31.140 --> 00:25:39.460
So you can say for the zero zero case, you can say assume n equals is not equal to or assume

00:25:39.460 --> 00:25:41.920
not n equals m equals zero.

00:25:41.920 --> 00:25:44.360
It's hard to do this without code.

00:25:44.500 --> 00:25:47.880
But you can make an assumption there so that it'll kick that one out.

00:25:47.880 --> 00:25:49.080
That's how I would have done that.

00:25:49.080 --> 00:25:55.220
But other than that, it's a really great introduction to the how to work with property based testing.

00:25:55.220 --> 00:25:57.400
So I give it a thumbs up.

00:25:57.400 --> 00:25:59.540
Then there's a second example, which is nice, too.

00:25:59.540 --> 00:26:00.680
So that's cool.

00:26:00.680 --> 00:26:02.100
I didn't know about assume.

00:26:02.100 --> 00:26:03.700
So I'm very good to know about that.

00:26:03.780 --> 00:26:08.220
The other thing that I think is a good thing to know about is example.

00:26:08.220 --> 00:26:10.060
So like the example zero zero.

00:26:10.060 --> 00:26:14.080
We specifically don't want to test that because we know it's broken or it's not defined.

00:26:14.080 --> 00:26:19.140
But there are lots of cases where you're like, you know, somebody you're doing property based

00:26:19.140 --> 00:26:23.480
testing on something and you get a defect of like, well, if I run these numbers, it fails.

00:26:23.480 --> 00:26:26.440
And you're like, oh, well, we want to make sure we always run that.

00:26:26.440 --> 00:26:29.920
So with example, you can say hypothesis.

00:26:29.920 --> 00:26:33.520
You get to come up with the examples, except for always run this one also.

00:26:33.520 --> 00:26:36.000
So and you can just kind of stack them up.

00:26:36.000 --> 00:26:36.560
That's good.

00:26:36.560 --> 00:26:36.900
Yeah.

00:26:36.900 --> 00:26:41.960
And so for people listening, example is a decorator you put on your test at example and you put

00:26:41.960 --> 00:26:44.000
a certain set of parameters that get called there.

00:26:44.000 --> 00:26:46.400
Yeah, I just I kind of don't like that.

00:26:46.400 --> 00:26:51.640
So examples is a decorator that you put on the outside to say, run this one always.

00:26:51.640 --> 00:26:56.220
I'd like the reverse also to say this particular example, don't run it.

00:26:56.220 --> 00:26:57.520
Because I know it's broken.

00:26:57.520 --> 00:27:02.780
And the I mean, we get around it with the assume part, but it would be cool if there

00:27:02.780 --> 00:27:04.420
was like a don't run this example.

00:27:04.420 --> 00:27:05.020
Yeah.

00:27:05.020 --> 00:27:05.480
Yeah.

00:27:05.480 --> 00:27:06.140
It looks very helpful.

00:27:06.140 --> 00:27:07.100
And I learned some things.

00:27:07.100 --> 00:27:07.780
So excellent.

00:27:07.780 --> 00:27:08.420
How about you?

00:27:08.420 --> 00:27:09.140
What's next?

00:27:09.140 --> 00:27:11.420
We got extras, extras, extras.

00:27:11.420 --> 00:27:13.100
Are we done with our normal ones?

00:27:13.100 --> 00:27:13.580
Wow.

00:27:13.580 --> 00:27:14.080
Yeah.

00:27:14.080 --> 00:27:15.840
Time flies when you're having fun, you know?

00:27:15.840 --> 00:27:16.140
Yeah.

00:27:16.140 --> 00:27:16.800
All right.

00:27:16.800 --> 00:27:18.020
When we go first, you want to do yours?

00:27:18.020 --> 00:27:20.600
I got a short one.

00:27:20.600 --> 00:27:21.120
All right.

00:27:21.120 --> 00:27:21.540
Go for it.

00:27:21.540 --> 00:27:21.760
OK.

00:27:21.760 --> 00:27:23.780
So my let's let's get rid of that.

00:27:23.780 --> 00:27:24.460
We don't need that.

00:27:25.100 --> 00:27:29.440
My example, my extra is just that this came in the mail and I'm really excited about

00:27:29.440 --> 00:27:29.840
it.

00:27:29.840 --> 00:27:33.740
So it's the Japanese version of Python testing with pytest.

00:27:33.740 --> 00:27:37.840
It's been out for a little while in, I assume, Japan.

00:27:37.840 --> 00:27:42.320
But it got translated.

00:27:42.320 --> 00:27:48.400
I was in touch with the translator and they asked me a few questions.

00:27:48.400 --> 00:27:49.540
Very respectful, dude.

00:27:50.140 --> 00:27:51.120
And I'm glad.

00:27:51.120 --> 00:27:52.520
And I'm like, can I get a copy?

00:27:52.520 --> 00:27:54.740
And they sent me a few copies, actually.

00:27:54.740 --> 00:27:55.760
So pretty exciting.

00:27:55.760 --> 00:27:56.400
Fantastic.

00:27:56.400 --> 00:27:57.420
Oh, that's really cool.

00:27:57.420 --> 00:27:58.860
It's neat to see it.

00:27:58.860 --> 00:28:01.300
It's neat to be reminded of the global reach.

00:28:01.300 --> 00:28:01.920
Yeah.

00:28:01.920 --> 00:28:02.820
And not just the cover.

00:28:02.820 --> 00:28:04.400
The insides are there, too.

00:28:04.400 --> 00:28:06.340
Amazing.

00:28:06.340 --> 00:28:09.520
So you're going to learn Japanese?

00:28:09.520 --> 00:28:10.440
Are you going to figure this out?

00:28:10.520 --> 00:28:14.260
I do have a friend that speaks Japanese, so I'm going to go and see.

00:28:14.260 --> 00:28:15.600
But they don't code.

00:28:15.600 --> 00:28:16.920
Yeah.

00:28:16.920 --> 00:28:17.540
It's all right.

00:28:17.540 --> 00:28:19.780
I'm sure they'll find it riveting anyway.

00:28:19.780 --> 00:28:22.460
Yeah, that's awesome.

00:28:22.460 --> 00:28:23.600
What are your extras?

00:28:24.320 --> 00:28:25.660
Well, a couple of things.

00:28:25.660 --> 00:28:31.360
So it seems like I have survived the very first Python bytes on my new Mac Mini.

00:28:31.360 --> 00:28:35.380
I just got, you know, Apple released the Mac Mini Pro M2, and I got that.

00:28:35.380 --> 00:28:38.020
And so far, super, super neat.

00:28:38.020 --> 00:28:38.760
I can recommend it.

00:28:38.760 --> 00:28:40.880
It's a lot faster than the previous Mini.

00:28:40.880 --> 00:28:45.540
So I mentioned that I used to have money, and then I had a Mini on order.

00:28:45.540 --> 00:28:46.820
And now I actually have a Mini.

00:28:46.820 --> 00:28:47.820
A new Mini.

00:28:47.820 --> 00:28:51.860
It looks identical to the other, but it goes way faster, which is great.

00:28:52.420 --> 00:28:53.820
Maybe I'll have more to say about that later.

00:28:53.820 --> 00:28:54.340
All right.

00:28:54.340 --> 00:28:57.580
So have you heard that Twitter is going through some turmoils?

00:28:57.580 --> 00:28:58.320
I'm not sure.

00:28:58.320 --> 00:29:00.960
I think something's going on over there.

00:29:00.960 --> 00:29:10.920
The latest turmoil is that they decided to unceremoniously, unprofessionally cancel all the third-party Twitter apps.

00:29:10.920 --> 00:29:12.840
That's just insane.

00:29:12.840 --> 00:29:14.420
It's pretty insane.

00:29:14.420 --> 00:29:21.220
I think it's, honestly, I think it's fine within Twitter's right to say, look, we don't want to have third-party apps.

00:29:21.560 --> 00:29:23.380
We have a business model that doesn't work well.

00:29:23.380 --> 00:29:25.380
There's not third-party Facebook apps.

00:29:25.380 --> 00:29:27.660
There's not third-party Instagram apps, are there?

00:29:27.660 --> 00:29:28.480
I don't think so.

00:29:28.480 --> 00:29:30.420
Anyway, I think it's fine.

00:29:30.420 --> 00:29:35.280
But the way that it was done was, oh, we're just going to cut them off.

00:29:35.280 --> 00:29:37.900
And then in a few days, maybe somebody will say something.

00:29:37.900 --> 00:29:45.140
What they said was, the reason we cut off things like TweetBot and other ones is because they violated the terms of service.

00:29:45.140 --> 00:29:47.160
Like, wait, we've been doing this for 10 years.

00:29:47.200 --> 00:29:47.560
What do you mean?

00:29:47.560 --> 00:29:53.160
The reason they violated them is they went back and updated the terms of service to say we don't allow third-party apps.

00:29:53.160 --> 00:29:55.540
That's the human violation of it.

00:29:55.540 --> 00:29:57.120
I mean, it was just really weird.

00:29:57.120 --> 00:30:09.300
Anyway, I want to just direct people who want to, you know, enjoy the moment technically and socially to tapbots.com slash TweetBot, where they put up a memorial to TweetBot.

00:30:09.540 --> 00:30:11.540
Brian, isn't this a fantastic picture?

00:30:11.540 --> 00:30:12.400
It really is.

00:30:12.400 --> 00:30:14.220
There's this little elephant.

00:30:14.220 --> 00:30:17.740
But it's all, like, 3D-looking, like claymation or something.

00:30:17.740 --> 00:30:20.720
Yeah, it does look a little claymation-y.

00:30:20.720 --> 00:30:25.440
And, you know, the mastodon elephant is at the gravestone of TweetBot.

00:30:25.860 --> 00:30:34.240
And it has the life from April 2011 to January 2023 on the gravestone of TweetBot.

00:30:34.240 --> 00:30:36.020
And it's just, anyway, it's pretty interesting.

00:30:36.020 --> 00:30:46.000
The reason, partly I bring this up, not just for the picture, is if you're into mastodon, the same company decided, well, we're doubling down on mastodon and creating ivory,

00:30:46.000 --> 00:30:54.560
which there's been a ton of talk about ivory being a really cool app for if you want something better than, say, the progressive web app for mastodon.

00:30:54.560 --> 00:31:00.320
I know there are others out there as well, but a lot of people are really big fans of TweetBot and TapBot's the company.

00:31:00.320 --> 00:31:03.540
And so you can now, this is now publicly available.

00:31:03.540 --> 00:31:05.540
So there's that.

00:31:05.540 --> 00:31:07.540
And anyway, I started using it.

00:31:07.540 --> 00:31:08.960
I like it really well.

00:31:08.960 --> 00:31:16.680
I don't use it exclusively over just using the progressive web app because the progressive web app has the advanced view where you have multiple columns.

00:31:16.680 --> 00:31:19.660
You can create searches for hashtags and pin those as columns.

00:31:19.660 --> 00:31:20.400
And it's really nice.

00:31:20.400 --> 00:31:25.040
But this is quite a nice, nice app if you're not kind of doing that advanced view.

00:31:25.040 --> 00:31:29.540
Oh, and by the way, Christopher Tyler has caught something incredible.

00:31:29.540 --> 00:31:30.160
Yeah.

00:31:30.160 --> 00:31:32.440
I have missed this.

00:31:32.440 --> 00:31:37.140
This gravestone in the memorial happens to be on Mars, I think.

00:31:37.140 --> 00:31:38.560
Yeah, it kind of looks like that.

00:31:38.560 --> 00:31:38.680
Right.

00:31:38.680 --> 00:31:39.400
That's awesome.

00:31:39.400 --> 00:31:40.580
Why do you think it's on Mars?

00:31:40.580 --> 00:31:41.240
I don't know.

00:31:41.240 --> 00:31:42.500
Same thing in the simulation.

00:31:42.500 --> 00:31:43.340
We're not sure about that.

00:31:43.340 --> 00:31:45.080
Anyway, check out Ivory.

00:31:45.080 --> 00:31:46.120
People can try that.

00:31:46.120 --> 00:31:48.440
If you're in iOS, that's pretty good.

00:31:48.440 --> 00:31:50.780
One more quick extra.

00:31:50.780 --> 00:31:52.360
PyCon, PyCon, PyCon.

00:31:52.360 --> 00:31:52.940
Yay.

00:31:52.940 --> 00:31:53.640
Yay.

00:31:53.640 --> 00:31:54.960
I'm looking forward to this.

00:31:54.960 --> 00:31:56.420
I got my tickets, Brian.

00:31:56.420 --> 00:31:58.100
I'm going to be there for a week.

00:31:58.100 --> 00:32:01.020
I'm going to try to be cruising around the sprints.

00:32:01.020 --> 00:32:03.440
I might even take a day and try to go skiing.

00:32:03.440 --> 00:32:04.120
I haven't decided.

00:32:04.120 --> 00:32:05.440
We'll see what the weather's like out there.

00:32:05.440 --> 00:32:07.760
But it's in Salt Lake City, of course.

00:32:08.120 --> 00:32:09.560
However, I have news for you.

00:32:09.560 --> 00:32:11.400
I haven't even told you this officially.

00:32:11.400 --> 00:32:12.060
Okay.

00:32:12.060 --> 00:32:20.020
But I have gotten us an official time and place at PyCon to do a live Python Bytes show.

00:32:20.020 --> 00:32:20.600
Yay.

00:32:20.600 --> 00:32:21.240
Awesome.

00:32:21.240 --> 00:32:21.760
Yeah.

00:32:21.760 --> 00:32:26.360
So we've previously kind of run around the first day and looked for somewhere where we

00:32:26.360 --> 00:32:27.600
might be able to do something.

00:32:27.600 --> 00:32:32.700
But we're supposed to have an official room and a time where we could actually live stream

00:32:32.700 --> 00:32:32.840
it.

00:32:32.880 --> 00:32:35.520
We can talk to people ahead of time if they really want, they're going to be there and

00:32:35.520 --> 00:32:36.040
they want to come.

00:32:36.040 --> 00:32:38.800
So we should be able to have a cool event at PyCon.

00:32:38.800 --> 00:32:39.760
That's why I bring this up.

00:32:39.760 --> 00:32:40.260
Yeah.

00:32:40.260 --> 00:32:41.760
And it won't be on Tuesday then.

00:32:41.760 --> 00:32:48.640
No, it won't be on Tuesday because it's Thursday night, Friday, Saturday, Sunday is the conference.

00:32:48.640 --> 00:32:49.860
So it's going to be one of those days.

00:32:49.860 --> 00:32:50.220
Awesome.

00:32:50.560 --> 00:32:51.500
I'm looking forward to that.

00:32:51.500 --> 00:32:52.560
I'll be there too.

00:32:52.560 --> 00:32:55.580
Neither of us are speaking, but we'll do the live event.

00:32:55.580 --> 00:32:58.920
And then Michael's going to probably interview absolutely everybody at the conference.

00:32:58.920 --> 00:33:00.480
Yeah.

00:33:00.480 --> 00:33:02.080
I'm trying something different this year.

00:33:02.080 --> 00:33:08.280
You know, PacPython, primarily for the courses side of things, has had a booth on the expo

00:33:08.280 --> 00:33:13.140
floor hall where I'll set up and meet people and show off the things we're doing.

00:33:13.140 --> 00:33:16.080
And, you know, Brian, you've come a couple of years and hung out there.

00:33:16.080 --> 00:33:19.880
We talked about Python Bytes and that booth as well, which is fantastic.

00:33:20.200 --> 00:33:21.660
This year, I'm not doing that.

00:33:21.660 --> 00:33:27.760
I just want to try to be around, have more, interact with more people and try to maybe do

00:33:27.760 --> 00:33:31.100
some more on the spot shows and some other stuff like that.

00:33:31.100 --> 00:33:31.320
Right.

00:33:31.320 --> 00:33:33.880
So absolutely, we're going to be at PyCon.

00:33:33.880 --> 00:33:37.180
We're going to be doing fun stuff, just not at a booth this time.

00:33:37.180 --> 00:33:39.740
I'm going to try some variations on it this year.

00:33:39.740 --> 00:33:40.360
Yeah.

00:33:40.360 --> 00:33:43.000
And I think a lot of people, I think they should hit us up.

00:33:43.000 --> 00:33:48.940
So especially if you thought about maybe asking to be on one of our shows, either yours or mine

00:33:48.940 --> 00:33:49.560
or this one.

00:33:49.840 --> 00:33:52.600
But you're a little nervous, then this is a great opportunity.

00:33:52.600 --> 00:33:53.880
One, you don't have to be.

00:33:53.880 --> 00:33:55.200
You could just contact us anyway.

00:33:55.200 --> 00:34:00.820
But at PyCon, you can hit us up and say, hey, I was curious if this would fit.

00:34:00.820 --> 00:34:03.720
And in person, sometimes it's easier to talk.

00:34:03.720 --> 00:34:07.140
And I'll be bringing stickers, of course, to promote the book.

00:34:07.980 --> 00:34:09.260
And I'm excited.

00:34:09.260 --> 00:34:12.740
And also, I'll be at PyCascades before PyCon.

00:34:12.740 --> 00:34:14.100
PyCascades is there.

00:34:14.100 --> 00:34:16.180
It's coming up in March.

00:34:16.180 --> 00:34:18.400
And I'm speaking there, too.

00:34:18.400 --> 00:34:20.320
That's in Vancouver, right?

00:34:20.320 --> 00:34:20.600
Yep.

00:34:20.600 --> 00:34:21.420
Vancouver, BC.

00:34:21.420 --> 00:34:22.220
Lovely.

00:34:22.220 --> 00:34:24.620
I've been to the one in Vancouver.

00:34:24.620 --> 00:34:26.340
I think the inaugural one was there.

00:34:26.440 --> 00:34:27.880
And it's really, really nice there.

00:34:27.880 --> 00:34:29.960
So excellent, excellent commerce.

00:34:29.960 --> 00:34:32.500
I told my daughter I'm going and she's like, what's the big deal?

00:34:32.500 --> 00:34:34.000
Vancouver's like 20 minutes away.

00:34:34.000 --> 00:34:35.760
No, different Vancouver.

00:34:36.580 --> 00:34:42.820
For those of you who don't know, the people who explored, the Europeans who explored the

00:34:42.820 --> 00:34:45.140
Pacific Northwest, they didn't have a lot of creativity.

00:34:45.140 --> 00:34:47.880
There's multiple Vancouver's.

00:34:47.880 --> 00:34:49.000
There's like one just by Portland.

00:34:49.000 --> 00:34:50.300
There's one up in BC.

00:34:50.300 --> 00:34:53.240
Mount Hood, one of the most awesome mountains around here.

00:34:53.240 --> 00:34:57.940
It's just named for the friend of some guy back in England who never even was here or looked

00:34:57.940 --> 00:34:58.600
upon the mountain.

00:34:58.600 --> 00:34:58.980
Really?

00:34:58.980 --> 00:35:00.220
Oh, yeah.

00:35:00.220 --> 00:35:02.920
It's awesome in a bad way.

00:35:02.920 --> 00:35:03.860
Okay.

00:35:05.120 --> 00:35:09.980
But yeah, the other, the northern, the Canadian Vancouver is a really nice place to go.

00:35:09.980 --> 00:35:10.460
All right.

00:35:10.460 --> 00:35:11.680
You ready for our joke, Brian?

00:35:11.680 --> 00:35:11.960
Yeah.

00:35:11.960 --> 00:35:15.800
So I feel like you and I can relate to this given our age here.

00:35:15.800 --> 00:35:21.960
There's a post here that says from somebody named Mark the Cat Whisperer, but re-shared

00:35:21.960 --> 00:35:22.840
by Rob Isaac.

00:35:22.840 --> 00:35:29.620
Mark says, I'm a Gen Xer, so I adapt to new technology like a millennial, but I get angry about it like

00:35:29.620 --> 00:35:30.100
a boomer.

00:35:30.100 --> 00:35:32.420
I get that.

00:35:32.420 --> 00:35:33.860
I get that too.

00:35:33.860 --> 00:35:39.420
I'm definitely in the Gen X space and oh my gosh, I have more than one time yelled

00:35:39.420 --> 00:35:40.920
at my, yelled at my computer.

00:35:40.920 --> 00:35:45.720
I find personally the way, like the reason I connected with this joke so well is I get

00:35:45.720 --> 00:35:49.060
mad at other people's technology because I'm like, I know this could be better.

00:35:49.060 --> 00:35:50.540
Why have you not put an index here?

00:35:50.540 --> 00:35:52.060
Why have you not auto-filled this?

00:35:52.060 --> 00:35:55.240
You know, like, just like, I know you could make it better so easily.

00:35:55.240 --> 00:35:56.180
What is wrong with you?

00:35:56.700 --> 00:35:58.440
And then I guess the boomer side.

00:35:58.440 --> 00:35:59.740
Yeah.

00:35:59.740 --> 00:36:03.140
But the joke is Rob says, I didn't come here to be called out like this.

00:36:03.140 --> 00:36:05.900
Funny.

00:36:05.900 --> 00:36:06.400
All right.

00:36:06.400 --> 00:36:07.720
Well, that's what I got for us.

00:36:07.720 --> 00:36:08.020
Nice.

00:36:08.020 --> 00:36:11.340
Well, thanks a lot, Michael, for joining us again today.

00:36:12.040 --> 00:36:16.900
And on this 232, wait, 321st episode.

00:36:16.900 --> 00:36:17.400
Wow.

00:36:17.400 --> 00:36:17.980
Yeah.

00:36:17.980 --> 00:36:19.580
It's like the amazing countdown.

00:36:19.580 --> 00:36:20.540
We just don't know to what.

00:36:20.540 --> 00:36:21.360
Three, two, one.

00:36:21.360 --> 00:36:22.000
Contact.

00:36:22.000 --> 00:36:23.300
It's the future.

00:36:23.300 --> 00:36:25.720
Well, thanks everybody for joining.

00:36:25.720 --> 00:36:27.060
And thanks, Michael.

00:36:27.060 --> 00:36:29.040
And talk to everybody next week.