-
- Very common to write custom sort functions as lambdas (even if many levels of sort), but remember you can go even further if your custom logic has function wrappers or other inputs you need to consider (
sorted
‘s key
param just passes the element of the iterable you’re sorting, one argument). Or if you need to type annotate in a clear way, a custom function is better. Remember: you just need to return a tuple of the numbers that matter, in order. Negate the ones you want to sort in the opposite direction, for that level.
- Equinox massage. Better quality than massage envy. I got the master therapist session, although not sure the diff between master and normal (assume training/licensing).
- Lots of private work.
typing.cast
for list comprehensions and other places where normal : <>
annotations do not work.
- Rise Gardens came out with a membership plan now.
- Analysis of current costs for 1 triple garden:
- My current subscription for nutrients is $78 every 4 mo (all-in, including tax+shipping). 200mL pH, 500mL blossom, 500mL sprout, 1000mL thrive. So that’s $234/yr.
- Then I’d buy seeds as necessary. Say 8x 4-packs, at $12 apiece, every 3mo. Plus (assume) 10% for tax+shipping. So that’s $422/yr.
- Total $656/yr to stock a single triple rise garden. Then you’d double for 2 triple gardens, to $1312/yr.
- Perks of membership plan:
- Membership is $360/yr (I got it for $300/yr with LOYALGARDNER bc first signup).
- Free shipping on orders >$30.
- 15% off sitewide.
- Reedeemable loyalty points.
- Plus a bunch of others: VIP sales, early access, welcome gifts (microgreens+nursery for me), events, birthday gifts, merch, more.
- You can add to upcoming boxes at will (or change seeds, etc), just like butcherbox.
- You get 6x 4-packs every 3 mo. Then you’d add 2x more (to equal the above), at $10 apiece (15% off), every 3mo. Free shipping. Ignore tax (say that’s equal to loyalty point redemption). So that’s $80/yr.
- You get these nutrients in every pack: 100mL pH, 150g dry nutrient, 150g dry nutrient. Not sure exactly how the dry nutrients convert, or only 2/3, but assume I have to manually double this. So that’s another $78*0.5quantity*3times/yr*0.85discount = $100/yr.
- Total $480/yr to stock a single triple rise garden. Then for the second garden it’s $320 for seeds (incl15% discount) and $200 for the nutrients. So total $800/yr.
- So I’m saving >$500/yr, and getting a bunch of other perks for early access, welcome gifts, cheaper spot orders, birthday gifts, loyalty points, etc. Well worth it.
- Quick sqlalchemy refresher:
- db.session.query() returns a query
- query.join() returns a query
- query.filter() returns a query
- query.all() returns a list of results
- query.one() returns exactly one result, or raises an error if there’s 0 or multiple results
- query.first() returns the first result of all results, or None if no results
- query.scalar() returns the first element of the first result, or None if no results, or raises an error if multiple rows
- “Result” above means an object (instance) of the class which defines the model for that result (whatever table you queried). If the query/results span multiple tables/models, then instead of single objects, it will be tuples of objects of the respective tables/models in the query/join.
- “Element” is just the object if you’re querying a table. If you’re querying a specific col, scalar() will return the value of that col.
- SBSC. Misc.
- Cleaned up a ton of the ORM layer.
- Removed the joins module, made explicit in the queries module.
- Removed all type:ignore instances except the flask_user addition of user_manager to flask.current_app. Will be fixed later when I undepend on the yanked flask_user package.
- Updated all my stubs. Just
: Any
specs for any objects (vars, classes, functions), structured in the module structure of the package. I’m not managing any members, args, params. Not worth it.
-
- Some private work.
- Reorganized all the cabling in the bedroom, ~10 connections. Much cleaner now and much stabler for the remotes.
- Did some elimination testing for the food poisoning over the last couple days. Not smoothies or my other usuals. Was either the batch of liver or the new hot sauce (clark+hopkins florida). Threw away both in an abundance of caution.
- This has happened ~twice in two months now. If it happens again, then I’ll be safe and cook the liver more (right now it’s around medium rare).
- Desktop/WSL2 tasks.
- Windows cumulative update patches as well as Corsair iCUE.
- Created a few custom murals and device layouts for iCUE. Simple watercolor (dynamic) is probably my favorite. The audio lighting is pretty cool tool, following your music.
- Uninstalled sonic studio. The only programs that should be running in the tray are iCUE and docker desktop (both started automatically at startup as well).
- Full startup list: spotify, chrome, icue, docker desktop. Others: chrome (not technically on the list, but I always leave it open so it reboots), expressvpn, sshd/agent, etc.
- Planted 2 chrysanthemums and 2 lettuces directly in the rise gardens, skipping the nursery (like aerogarden). I bought separate humidity caps. Water level looks good, and this obviously keeps fresh water (vs stagnant nursery requiring weekly change). Only difference (and remaining concern) is nutrients. The garden has higher levels, the nursery has none. AFAIK, seeds simply don’t absorb nutrients, rather than being harmed by them. So I’m hopeful. Overall, if this works, it should be much faster/easier/cheaper/simpler without nurseries.
- Poetry version updating (comparing HEAD to your lockfile).
poetry show -o
- Prints all the versions that are behind latest.
- Does NOT respect resolution. Ie if one of your deps pins lower than latest, this command will still show latest.
poetry update --dry-run
- Prints all the versions that are behind latest.
- DOES respect resolution. Will show what your lockfile updates to (exactly) with
poetry update
or poetry lock
.
- SBSC. Misc.
- Typing. Fully finished.
- Snuck in the change to color percentage cells above/below/equal 50.
- Updated deps. Only minor and patch semvers, no major.
-
- 5/7 days into the airthings calibration. CO2 modulation is good with the window. Low humidity though. Bought a humidifier.
- Still feeling terrible after yesterday.
- Little bit of private work.
- Spacing guide for rise garden: https://support.risegardens.com/en_us/how-to:-space-out-your-gardens-B1yWSGyqc
- Great little Shel Silverstein story: https://www.slideshare.net/cyaneum/the-missing-piece-meets-the-big-o
- For gunicorn python autoreload in dev mode, I notice that often I have to restart twice (just save twice) for changes to take effect, not just once.
operator.itemgetter
and attrgetter
are excellent for basic sorts, but if you need to negate values (or do any calculation of any kind on any sort level), then just build a custom lambda.
- A note on general building blocks, dict vs defaultdict. Use dict when you have expected keys, of course. Don’t just use it for coding convenience, because you can have unexpected results from the parents/callers.
- Eg for sbsc game statuses, use a dict. For something like a user_id key (unknown, could be many in the future, unbound), use a defaultdict. Even for weeks, which can change / be dynamic.
- Also: if the defaultdict has an value lambda of something like a list or a dict, that’s safer. A lambda of an int (which defaults to 0) or another value might be more misleading. An empty list will rarely break the caller silently (who would have gotten a keyerror). If the caller gets a 0.0 instead of a keyerror, that might break silently.
- My sally lightfoot crab (adult) caught and ate my red fairy anthias (~3”) alive! I reached in with tongs to separate them, but the crab was able to scurry away to safety under a rock with the wriggling fish still in its front claws.
- SBSC. More restructuring of the results module.
- Very clean now.
- Separated by week_results, season_results, and alltime_results. Each managing multiple views, as appropriate. Each following the same flow: query -> organize -> calculate -> sort -> inject -> toprow.
- Did a little deepdive into conditional typing. You can use union
|
to indicate that a function can return multiple types, but what if the expected return is directly linked an input param? Eg return_email=True
vs the default of returning user IDs. Use typing.overload
! Details on ticket.
-
- Food poisoning again. Bed at 130 last night, woke up at 330 to puke (and stayed in there straight until ~830). Couldn’t do much today.
- Little bit of private work.
- Finished the setup of the v2 charchoal. Deep cleaned both triple families. Planted all nurseries.
- Pro chess league started today. And warriors’ last game before allstar break. We’re finally getting into the paint.
-
- Vscode:
"editor.renderWhitespace": "all"
- Cool agad video search tool: https://agadmator-library.github.io/
- Private work.
- SBSC. Absolute rewrite of the results module. It’s so much cleaner now.
- Split into week results, season results, alltime results. And the underlying libs.
- Split each view into logical segments: init, check, query, organize, calculate, aggregate, sort, inject, toprow.
- Updating the typing of the module simultaneously. Much cleaner on that front as well.
-
- Set up HEPA purifier.
- Finalized v2 charcoal triple rise garden. Only items I may consider ordering in a later seed batch: 2 more nurseries (to total 9) and v2 caps (square extrusion).
- Superbowl.
- Aquarium maintenance.
- Equinox etc.
- SBSC. Typing.
- Reread all the docs to freshen up.
- Remember that an
alias
is a custom collection of other types. A NewType
is a custom subclass of another type.
- Pep589 for
TypedDict
, a great structure that is still a dict at runtime but allows types for specific keys: https://peps.python.org/pep-0589/
- Remember that python uses inference on your code to determine type. This is called (static) duck typing, but the official docs call it “structural subtyping”. It just means that you don’t have to put annotations on EVERY param/arg/return/member/var (nominal subtyping) – it can infer it whenever obvious, and will flag when unknown.
- Wrote a bit for instantiating type aliases. Long story short: don’t do it.
- I imagine they’ll fix this in a future release, just like they did with allowing subscription within the builtins, rather than shipping a bunch of generics with the typing module to mirror the containers.
- It would be really nice to define the (nested) type interface and then just instantiate from that.
- I guess the rationale is that they want us to define our own custom generic classes for these cases, and then instantiate those classes (all instead of type aliases + subscription), because then instantiation becomes clear (and we’re working in the realm of runtime code instead of types).
Num = int | float
is possible, but I like the explicit version without the alias much better.
- Notes on the ticket for TypeVars (define/reference) and Generics (scoping). Also invariance, covariance, contravariance: https://peps.python.org/pep-0483/#covariance-and-contravariance and https://peps.python.org/pep-0484/#covariance-and-contravariance
- Revisited ParamSpec, Callable, and Concatenate. All useful type features for decorators.
-
- Played with vscode
launch.json
and tasks.json
.
- You can specify a launch configuration however you’d like, then run it from the IDE’s debugger as desired.
- This can be an execution on the host machine, OR within docker containers.
- Tasks also allow you to define the common actions of your project. For SBSC, I have all targets defined in a gnumakefile. I could port them over, and get some nice IDE support, but I’m fine running the tasks directly from the CLI with make.
- Received the Code V3 with cherry MX blues and set it up. Looks, feels, and sounds amazing. Not too hard to push, feels correctly tactile. Took a minute to get used to the 87 key layout again. I never use the numpad, but keyboard size just subconsciously affects my placement.
- fn-f12 to turn keyboard backlight on/off. fn-f11 to adjust brightness (appears to be 7 levels, including off).
- Laundry, cleaning, aquarium water change, mealprep, week planning, all the usual weekend tasks. Also made a 5lb chuck roast.
- Basically finished param typing for SBSC. Will move onto args, members, vars next. Again, this has been an overall useful exercise.
- Generic type aliases are very helpful.
- Also ParamSpec.