13th May 2022
New: Introduce my food management workflow.
As humans diet is an important factor in our health, we need to eat daily around three times a day, as such, each week we need to invest time into managing how to get food in front of us. Tasks like thinking what do you want to eat, buying the ingredients and cooking them make use a non negligible amount of time. Also something to keep in mind, is that eating is one of the great pleasures in our lives, so doing it poorly is a waste. The last part of the equation is that to eat good you either need time or money.
This article explores my thoughts and findings on how to optimize the use of time, money and mental load in food management while keeping the desired level of quality to enjoy each meal, being healthy and following the principles of ecology and sustainability. I'm no expert at all on either of these topics. I'm learning and making my mind while writing these lines.
New: Introduce my grocy management workflow.
Buying stuff is an unpleasant activity that drains your energy and time, it's the main perpetrator of the broken capitalist system, but sadly we have to yield to survive.
This article explores my thoughts and findings on how to optimize the use of time, money and mental load in grocy management to have enough stuff stored to live, while following the principles of ecology and sustainability. I'm no expert at all on either of these topics. I'm learning and making my mind while writing these lines.
grocy is a web-based self-hosted groceries & household management solution for your home.
My chosen way to deploy grocy has been using Docker. The hard part comes when you do the initial load, as you have to add all the:
- User attributes.
- Product locations.
- Product groups.
- Quantity conversions.
Sometimes you want to have some API endpoints to populate the database for end to end testing the frontend. If your
appconfig has the
environmentattribute, you could try to do:
app = FastAPI() @lru_cache() def get_config() -> Config: """Configure the program settings.""" # no cover: the dependency are injected in the tests log.info("Loading the config") return Config() # pragma: no cover if get_config().environment == "testing": @app.get("/seed", status_code=201) def seed_data( repo: Repository = Depends(get_repo), empty: bool = True, num_articles: int = 3, num_sources: int = 2, ) -> None: """Add seed data for the end to end tests. Args: repo: Repository to store the data. """ services.seed( repo=repo, empty=empty, num_articles=num_articles, num_sources=num_sources ) repo.close()
But the injection of the dependencies is only done inside the functions, so
get_config().environmentwill always be the default value. I ended up doing that check inside the endpoint, which is not ideal.
@app.get("/seed", status_code=201) def seed_data( config: Config = Depends(get_config), repo: Repository = Depends(get_repo), empty: bool = True, num_articles: int = 3, num_sources: int = 2, ) -> None: """Add seed data for the end to end tests. Args: repo: Repository to store the data. """ if config.environment != "testing": repo.close() raise HTTPException(status_code=404) ...
serialfixture with a session-scoped file
lockfixture using the
filelockpackage. You can add this to your
import contextlib import os import filelock @pytest.fixture(scope='session') def lock(tmp_path_factory): base_temp = tmp_path_factory.getbasetemp() lock_file = base_temp.parent / 'serial.lock' yield filelock.FileLock(lock_file=str(lock_file)) with contextlib.suppress(OSError): os.remove(path=lock_file) @pytest.fixture() def serial(lock): with lock.acquire(poll_intervall=0.1): yield
Then inject the
serialfixture in any test that requires serial execution. All tests that use the serial fixture are executed serially while any tests that do not use the fixture are executed in parallel.
New: Introduce gettext.
Gettext is the defacto universal solution for internationalization (I18N) and localization (L10N), offering a set of tools that provides a framework to help other packages produce multi-lingual messages. It gives an opinionated way of how programs should be written to support translated message strings and a directory and file naming organisation for the messages that need to be translated.
New: Introduce Python Internationalization.
To make your code accessible to more people, you may want to support more than one language. It's not as easy as it looks as it's not enough to translate it but also it must look and feel local. The answer is internationalization.
Internationalization (numeronymed as i18n) can be defined as the design process that ensures a program can be adapted to various languages and regions without requiring engineering changes to the source code.
Common internationalization tasks include:
- Facilitating compliance with Unicode.
- Minimizing the use of concatenated strings.
- Accommodating support for double-byte languages (e.g. Japanese) and right-to-left languages (for example, Hebrew).
- Avoiding hard-coded text.
- Designing for independence from cultural conventions (e. g., date and time displays), limiting language, and character sets.
Localization (l10n) refers to the adaptation of your program, once internationalized, to the local language and cultural habits. In theory it looks simple to implement. In practice though, it takes time and effort to provide the best Internationalization and Localization experience for your global audience.
In Python, there is a specific bundled module for that and it’s called gettext, which consists of a public API and a set of tools that help extract and generate message catalogs from the source code.
New: Introduce python's vlc library.
Python VLC is a library to control
There is not usable online documentation, you'll have to go through the
help(<component>)inside the python console.
sql_query = """SELECT name FROM sqlite_master WHERE type='table';""" cursor = sqliteConnection.cursor() cursor.execute(sql_query) print(cursor.fetchall())
New: Introduce JWT.
JWT (JSON Web Token) is a proposed Internet standard for creating data with optional signature and/or optional encryption whose payload holds JSON that asserts some number of claims. The tokens are signed either using a private secret or a public/private key.
New: Introduce Anki.
Anki is a program which makes remembering things easy. Because it's a lot more efficient than traditional study methods, you can either greatly decrease your time spent studying, or greatly increase the amount you learn.
Anyone who needs to remember things in their daily life can benefit from Anki. Since it is content-agnostic and supports images, audio, videos and scientific markup (via LaTeX), the possibilities are endless.
Although there are some python libraries:
I think the best way is to use AnkiConnect
The installation process is similar to other Anki plugins and can be accomplished in three steps:
- Open the Install Add-on dialog by selecting Tools | Add-ons | Get Add-ons... in Anki.
2055492159into the text box labeled Code and press the OK button to proceed.
- Restart Anki when prompted to do so in order to complete the installation of Anki-Connect.
Anki must be kept running in the background in order for other applications to be able to use Anki-Connect. You can verify that Anki-Connect is running at any time by accessing
localhost:8765in your browser. If the server is running, you will see the message Anki-Connect displayed in your browser window.
New: Introduce LibreElec.
LibreElec is the lightweight distribution to run Kodi
New: Introduce King Arthur Gold.
King Arthur Gold, also known as KAG, is a free Medieval Build n'Kill Multiplayer Game with Destructible Environments.
Construct freeform forts as a medieval Builder, fight in sword duels as a Knight or snipe with your bow as an Archer. KAG blends the cooperative aspects of Lost Vikings, mashes them with the full destructibility of Worms and the visual style and action of Metal Slug, brought to you by the creators of Soldat.
New: Introduce the sudoku game.
Sudoku is a logic-based, combinatorial number-placement puzzle. In classic Sudoku, the objective is to fill a 9 × 9 grid with digits so that each column, each row, and each of the nine 3 × 3 subgrids that compose the grid (also called "boxes", "blocks", or "regions") contain all of the digits from 1 to 9. The puzzle setter provides a partially completed grid, which for a well-posed puzzle has a single solution.