Skip to content

Instantly share code, notes, and snippets.

View odbol's full-sized avatar

Tyler Freeman odbol

View GitHub Profile
@odbol
odbol / pin_requirements.py
Created April 2, 2026 18:48
Python project dependency fixer: Pin all package versions in requirements.txt to a specified date.
#!/usr/bin/env python3
"""
Pin all package versions in requirements.txt to a specified date.
This is for all those ML codelabs and github repos that forgot to pin their dependencies and now have broken installs.
Just run this script with the last commit date of the repo, and it will update your requirements.txt with the closest
versions available on PyPI as of that date.
Usage: python pin_requirements.py <date> [requirements.txt]
Date format: YYYY-MM-DD
"""
@odbol
odbol / EventBus.kt
Created October 2, 2025 17:44
Shares events across activities, services, etc. So much simpler than the Java version! But still useful.
package com.odbol.utils
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow
/** Shares events across activities, services, etc */
object EventBus {
val events = MutableStateFlow<Event>(Event.None)
}
@odbol
odbol / CollectionUtils.kt
Last active October 2, 2025 17:39
Kotlin utils: useful little utils for Kotlin functional programming: sequences, collections, grouping, etc
package com.odbol.utils
/**
* Groups consecutive items in an iterable by the given key. i.e. the sequence will emit a new list
* each time the key changes, containing all items since the last key change.
*
* This is similar to Kotlin's built-in `groupBy` function, but it groups consecutive items with the
* same key, rather than all items with the same key. Thus the same key can appear multiple times in
* the output sequence.
*
@odbol
odbol / CoroutineHelper.kt
Last active March 17, 2025 23:14
Utils for use coroutines from Java code, like calling Flow.collect() from Java
package com.odbol.coroutines
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.coroutineScope
import java.util.function.Consumer
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.launch
/** Helps using Kotlin coroutines from Java code */
object CoroutineHelper {
@odbol
odbol / StringEnumTypeAdapter.java
Created February 6, 2025 01:06
GSON adapter for string enums when you want the JSON to have the string value instead of the enum constant's name
/*
* Copyright (C) 2024 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
@odbol
odbol / example.tsv
Last active May 2, 2024 22:21
AppScript to fix Google Sheets with =IMAGE() formulas that contain data-urls
We can make this file beautiful and searchable if this error is corrected: Illegal quoting in line 2.
Image key Image Another column
1 =IMAGE("data:image/gif;base64,R0lGODlhEAAQAMQAAORHHOVSKudfOulrSOp3WOyDZu6QdvCchPGolfO0o/XBs/fNwfjZ0frl3/zy7////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAkAABAALAAAAAAQABAAAAVVICSOZGlCQAosJ6mu7fiyZeKqNKToQGDsM8hBADgUXoGAiqhSvp5QAnQKGIgUhwFUYLCVDFCrKUE1lBavAViFIDlTImbKC5Gm2hB0SlBCBMQiB0UjIQA7") Random data
2 =IMAGE("data:image/gif;base64,R0lGODlhEAAQAMQAAORHHOVSKudfOulrSOp3WOyDZu6QdvCchPGolfO0o/XBs/fNwfjZ0frl3/zy7////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAkAABAALAAAAAAQABAAAAVVICSOZGlCQAosJ6mu7fiyZeKqNKToQGDsM8hBADgUXoGAiqhSvp5QAnQKGIgUhwFUYLCVDFCrKUE1lBavAViFIDlTImbKC5Gm2hB0SlBCBMQiB0UjIQA7") More Random data
@odbol
odbol / Regexes.md
Created February 5, 2024 18:11
Useful Regexes

Find all <style> tags and their contents:

``

@odbol
odbol / woocommerce-bulk-update-prices.md
Last active January 15, 2024 22:25
WooCommerce: how to update prices in bulk directly in the database using SQL

WooCommerce: how to update prices in bulk without a plugin

The WooCommerce Wordpress plugin doesn't have a way to update all prices for all products and all variations in bulk. You have to do it by hand, in the Wordpress admin editor, or pay for a "bulk edit" plugin to do it.

Or, you can hack the database directly using some fancy SQL. It took me a while to figure this out.

-- Update all prices for all variations and products that are 4.99, change to 5.99
@odbol
odbol / FractionsSequence.kt
Created December 5, 2022 18:15
Kotlin sequence generator for stepping through float ranges without accumulating floating-point errors
fun generateSequenceOfFractions(
range: ClosedFloatingPointRange<Float>,
step: Float
): Sequence<Float> {
val multiplier = 1f / step
val start = floor(range.start * multiplier).toInt()
val endInclusive = ceil(range.endInclusive * multiplier).toInt()
return generateSequence(start) { it + 1 }
.takeWhile { it <= endInclusive }
.map{ it.toFloat() / multiplier }
@odbol
odbol / Utils.ts
Created October 3, 2022 22:45
Utility functions for parsing querystrings and other useful JS goodies
/** Returns the first querystring parameter with the given key, or null if not found. */
export function getParam(param: string): string|null {
var dataCallbackMatches = new RegExp(param + '=([^&]+)').exec(document.location.href);
if (dataCallbackMatches) {
return dataCallbackMatches[1];
} else {
return null;
}
};