How time flies and how I grow older. I almost finished my fifth year working for Amazon Alexa (the voice service, not the web service that unfortunately got shut down). The fact that Alexa is now 10 years old and I lived half of it definitely made me feel old. The team I work for has moved on to work on non-Alexa stuff in the new year. It would be a proper time now to reflect and appreciate a bit.
What's new: Tappable CharlieTicket
MBTA's Fare Transformation program is phasing out the old CharlieTicket with "Tappable CharlieTicket". Under the hood, their storage is changed from magstripe to RFID.
CharlieTicket is still an important tool to get MBTA passes that work on every mode before the Fare Transformation is fully complete. I have found lack of information on this technical change, so maybe it's time to document some of them. 继续阅读“What's new: Tappable CharlieTicket”
Day 19 of the Positive Life
I promised to write more blogs but obviously I failed again. Not surprising.
I am out of isolation already. I am feeling OK. Maybe I should just go over what happened during my isolation days.
Where I reported
It's very easy to forget to do contact tracing and reporting once the panic of positivity came in. I am a bit afraid of forgetting them, and I think I did complete what I was supposed to do. 继续阅读“Day 19 of the Positive Life”
Day 3 of the Positive Life
It turns out life locked inside one room can still be pretty busy (although a bit frustrating if you had plans outside). After this isolation weekend I didn't complete the supposedly Day 2 of the series, talking about what post-positive life would mean. I guess I would just do a quick check-in here for now as a dairy.
Day 1 of the Positive Life
It's so frustrating that two trips to the west don't give me covid, but a week in the east does. Stay safe all.
— Phy (@phy25) May 14, 2022
Yes, I got COVID. After 2 years and 3 shots. It's so frustrating.
I might just have too much to write about, so much that no one might ever want to see on Twitter. Maybe a blog series would work then? Writing something down might make me feel a little positive with these positive days, I guess.
I don't really want to bother anyone to chat with me all day randomly. Ugh, social is hard. 继续阅读“Day 1 of the Positive Life”
Customized COVID data comparison with pandas and plotly
It's yet another summer that people just want to travel without fear. Probably it has been "back to normal" for some people, but for me, it has to be backed with some data. There are plenty of websites that publish COVID case data and visualize them by city (even in Google onebox - by the way, Google Travel shows some helpful metrics on hotel reservation rate as well).
However, with a lot of travel destinations in mind, it would be very helpful if there's a dashboard that I can compare COVID cases between different cities and figure out the trend myself. I haven't seen one handy, and I really want to play around the data with some home baked solution. 继续阅读“Customized COVID data comparison with pandas and plotly”
Wrap Context Manager (as nested) in a Python function
To make my code more elegant, I need to wrap a context manager with initialization code as a function in Python. This is definitely possible, but it took me some time to find the most elegant way to do this.
Generally speaking, you will want to enter all contexts when using the decorator @contextlib.contextmanager
or @contextlib.asynccontextmanager
. When the end user uses with my_function() as a:
, everything inside the with
block has been inside the nested contexts. When Python gets out of the end user's with
block, it should also run all related __exit__
s in the wrapper function. See example (requires Python 3.7+ probably and writes test.txt
; you can test it on repl.it):
import asyncio
import contextlib
import aiofiles
import typing
@contextlib.asynccontextmanager
async def my_context_manager() -> typing.ContextManager[aiofiles.threadpool.AsyncFileIO]:
# init
filename = 'test.txt'
async with aiofiles.open(filename, 'w+') as file:
# you can still override or interact with `file` if needed
yield file
async def main():
# end user
myfile: aiofiles.threadpool.AsyncFileIO
async with my_context_manager() as myfile:
print(await myfile.write("12\n"))
await myfile.seek(0)
print(await myfile.readline())
asyncio.run(main())
When I rewrite the code above I feel it so easy and natural. It really took me some time to realize how this works.
Side note of some scheduling tools
SignUpGenius
Free version includes:
- multiple spots in one time slot
- email (ics) confirmation to invitee
- export as table
- cancellation email triggered by organizer
- modify bookings by unique link (in the email).
UX feels like oldest.
Doodle
Free version includes:
- multiple spots in one time slot
- export as table (maybe?)
No invitee email is available in free version. Booking modification can only be protected if invitees log in with a Doodle account. UX is a lot better.
Calendly
Free version includes:
- email (ics) confirmation to invitee
- export as table
- cancellation email triggered by organizer
- modify bookings by unique ID (in the email)
Paid version (10 days trial) includes:
- multiple spots in one time slot
- webhook (API)
UX is the best.
Strip Assets Files in new Android Gradle
Spending 2 hours on this because 1) I don't have experience with Gradle script (its syntax looks funky) 2) DJI sxxks, and they put 50MB of large assets files to their SDK, which is camera distrotion_correction files that I never need, and 3) Android Gradle library upgrades, which deprecating mergeAssets.
Looking at some GitHub projects's Gradle script, it looks like dependsOn
is very popular in defining what order the task should be executed, and it works! 继续阅读“Strip Assets Files in new Android Gradle”
Manual work after WordPress auto update failed
WordPress 版本都到 4.9 了,全球 CMS 占有量也早过三分之一了,自动更新居然还是全量下载,连个增量更新都不做(光做 no-content.zip 有啥用拜托?)。虚拟主机下载 WordPress 的包速度又很慢,结果总是超时(虚拟主机控制的那种超时断开),更新失败。
网上搜了一圈,居然官方建议是“绝对是你的主机有问题,请手动更新”。网差一点还被说是主机不行?那就只能自己来呗。
My WordPress auto update always failed because of slow download speed. Just don't know why WordPress doesn't implement a incremental upgrade mechanism (maybe I should search for a ticket?). Whatever, I have to solve it manually, in a smart way.
P.S. 写完这篇之后,看到更新的 API 了,的确是有增量更新的,但他们不用。They actually have incremental upgrade implemented, but they hardly use it.
继续阅读“Manual work after WordPress auto update failed”