Python Bytes - #278 Multi-tenant Python applications
Episode Date: April 8, 2022Topics covered in this episode: dunk - a prettier git diff Is your Python code vulnerable to log injection? Building multi tenant applications with Django Should you pre-allocate lists in Python? m...ockaroo and tonic Extras Joke See the full show notes for this episode on the website at pythonbytes.fm/278
Transcript
Discussion (0)
Hello and welcome to Python Bytes, where we deliver Python news and headlines directly
to your earbuds. This is episode 278, recorded April 6th, 2022. I'm Michael Kennedy.
And I'm Brian Akin.
And I'm Vucile Ndobu.
Welcome, Vucile. It's really great to have you here.
You know, I'm really excited and I feel honored to be here. So thanks for the opportunity.
Yeah, it's going to be great to share some Python news with you.
Now, before we jump into all those things, tell us a bit about yourself. What do you do?
What are you into? Firstly, I'd like to say I'm still relatively early on in my career and
I'm from Zimbabwe and we have a small but growing Python community here. And for the long time,
I didn't have any community. So podcasts like your TalkPipe and podcast was the only way I got to connect with community members.
So it's really great to be here.
But on the question of Parkme, I'm a software developer.
I work in the back end.
I work for a company called Ideation.ai.
It's a health tech startup that's building information systems that help clinicians manage patients and hospitals better.
So I work mostly on APIs and microservices using Python, Django, Postgres mostly.
That sounds like a really fun project.
And we know that healthcare needs help and automation and modernization.
So thanks.
That's awesome.
Very cool. All right. Brian, should we kick it off? Yeah, sure. When you talk about getting drunk, what is this? automation and and modernization so thanks that's awesome yeah yeah very cool all right
brian should we kick it off yeah sure when you talk about getting drunk or what is this
getting dunk oh sorry i must have misread that um so this was uh just announced a few days ago
from darren burns um he's he's uh the uh engineer that's helping William, is it Will?
Will, with the rich and everything.
The rich empire.
Yeah.
So this is just really cool because I often wanted the dunk.
He released dunk.
So dunk is a prettier get diff tool
and it uses rich and it's just a command line tool and it's uh it uses rich and it um it's just a command line tool and
it's beautiful um so you just uh even install it and then you do a git diff on something uh could
be one file or it could be uh it's usually a commit right so you do a diff of whatever you
have now or other stuff and it just instead of doing the weird uh like the hard to read the plus minus
plus yeah yeah that thing um it's got these nice uh just this nice colors with rich of like you
know what was added what was green for added red for taken out um and the line numbers it's
beautiful um and he's it's still a work in progress but i'm using it already it's just great
uh this is fantastic when i first looked at this i thought it was like um a gooey window that was
showing but no that's just the terminal yeah um yeah yeah it's pretty cool you know text editor
right yeah definitely some text editors have have something that like this nice but just on the
command line it's super cool.
One of my first questions with it was, sometimes I have a lot of diff stuff, so does this have a pager?
And the answer from Darren was, it does not have a pager, but you can use less-R.
I don't know what the R does, but anyway.
If you pipe get diff to dunk and then pipe it to
less dash R, you've got a diff with a pager. That works for me. I'll just alias that to something.
So yeah, yeah, that's really cool. Anyway, pretty quick, pretty short topic, but for people that are
looking at get diffs a lot, this is a super handy thing to look at. Yeah, this is neat. I usually do
a lot of my diffs in PyCharm,
and it actually looks real similar to that UI.
Husey, what about you?
How do you see your diffs?
Yeah, I do most of my coding in Visual Studio Code,
and I use the Visual Studio GIF viewer for that.
It's pretty similar to this.
Nice. Yeah, this looks great, I think.
Very nice.
Good job here.
Yeah, very nice one. How about we start with some memes?
So we all heard about Log4J, and my favorite one was the take on the XKCD about little Bobby Tables,
the little Jindy we call him or something like that. I can't remember.
But all the jokes aside, here's Homer Simpson,
zero days without log4j CVE. And maybe the best one was that this guy right here, this guy,
he looks like he's probably about 75 or entire and says, upgrading log4j three times wasn't
that stressful, says Dave, 28 years old. But in all seriousness, is there a log for Pi? Is this
something we should consider? And my first thought was, yeah, no, we're good. We don't have this
stupid remote method invocation where you can inject a function call as a string inside of your
log message. But here's Ari Bovenberg
who wrote an article that says,
yeah, it's not anywhere near as severe as that,
but there are some things you should consider.
And so for your consideration,
I present this article and some ideas.
So it says, look, here's the basics of logging.
And this is using Python's built-in logger.
I'm a fan of Logbook and Loguru
and the sort of higher level ISA things.
But nonetheless, here's the basics, right?
So you can log, like say logger.info or trace or whatever, and then put out a message like
hello world.
There's no injection there.
You can also do this thing, which is really the crux of the problem across the board is
you can say, here's a formatted string and the data that formats it so you can put in the problem with log
for j was even if the string was fully evaluated as user input or something um you take some user
input and you fully validate it it still could have it'll still get like reinterpreted for these
remote like trying to find you what machine am i running on or my production or debug like let me
go call this function find out or just call it to hack you but so the python version doesn't have that but
you can do this like format string and pass this context variable thing like pass a data structure
in and in that case some bad stuff can actually happen here right so that's fine says well what
about what if i wrote my as my name instead, or my message, instead of hello, I wrote hello, quote, backslash, and info main user Alice commented something else. And you would pass that over. And what you would end up with is a log message that was supposed to be one line that ends up like two. So that could cause some confusion, right? That might might be problematic it's not going to
result you in being hacked but there's more like denial of service type of thing so like one thing
you could say is well just don't use backslash n like take those out but there are all sorts of
freaky unicode ways to like restructure similar meanings and stuff so another one has to do with
formatting so if you're logging in some information and it's
just a regular F string, that's probably fine. But if what you're logging into the F string,
you can later get evaluated again, passing this like data structure, asking the logger to fill
out the format string. Then you can pass interesting stuff. One of the more interesting ones was you could say percent,
parenthesis, variable name, close parenthesis,
999999999S.
And what that'll do is it'll pad the username
with a gigabyte of white space
and then try to have you write it to the log file.
Okay.
So that's bad, right?
Right, yeah. You could also do things if you knew the data structure
that was being passed in to fill out the log string had you could sort of try to reach out
and get variable names out of it by putting a formatted string in there and if you marry that
with the huge piece of text that'll make the login really slow so you could put in like
different things and if you see oh this message actually makes the request really slow you could
infer that maybe that data is actually in the variable being passed over so then you could try
to get it to write it to a file if you have say file access but not other types of access anyway
so there's a bunch of things so basically this the long story short is don't mix like F string formatting
along with passing more data to the log file.
One or the other,
because the logger knows how to look
for some of these things
when it takes the data and puts it in the format,
but it doesn't do that for the original string.
So careful about mix and match.
Final thing, there's actually been included in a PEP
and there's a discussion on discuss.python.org,
and there's actually a pretty interesting discussion
with a bunch of core devs there.
So you can see that's maybe a better follow-up there.
But pretty interesting.
There's no log for Py,
but that doesn't mean you can just completely go crazy
with unverified user input.
You should trust your users, though.
I know.
Why not? They're so friendly and considerate. Yeah, why not? The real ones are. You know, when this, when this log4j vulnerability
came out and I realized that it wasn't really a big problem in Python, I didn't pay any attention
to it. And now I'm, I'm actually shocked that you could do a denial of service attack using that.
Yeah, exactly. I think that's what it basically becomes is there's two aspects.
One is you can sort of crush the server by having it write so much data.
The other that they pointed out here was if your goal is to try to obscure regular hacking,
if you could wreck the log file with so much data that it's really difficult for people
to parse the log file.
You might be able to hide yourself a little bit better for longer.
So anyway, there's some interesting stuff there.
All right, Vucile, over to you.
Yep.
Thanks.
If you're building a software as a service platform in Python and Django, there are a
few things to think about, you know, like the architecture you're going to use, what
type of database you're going to use,
whether you use a single database or multiple databases and all these things.
So while I was getting ready for this call, I found this book. It's called Building Multi-Tenant Applications with Django. And it's by an author that you've actually covered on the show. It's a
company, I think, called Gin. So this book is free. It's open source. Anyone's free to read it, download it.
And it goes through the different approaches
that you'd have to follow.
I mean, the different architecture designs
that you should consider
when building software as a service
or multi-tenant applications.
And so one of the things they cover here
is EMA where you're using queries
to isolate the data.
Something like Postgres, EMAs can do that.
This book goes over the different approaches you can use to build multi-tenancy apps, right?
And then it also covers some third-party packages that you can install that help do a lot of the boilerplate code for you.
That's really nice.
Because I've considered this.
It'd be so great if you're doing some sort of software as a service type thing where people log in and you want that group just to see all their data and all their records and stuff.
But it's so scary because if you just forget the where clause on just one, they get everybody's data, which is really bad, right?
And so this is really cool.
Yeah. This is really cool. Yeah, this is neat. So the book covers things like using HTTP headers or subdomains in the request to identify different tenants and how you do that, how you capture that using middleware in Django.
That's cool.
So some of the middleware is Django multi-tenant, Django tenant schemas, or Django DB multi-tenant.
Not a ton of variation in the name in there, but it's still pretty cool, right? And some of them use schemas and some of them use
isolated databases, right? Yeah. Yeah. Nice. So it will all depend on what your tolerance for
cost is and database management. So if you don't mind having a database for each client, you could
do that. And then you'd have to do migrations on each database, wherever you make updates to the application,
or you can just want to have a single shared database. You can do that and isolate using
schemas. Yeah. I hadn't thought about having to migrate every separate database, but yeah,
that's a ton of work. But deployment all of a sudden looks really rough, doesn't it?
Yeah. Yeah. But that's true isolation yeah exactly there's no way
you're going to make a mistake there do you guys do anything like this with your health care
products yeah yeah we use one of these approaches i can't tell you which one but uh we we use uh
we use with our software as a software as a what you call it uh software as a service we have a
number of clients uh they need to have a central login, like the single application that they can all log in
and view only their data.
And we can't have information from one client
leaking over into another.
Yeah, cool.
All right, well, really neat.
I'm sure that'll be super valuable to people indeed.
Yeah.
Now, Brian, before we move on,
how about I tell you about our sponsor?
Once again, Microsoft is here.
So let's hear from them before we carry on.
This episode of Python Bytes is brought to you by Microsoft for Startups Founders Hub.
Starting a business is hard. By some estimates, over 90% of startups will go out of business in just their first year. With that in mind, Microsoft for Startups set out to understand
what startups need to be successful and to create a digital platform to help them overcome those
challenges. Microsoft for Startups Founders Hub was born. Founders Hub provides all founders at
any stage with free resources to solve their startup challenges. The platform provides technology
benefits, access to expert guidance and skilled resources, mentorship and networking connections,
and much more. Unlike others in the industry, Microsoft for Startups Founders Hub doesn't Thank you. cloud computing resources and the ability to unlock more credits over time. To help your
startup innovate, Founders Hub is partnering with innovative companies like OpenAI, a global leader
in AI research and development, to provide exclusive benefits and discounts. Through
Microsoft for Startups Founders Hub, becoming a founder is no longer about who you know. You'll
have access to their mentorship network, giving you a pool of hundreds of mentors across a range of disciplines and areas like idea validation, fundraising, management and coaching, sales
and marketing, as well as specific technical stress points. You'll be able to book a one-on-one
meeting with the mentors, many of whom are former founders themselves. Make your idea a reality
today with the critical support you'll get from Founders Hub. To join the program, just visit pythonbytes.fm slash foundershub,
all one word, no links in your show notes.
Thank you to Microsoft for supporting the show.
This is a topic that has been very interesting to me,
sort of this memory story around Python lists.
Yeah.
I'm looking forward to this one you got to share.
So I was interested.
This is a, we're going to present an article called Pre-Allocated Lists in Python by Redouan
Delawar, I think.
Anyway, I've always, I've thought about this before because one of the things that happens
with when you allocate a list in Python, if it's empty, it's not really empty.
There's some data there already.
And one of the first things the article talks about is this data structure that a C struct that Python uses to store basically the info about the
list, but it's still space, but it's, you know, it's still, it's empty supposedly. And then when
you, and normally you kind of just append to it. So you, or one way to, to add things to a list is
to just append one thing after another.
And what Python does, it's kind of a neat algorithm,
is it allocates more than it needs.
So if you add like five things or six things or something
and there's not enough space, it'll,
and I don't remember the real algorithm,
but it chunks a bigger portion.
And then if you run out of space again,
you get more space added to it.
Right. Cause the last thing you want to do is reallocate for every bite at a time and copy
the whole list as you're adding a thousand items, that would be super bad.
Right. So this, this article talks about three different ways. Like, let's say, if you know,
you know, you're going to have 10,000 elements in a list. And in this example, it's just counting,
you know, zero through, you know, 9,999 and filling it into the list. But there's, that's,
I think that that's irrelevant. It's the same sort of work for each kind of list, but it takes
three kinds. Well, the first kind is starting with an empty list and just appending every time.
And that seems like it would be slow, but it's not actually not that bad. The other two ways are to pre-allocate. And I'm like, how would you pre-allocate? But his technique was to take
like none and assign your list none times 10,000. So you got a 10,000 element list of nones.
That's fine.
And then...
As long as none's not a valid value, you're fine.
Yeah.
And then the third way was to take...
Let's see, where is it?
Is to do a list comprehension.
And just assign your list, the list comprehension,
and then put a for loop for i in range 10,000 in the middle of it.
And in this case, if you weren't really just counting to a 10,000 and doing something else,
it would be a similar sort of thing if you'd have a for loop to fill this in.
And I actually had no guesses as to what would be fastest.
So the final say when he was doing timing on this
was that the append method actually was the slowest,
but not terrible.
It's pretty efficient.
And the pre-allocate method, it shaved,
so we had 499 microseconds on his machine.
And then 321 on the pre-allocate.
So that's not even half as, I mean, it's not an order of magnitude, but it is faster.
And the list comprehension was 225.
So that was about half.
It was about twice as fast as the append was to use the list comprehension.
And the list comprehension is actually the most readable of the three,
I think.
So it's just sort of a,
I guess it's an interesting article to look at like how to discuss like how,
how this,
this allocating and allocating extra memory happens with append.
But it also is interesting that the preallocate,
it seems like that would be one of the faster ones,
and it's not.
So interesting.
Yeah.
I wonder if, I don't think the list has this.
I know in other languages it does.
When you create the list empty,
you can say I would like to initialize you
with this capacity.
Yeah.
Right?
And if it was like a built-in way to say, when you allocate your inner C-level array
pointers, make it this big to start with, but still sort of fill into it before you
start your growing algorithm.
Yeah.
Maybe that'd be a cool pep for some of the containers if it's not there.
But yeah, I think it's natural that the list comprehension is fastest.
And also it means you don't end up with a weird programming model
where you have a list,
its length is one thing,
but that's not what you should actually work with.
I think that's probably not worth it
except for extreme cases.
A couple of things that I was,
I found interesting about this
that I'd like to pursue a little further
is it didn't talk about memory space.
So one of the benefits of pre-allocating
is you're not allocating more than you need,
but I don't know if you're not allocating.
I don't know what the Python algorithm is.
But the, so I'd like to see this with space.
So how much memory is being used by the three methods?
The other thing that would be interesting to see is to throw NumPy in the mix, because I know NumPy has some more efficient. I mean,
it's a completely different beast, but still. You work with homogeneous data that's numbers
or something or strings. Yeah. So what do you think about this? Do you have to worry about
these little details? Are you guys under like heavy performance pressure? You know,
no, not, not right now, at least. I've never had to think about C-level things. And I'm actually taking it back
that so much goes into allocating stuff to a list
because in Python, allocating stuff to a list
is just create the list and put stuff in there.
So this is eye-opening to me.
Yeah, it's pretty cool.
It's not like C where you have to pre-allocate it
and then fill it out or something funky like that.
So what Makugan is saying,
I think the list comprehension will pre-allocate fill it out and or something funky like that. So, so Will McCougan is saying,
I think the list comprehension will preallocate because the range object has a
dunder length int method that reports its size.
And yeah.
So I think maybe the time saving we're get,
we're getting is that we're not filling it in with a nuns to begin with,
but actually filling it in with the data we want.
Okay.
Yeah.
Good to know.
Thank you.
Well,
I've more than once had a,
not argument, but a disagreement
where somebody said,
but you need to show me because,
and it's, oh, you have a for loop
and you just append to the list.
That's the same as a list comprehension.
They're doing the same thing.
The outcome, the final result is the same,
but the information that Python has to work with
is more much like Will was saying here. It can take all the that Python has to work with is more, much
like what we'll say here.
It can take all the information it has to work with and say, oh, look, it's going to
be this long as we loop.
And you're going to just add stuff to the list, not use it in other interesting ways.
So just go and jam on it, right?
Yeah.
Yeah.
All right.
Speaking of working with some data, let me tell you about this cool project called Mockaroo.
You guys familiar with
this? No. No? No. So here's the story. Imagine you needed some data and you want this for testing or
this could be testing like unit testing. This could be development. Like one of the big problems
with UI apps is having something to display just so that it fills it out. If I'm going to fill out
a webpage and I say, I want to work on the CSS of this table or the CSS of this list,
if there's nothing in the list, what are you going to do, right? So you want to have some
realistic data to work with. So this mockery is this free thing that has all these different
types of data that you can work with. So I can come over here and just say, I want some data.
And I want it in a CSV format or SQL table or Firebase or Excel or XML.
Or my favorite probably is JSON.
And then you can say, all right, well, I'm going to have an ID.
Here we have a customer table.
So ID, first name, last name.
But it has also things like gender.
And one of the types you can pick is gender. So it has all these well-known data types. So if I go and type in, I want a gender,
not only will it say male, female or something, it gives you like a list. So I can have gender
written out as female, male, or non-binary. I could have gender abbreviated as M or F or just
binary. So you can have like lots of control. So if I wanted to like, you say auto or car,
what do I got to type?
I got a car.
You can do like car makes,
models,
registration numbers,
all of these things.
So you can say,
this one is a gender abbreviated
and like you fill it out.
Then you can just say,
generate me this data
exactly like you want
and then download it in whatever format.
Like I said,
CSV,
SQL,
insert statements, JSON, Excel. Isn't that cool that's pretty cool so i've used this more than
once i can see a use case for this already awesome yeah right yeah yeah and i i kind of
like the first option when you're selecting the gender type um having it be animal names, that'd be fun.
Yeah.
I mean, there's all, like,
there's all these,
there's all these, that's crazy.
There's all these different data formats.
So you've got, like, cars.
What else we got here?
Credit cards, GUIDs,
ISBNs for books,
numbers on a normal distribution,
passwords.
Even MongoDB object IDs.
That's cool. cool oh that is pretty
cool yeah yeah so you have um e-commerce stuff money stock market symbols um locations health
care let's see how about that you got your all your drug companies your nhs numbers and all those
different things oh it's because i'm searching for car. Why is car keep showing up? Animal common names. Yeah. Yes. You could have a wombat or a jungle kangaroo. I mean,
these are all some fun, right? Yeah. So these are all super neat. You can get up to like a
thousand rows for free. And then I think you have to pay if you need more than that. And then a
follow on, I believe this from the same company, a full disclosure, these guys sponsored talk by
but I've wanted to talk about this even before so um they
have this thing the service called tonic that you can then point at your production database
and it'll do things like generate me something that looks exactly like production data but
doesn't have any personally identifiable information so that i can give it to the
developers to test with real looking data with real variations from our clients,
but is sort of safe.
Like if they lose their laptop or whatever,
or they just leave it open,
it's not going to destroy something.
Right.
Yeah.
That's pretty cool.
Yeah.
So you basically connect it to your database and then it will go along and
sort of create data that looks more like what you actually have instead of just this
mockaroo data so pretty neat anyway if you need to do some testing you need to generate big data
not just for like pi test testing but also ui development and just something to work with these
are both good options very cool yeah cool cool um sam out in the audience says this is fantastic i
agree and will says, super useful.
I could see even using this for testing development
of rich and textual out there.
So very cool.
All right, Vucile, off to you, last one.
All right, so this is a fun project
that a good friend of mine, Daniele Procida, made.
He's demoed it at a couple of conferences.
It's called the BrachioGraph.
The goal for this project is to make a pin plotter
powered by Python and make it as cheap as possible
using common things you can find in the house.
So it's a plotter.
It uses a Raspberry Pi, an ice cream stick,
and a clothes pin to draw, and a pencil, of course.
Right.
So it's got Python code that turns an image into, I think it's called a raster,
it rasterizes an image into coordinates on a piece of paper.
I could have used this yesterday. Oh my gosh, this is great.
Yeah. So I don't know if I can play video here, but it looks pretty cool when
it's actually printing out or plotting out an image.
Let me see if I can get it to work here. But it has a motor that then does everything and it can draw very basic images.
It's a fun project that you can work on it.
And it costs, I mean, the setup for this costs less than 50 US dollars.
And it's a pretty fun project
oh I would have
gotten an A
in art class
if I had this
no I love it
this is really neat
people should definitely
play the video
and watch it
because it's fascinating
yeah
the website has
like a how-to guides
and documentation
on how to build this
what things you need
sources to the software and everything.
And it's also an open source project
that anyone can contribute to if you're interested.
This is really neat.
This is one of the things I like
about simple things like this
is they're great projects to start kids with
because it's very real and physical.
Yeah, I was thinking this would be awesome
in a teaching scenario as well.
Yeah.
Cool. All right, this is a great one. I love it very neat to do with python and stuff all right well i think that's
it for our main items brian you got anything you'd like to share oh we covered uh last uh i think we
covered last week that that the uh python issues were migrating to github and it might be on April Fool's Day and it was not. So next plan looks
like April 8th. Next, one more week. If we keep talking about it, it's never going to happen.
Like a watch pot sort of a thing. Exactly. Yes. Well, I'm waiting for it to happen.
I want it to happen. I know that the transformation will be complete at that point, right?
So next week we won't cover it at all unless it's already happened.
But if it's delayed again, we won't cover it again until that.
Yeah, exactly.
We're not getting roped into this three times.
Lucille, anything else you want to give a shout out to?
Yeah.
Yeah.
Just one thing is a project that I found recently.
It's called Thunder Client.
It's an alternative video code extension and it's lightweight.
You download it
and install it
in less than a second
and you can get started
sending requests
and it has less setup
than Postman
and it doesn't need any
it's like
it's easy to install
yeah so if you were
testing APIs
like constructed JSON thing
put this header in
you want to call it
yeah Thunder Client
for VS Code
very nice
yeah
Thunder
Thunder if you're using this code exactly yeah you you'd you'd go you just switch tabs you know
instead of switching applications so that shaves a few microtechs yeah exactly that's cool i love it
all right nice i've got just uh one thing i believe today this is really short i've spoken
about ngrok at ngrok.com before
about how it's really cool for exposing
if you're like wanting to expose an API
to the outside world that you're developing
or you need to debug it.
I've used this for like webhooks.
So this company, I need to integrate with their webhook.
So I need them to call this, but it's not working.
So I want like a break point on my machine,
but how do they get to my machine? Just run ngrok and it'll tunnel it right through the firewalls using SSH reverse
tunnels. That's all good. What I discovered working on yet another integration project
was that there's actually this super rich inspector that I think people haven't noticed
in there. If you fire up an ngrok thing and then you go to localhost 4040,
every request comes through.
You can see the summary, the HTTP headers,
the cookies, the response, the status codes,
the duration, all that.
If you're using ngrok for that sort of use case, be sure to check out this live web view
that lets you dive into.
It's almost like the dev tools,
the network tab of the dev tools,
but for just people coming in rather than you consuming stuff. So it's pretty like the the dev tools the network tab of the dev tools but for just people
coming in rather than you consuming stuff so it's pretty cool that's neat are you guys ready for a
joke yes shall we finish it finish out with a joke you may have heard recently that the microsoft
source code for bing was got by the laz group. And people thought this was some folks in like
Brazil or somewhere in South America. It turns out it was a bunch of British teenagers, like
$14 million in Bitcoin, whatever. So they had gotten a hold of some of the Windows and Bing
source code, I believe it was. And there was like, oh my gosh, is this going to reveal a bunch
of zero days because people can go through the source code? Well, we don't do that much Windows,
at least on the server in Python. There's some, but not as much. But we use a lot of Linux, right?
For all the TalkPython, Python byte stuff, we've got like a fleet of eight Linux servers. Now,
when I saw this headline, I really began to worry that maybe some vulnerabilities would be discovered or some kind of problem would happen here.
So the headline is, Linus Torvalds confirms the Lapsus breach after hackers publish the Linux kernel source code to the Internet.
Okay.
In a blog post on Tuesday, published hours after the Lapsus posted a torrent file containing partial source code from the Linux kernel, the geek man himself revealed that his branch was cloned by the hacking group, granting attackers unlimited power too.
The article stops there.
How many times do you have to read?
Exactly.
I think being open source, it's probably okay.
Yeah.
Yeah.
Yeah.
Oh, no.
It's publish the source.
They published the source to Linux.
What are we going to do?
The programming humor just never stops.
I love it.
So they published the Binging source code i think
they got some of the bing source code maybe cortana i can't remember exactly what it was but
some of these services and i think the windows source code as well i was surprised so i i don't
pay too much attention to the blog traffic stuff but i was looking the other day after i'd put up
a bunch of uh the transcripts for testing code uh i was curious how much we're
just getting hit and uh for python test.com um i'm getting more traffic from bing than from google
which is how interesting interesting all of a sudden bing's pretty awesome isn't it
well it's got nice pictures i'll tell you that it's got nice pictures, I'll tell you that. It's got nice background pictures. It does. Actually, in terms of beauty, it's really nice.
And, you know, I end up using DuckDuckGo.
So when I'm using DuckDuckGo,
I know they've got a ton of different sources,
but one of the sources they use for data, I believe,
is also Bing.
And yeah, it's all right.
It's all right.
It's all right.
Well, Vucili, it was really great to have you here with us.
And Brian.
Yeah, pleasure was mine.
Yeah, it's great to have a chat with you as always.
All right.
Bye, everyone.
Talk to you next week.
Bye.
Cheers.