Back in May, I decided to write down my tips and tricks of the month. My hope is that people find them useful (or share even newer tricks for me), but at the very least, writing them down organizes my thoughts (and forces me to write a blog post more than once a year). So here’s what I got for June:
span:nth-child isn’t the nth span (6/22/20)
Shame on me again for not reading docs first.
<div> <span id='1'> <span id='2'> <p>Text </p> <span id='3'> <span id='4'> </div>
If I have a CSS rule that specifies `span:nth-child(2n)` (or every 2nd one), it won’t give me the span with id 2 and 4, it will give me the span with 2 and 3! This is because nth-child refers to the sibling group, which is all the elements. From there it finds every second sibling, and then if that sibling is a span, does it apply the styling.
Push current branch (6/23/20)
Whenever I’m pushing a branch, I typically like to explicitly write my branch name :
git push origin <branch name>. However, for repos with a lot of branches sometimes I forget writing what branch I’m using. I sometimes default to
git push origin `git branch --show-current`
which is wordy. Well today I found out I can just do
git push origin $HEAD
HTMLCollection is live (6/22/20)
When you do a
document.getElementsByClassName, I always treated it as an array-like object that got returned. I can iterate over it just fine. I knew it was some special collection (HTMLCollection), but what I didn’t realize was that the collection can change out from underneath you.
var elements = document.getElementsByClassName('abc'); // suppose elements has a length of two addElementToMainDivWithClassName('abc') //elements length is now three!
As someone who favors immutability, this surprised me, especially since I thought I was getting a snapshot of a specific point of time. It is right there in the docs though, so at least it’s documented.
Use xargs to map over data (6/18/20)
I’ve known about xargs before, but I never really played with it. I finally found a case that would force me to learn how to use it. In our object storage at work, a mistake of mine wrote the bucket name as the name of a python method ( I was saving text.lower instead of text.lower()). I wanted to delete all the buckets that I had created (all 178 of them). Through the CLI, I was able to list them and cat them to a file (let’s call it test.txt). From there I could do :
xargs -t -d "\n" -a test.txt <delete command>
-t will show me the command output (I tested it out with an echo before I did a delete command
-d specifies the delimiter (in my case, newline)
-a told me the argument file.
Shell scripting surprises me at time, as in other languages I might consider this a map of a partial function, and I don’t always expect the same experience in the shell.
Using Pydantic to do type validations (6/2/20)
After a discussion with a colleague (thanks David), I decided to beef up the validations we do on user-submitted data. I am a big fan of Python types, but have always acknowledged that one of the downsides of types is the ability to be really strict in what you allow. For instance, how do I define a type that only takes values from 1 to 10, or only a list that has at least one element?
Enter pydantic. Pydantic is a library that allows you to define models of data, and restrict fields of that data appropriately. And to my pleasant surprise, they integrate with dataclasses really well. I won’t go into usage too much, but check out what a data model might look like (from their docs):
class Model(BaseModel): short_bytes: conbytes(min_length=2, max_length=10) strip_bytes: conbytes(strip_whitespace=True) short_str: constr(min_length=2, max_length=10) regex_str: constr(regex='^apple (pie|tart|sandwich)$') strip_str: constr(strip_whitespace=True) big_int: conint(gt=1000, lt=1024) mod_int: conint(multiple_of=5) pos_int: PositiveInt neg_int: NegativeInt big_float: confloat(gt=1000, lt=1024) unit_interval: confloat(ge=0, le=1) mod_float: confloat(multiple_of=0.5) pos_float: PositiveFloat neg_float: NegativeFloat short_list: conlist(int, min_items=1, max_items=4) decimal_positive: condecimal(gt=0) decimal_negative: condecimal(lt=0) decimal_max_digits_and_places: condecimal(max_digits=2, decimal_places=2) mod_decimal: condecimal(multiple_of=Decimal('0.25')) bigger_int: int = Field(..., gt=10000)
There’s a lot more it can do, so go check out the docs.
Using pipdeptree to see package dependencies (6/10/20)
Pipdeptree is a very useful tool to see your dependency tree of pip packages.
pipdeptree -p <package name> to see all of it’s dependencies, or
pipdeptree -r -p <package name> to see all the packages that depend on that package (very useful for figuring out version conflicts.