fix codeblocks
This commit is contained in:
parent
b7c4b5d39b
commit
df3d2b764f
|
@ -17,7 +17,7 @@ newPythonProgressBar [deadlink]
|
|||
|
||||
To use this progressbar, it is very easy.
|
||||
|
||||
.. code:: python
|
||||
.. code-block:: python
|
||||
|
||||
# To Setup
|
||||
from progress_bar import ProgressBar
|
||||
|
|
|
@ -21,12 +21,12 @@ This would be a little cleaner.
|
|||
|
||||
this example would allow for http, https, ssh, spdy and mailto, anything else would error out.
|
||||
|
||||
.. code:: python
|
||||
.. code-block:: python
|
||||
|
||||
facebook_page = URLField(default_protocol="http", protocols=["https","ssh","spdy","mailto"])
|
||||
|
||||
The way I could improve this would be
|
||||
|
||||
.. code:: python
|
||||
.. code-block:: python
|
||||
|
||||
facebook_page = URLField(protocols=["https","https","ssh","spdy","mailto"])
|
||||
|
|
|
@ -13,14 +13,14 @@ This key had a sub key as well, so figuring out this was tricky.
|
|||
|
||||
To start, you can list your gpg keys like so:
|
||||
|
||||
.. code:: console
|
||||
.. code-block:: console
|
||||
|
||||
$ gpg --list-keys
|
||||
|
||||
|
||||
This will list keys such as
|
||||
|
||||
.. code:: console
|
||||
.. code-block:: console
|
||||
|
||||
pub 4096R/01A53981 2011-11-09 [expires: 2016-11-07]
|
||||
uid Tyrel Anthony Souza (Five year key for email.)
|
||||
|
@ -28,7 +28,7 @@ This will list keys such as
|
|||
|
||||
To make this not expire, (same steps to change expiration date to another time), you must first edit the key
|
||||
|
||||
.. code:: console
|
||||
.. code-block:: console
|
||||
|
||||
$ gpg --edit-key 01A53981
|
||||
|
||||
|
@ -38,7 +38,7 @@ You will then see a gpg prompt ``gpg>``
|
|||
Type "expire" in and you will be prompted for how long to change it to
|
||||
|
||||
|
||||
.. code:: console
|
||||
.. code-block:: console
|
||||
|
||||
Changing expiration time for the primary key.
|
||||
Please specify how long the key should be valid.
|
||||
|
|
|
@ -14,7 +14,7 @@ I recently found a cool command in BASH that I hadn't previously known. ``C-o``
|
|||
|
||||
For example:
|
||||
|
||||
.. code:: console
|
||||
.. code-block:: console
|
||||
|
||||
$ touch a
|
||||
$ touch b
|
||||
|
|
|
@ -10,7 +10,7 @@ CFEngine3 Install on CentOS 5.7
|
|||
| Today I was tasked with installing CFEngine3 on CentOS-5.7 (A little outdated). When installing CFEngine-3.3.1 I kept getting an error that I couldn't find libtokyocabinet.so.9. I had to set my prefix to /usr/ because the location that tokyocabinet was installing my libraries to was not being read by CFEngine's make script.
|
||||
| To do this (I am using tokyocabinet 1.4.47)
|
||||
|
||||
.. code:: console
|
||||
.. code-block:: console
|
||||
|
||||
wget http://fallabs.com/tokyocabinet/tokyocabinet-1.4.47.tar.gz
|
||||
tar -xzvf tokyocabinet-1.4.47.tar.gz
|
||||
|
@ -23,7 +23,7 @@ Then I was able to ./configure && make && make install cfengine3 without any pro
|
|||
|
||||
So my overall script looked something like this:
|
||||
|
||||
.. code:: console
|
||||
.. code-block:: console
|
||||
|
||||
wget http://fallabs.com/tokyocabinet/tokyocabinet-1.4.47.tar.gz
|
||||
tar -xzvf tokyocabinet-1.4.47.tar.gz
|
||||
|
@ -32,7 +32,7 @@ So my overall script looked something like this:
|
|||
make
|
||||
sudo make install
|
||||
|
||||
.. code:: console
|
||||
.. code-block:: console
|
||||
|
||||
wget http://cfengine.com/source-code/download?file=cfengine-3.3.1.tar.gz
|
||||
tar -xzvf cfengine-3.3.1.tar.gz
|
||||
|
|
|
@ -35,7 +35,7 @@ If you notice I mentioned a current environment in my previous ``pip freeze`` ex
|
|||
Let's show an example of the first time use of ``virtualenv``:
|
||||
|
||||
|
||||
.. code:: console
|
||||
.. code-block:: console
|
||||
|
||||
$ sudo pip install virtualenv # Only time you might need sudo, try without first.
|
||||
$ virtualenv myenv # Create the virtual environment
|
||||
|
@ -51,7 +51,7 @@ After you create a virtual environment, you just run``source bin/activate`` and
|
|||
|
||||
Once installed correctly, you can run the command ``mkvirtualenv envname`` to create a virtual environment. You can then run``workon envname`` from anywhere, and it will activate that environment. For example, you could be at``/var/www/vhosts/www.mysite.com/django/`` and run``workon envname`` and it would activate the environment from there. This isn't a required package (none of them are really…) as I went a couple years without using``virtualenvwrapper``, but it is very useful and now I use it every day. Some tips I use with my setup of``virtualenvwrapper`` is that I use the postactivate scripts to automatically try to change into the proper project directory of my environment. This also means I usually name my``virtualenv`` after my project name for easy memory. It makes no sense to have a project called "cash_register" but the``virtualenv`` be called "fez". This is how I change to the right project after activating my ``virtualenv``. This goes in ``$WORKON_HOME/postactivate``
|
||||
|
||||
.. code:: bash
|
||||
.. code-block:: bash
|
||||
|
||||
#!/bin/bash
|
||||
# This hook is run after every virtualenv is activated.
|
||||
|
|
|
@ -15,7 +15,7 @@ The solution, after a day and a half of research is to override the **formfield_
|
|||
|
||||
Our solution is to prefetch for any M2M that are related to the current Model.
|
||||
|
||||
.. code:: python
|
||||
.. code-block:: python
|
||||
|
||||
def formfield_for_manytomany(self, db_field, request, **kwargs):
|
||||
if db_field.__class__.__name__ == "ManyToManyField" and \
|
||||
|
|
|
@ -11,7 +11,7 @@ Recently I have been diving into using signals with Django, which of course are
|
|||
|
||||
I am working on a website for work which in the most basicexplanation, is a task management site. Recently I have added in the ability to subscribe to tasks and get emails, I did this by connecting to the post_save signal. I only email out when a task is changed, not created (of course, no one would be subscribed to it). This worked flawlessly and "emails" out to anyone who is subscribed. I say that in quotes, because I haven't actually hooked it up to a real SMTP server, and only use
|
||||
|
||||
.. code:: shell
|
||||
.. code-block:: shell
|
||||
|
||||
python -m smtpd -n -c DebuggingServer localhost:1025
|
||||
|
||||
|
@ -23,7 +23,7 @@ I tried a lot of different things, and was debating some that would be a bit mes
|
|||
|
||||
You can do this by doing something like this:
|
||||
|
||||
.. code:: python
|
||||
.. code-block:: python
|
||||
|
||||
from app.models import ModelName
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ SSH Agent on "boot"
|
|||
|
||||
I had a friend complain that he had to keep adding his ssh key to his ssh-agent every time he rebooted. I have a really easy bit of shell code you can put into your .bashrc or your .zshrc file:
|
||||
|
||||
.. code:: bash
|
||||
.. code-block:: bash
|
||||
|
||||
SSHKEYFILE=/path/to/your/ssh/key/file
|
||||
ssh-add -l | grep -q $SSHKEYFILE
|
||||
|
|
|
@ -56,7 +56,7 @@ I added some markers to figure out what I needed to imitate in ESPHome, and saw
|
|||
|
||||
This looks like this in yaml:
|
||||
|
||||
.. code:: yaml
|
||||
.. code-block:: yaml
|
||||
|
||||
switch:
|
||||
- platform: gpio
|
||||
|
@ -78,7 +78,7 @@ I'm pretty sure I jumped and screamed with excitement when it opened!
|
|||
|
||||
Once the door was opening and closing, I was able to add more yaml to set another binary sensor to show whether it was open or closed (from the reed sensor):
|
||||
|
||||
.. code:: yaml
|
||||
.. code-block:: yaml
|
||||
|
||||
binary_sensor:
|
||||
- platform: gpio
|
||||
|
@ -90,7 +90,7 @@ Once the door was opening and closing, I was able to add more yaml to set anothe
|
|||
|
||||
All together this is shown on my Home Assistant Lovelace dashboard using two cards, one that shows a closed door, and one with an open door (both actual pictures of the door!) with a button to open it. Once it opens or closes the other card switches into place, Home Assistant at least at the time didn't have good conditional cards like I wanted.
|
||||
|
||||
.. code:: yaml
|
||||
.. code-block:: yaml
|
||||
|
||||
type: conditional
|
||||
conditions:
|
||||
|
|
|
@ -18,14 +18,14 @@ The tool I've chosen for reading EPUBs is the Python library `ebooklib <https://
|
|||
|
||||
My first task was to find an EPUB file, so I downloaded one from my calibre server. I convert all my ebook files to ``.epub`` and ``.mobi`` on my calibre server so I can access them anywhere I can read my OPDS feed. I chose Throne of Glass (abbreviating to ``TOG.epub`` for rest of post). Loading I launched Python, and ran
|
||||
|
||||
.. code:: console
|
||||
.. code-block:: console
|
||||
|
||||
>>> from ebooklib import epub
|
||||
>>> print(book := epub.read_epub("TOG.epub")
|
||||
|
||||
This returned me a ``<ebooklib.epub.EpubBook object...>`` , seeing I had an EpubBook I ran a ``dir(book)`` and found the properties available to me
|
||||
|
||||
.. code:: python
|
||||
.. code-block:: python
|
||||
|
||||
['add_author', 'add_item', 'add_metadata', 'add_prefix',
|
||||
'bindings', 'direction', 'get_item_with_href', 'get_item_with_id',
|
||||
|
@ -42,7 +42,7 @@ I will note, at this time I was thinking that this wasn't the direction I wanted
|
|||
|
||||
Seeing I was on at least some track, I opened up PyCharm and made a new Project. First I setup a class called Epub, made a couple of functions for setting things up and ended up with
|
||||
|
||||
.. code:: python
|
||||
.. code-block:: python
|
||||
|
||||
class Epub:
|
||||
def __init__(self, book_path: str) -> None:
|
||||
|
@ -52,7 +52,7 @@ Seeing I was on at least some track, I opened up PyCharm and made a new Project.
|
|||
|
||||
I then setup a ``parse_chapters`` file, where I loop through the TOC. Here I went to the definition of ``Link`` and saw I was able to get a ``href`` and a ``title``, I decided my object for chapters would be a dictionary (I'll move to a DataClass later) with ``title`` and ``content``. I remembered from earlier I had a ``get_item_by_href`` so I stored the itext from the TOC's href: ``self.contents.get_item_with_href(link.href).get_content()``. This would later prove to be a bad decision when I opened "The Fold.epub" and realized that a TOC could have a tuple of ``Section`` and ``Link``, not just ``Links``. I ended up storing the item itself, and doing a double loop in the ``parse_chapters`` function to loop if it's a tuple.
|
||||
|
||||
.. code:: python
|
||||
.. code-block:: python
|
||||
|
||||
def parse_chapters(self) -> None:
|
||||
idx = 0
|
||||
|
@ -67,7 +67,7 @@ I then setup a ``parse_chapters`` file, where I loop through the TOC. Here I wen
|
|||
|
||||
``_parse_link`` simply makes that dictionary of ``title`` and ``item`` I mentioned earlier, with a new ``index`` as I introduced buttons in the DearPyGUI at this time as well.
|
||||
|
||||
.. code:: python
|
||||
.. code-block:: python
|
||||
|
||||
def _parse_link(self, idx, link) -> None:
|
||||
title = link.title
|
||||
|
@ -81,7 +81,7 @@ That's really all there is to make an MVP of an EPUB parser. You can use ``Beaut
|
|||
|
||||
In my implementation my Epub class keeps track of the currently selected chapter, so this loads from all chapters and sets the ``current_text`` variable.
|
||||
|
||||
.. code:: python
|
||||
.. code-block:: python
|
||||
|
||||
def load_view(self) -> None:
|
||||
item = self.chapters[self.current_index]['item']
|
||||
|
|
|
@ -9,7 +9,7 @@ Scrollbar Colors
|
|||
|
||||
Was talking to someone about CSS Nostalgia and "back in my day" when scrollbar colors came up.
|
||||
|
||||
.. code:: css
|
||||
.. code-block:: css
|
||||
|
||||
/* For Chromium based browsers */
|
||||
::-webkit-scrollbar {
|
||||
|
|
|
@ -17,11 +17,11 @@ My first job out of college was a Python/Django company - and that directed my n
|
|||
Django, if you are unaware, is a MVC framework that ships with a really great ORM.
|
||||
You can do about 95% of your database queries automatically by using the ORM.
|
||||
|
||||
.. code:: python
|
||||
.. code-block:: python
|
||||
|
||||
entry, created = Entry.objects.get_or_create(headline="blah blah blah")
|
||||
|
||||
.. code:: python
|
||||
.. code-block:: python
|
||||
|
||||
q = Entry.objects.filter(headline__startswith="What")
|
||||
q = q.filter(pub_date__lte=datetime.date.today())
|
||||
|
@ -49,7 +49,7 @@ Full design disclosure: I followed a couple of blog posts in order to develop th
|
|||
In order to instantiate a model definition, it's pretty easy.
|
||||
What I did is make a new package called ``models`` and inside made a file for my Album.
|
||||
|
||||
.. code:: go
|
||||
.. code-block:: go
|
||||
|
||||
type Album struct {
|
||||
ID string `json:"id" gorm:"primary_key"`
|
||||
|
@ -67,7 +67,7 @@ Each of the controller functions were bound to a ``gin.Context`` pointer, rather
|
|||
|
||||
The ``FindAlbum`` controller was simple:
|
||||
|
||||
.. code:: go
|
||||
.. code-block:: go
|
||||
|
||||
func FindAlbum(c *gin.Context) {
|
||||
var album models.Album
|
||||
|
@ -79,7 +79,7 @@ The ``FindAlbum`` controller was simple:
|
|||
|
||||
Which will take in a ``/:id`` path parameter, and the GORM part of this is the third line there.
|
||||
|
||||
.. code:: go
|
||||
.. code-block:: go
|
||||
|
||||
models.DB.Where("id = ?", c.Param("id")).First(&album).Error
|
||||
|
||||
|
@ -90,7 +90,7 @@ Error handling is standard Go logic, ``if err != nil`` etc and then pass that in
|
|||
|
||||
This was really easy to set up, and if you want to get a slice back you just use ``DB.Find`` instead, and bind to a slice of those structs.
|
||||
|
||||
.. code:: go
|
||||
.. code-block:: go
|
||||
|
||||
var albums []models.Album
|
||||
models.DB.Find(&albums)
|
||||
|
@ -109,7 +109,7 @@ I'll only bother describing the ``models`` package here, as thats the SQLX part
|
|||
|
||||
In the ``models/album.go`` file, there's your standard struct here, but this time its bound to ``db`` not ``json``, I didn't look too deep yet but I presume that also forces the columns to set the json name.
|
||||
|
||||
.. code:: go
|
||||
.. code-block:: go
|
||||
|
||||
type Album struct {
|
||||
ID int64 `db:"id"`
|
||||
|
@ -120,7 +120,7 @@ In the ``models/album.go`` file, there's your standard struct here, but this tim
|
|||
|
||||
An interface to make a service, and a receiver are made for applying the ``CreateAlbum`` form (in another package) which sets the form name and json name in it.
|
||||
|
||||
.. code:: go
|
||||
.. code-block:: go
|
||||
|
||||
func (a *Album) ApplyForm(form *forms.CreateAlbum) {
|
||||
a.ID = *form.ID
|
||||
|
@ -135,7 +135,7 @@ Nested inside the ``models/sql/album.go`` file and package, is all of the Receiv
|
|||
I'll just comment the smallest one, as that gets my point across.
|
||||
Here is where the main part of GORM/SQLX differ - raw SQL shows up.
|
||||
|
||||
.. code:: go
|
||||
.. code-block:: go
|
||||
|
||||
func (s *AlbumService) GetAll() (*[]models2.Album, error) {
|
||||
q := `SELECT * FROM albums;`
|
||||
|
|
|
@ -41,7 +41,7 @@ For software, I installed the python packages for Pimoroni and Blinkt, which cam
|
|||
|
||||
I then added a new service in systemd to control the mqtt server
|
||||
|
||||
.. code:: ini
|
||||
.. code-block:: ini
|
||||
|
||||
[Unit]
|
||||
Description=Meeting Indicator
|
||||
|
|
|
@ -14,7 +14,7 @@ Recently my coworker set something up that we need an environment variable set u
|
|||
* After that you can use ``lpass show`` and capture that in a variable to export your API key as an environment variable.
|
||||
|
||||
|
||||
.. code:: bash
|
||||
.. code-block:: bash
|
||||
|
||||
lpass status
|
||||
if [ $? -ne 0 ]; then
|
||||
|
|
|
@ -13,7 +13,7 @@ I was talking to a `friend <https://fredeb.dev>`_ [citation needed] about updati
|
|||
|
||||
I did this by showing the following output:
|
||||
|
||||
.. code:: shell
|
||||
.. code-block:: shell
|
||||
|
||||
$ which ls
|
||||
/usr/bin/ls
|
||||
|
@ -34,7 +34,7 @@ It turns out that ZSH's ``which`` is equivalent to the ZSH shell built-in ``when
|
|||
|
||||
After running ``/usr/bin/zsh`` and sourcing my aliases (I don't have a zshrc file anymore, I need to set that back up), I was able to settle my fears and prove to myself that I wasn't making things up. There is a which which shows you which aliases you have set up, which is default for ZSH.
|
||||
|
||||
.. code:: shell
|
||||
.. code-block:: shell
|
||||
|
||||
$ which ls
|
||||
ls: aliased to exa -lhFgxUm --git --time-style long-iso --group-directories-first
|
||||
|
|
93
content/blog/2023-10-03_rotate-a-matrix-in-python.rst
Normal file
93
content/blog/2023-10-03_rotate-a-matrix-in-python.rst
Normal file
|
@ -0,0 +1,93 @@
|
|||
Rotate a Matrix in Python
|
||||
#########################
|
||||
:author: tyrel
|
||||
:category: Tech
|
||||
:tags: python
|
||||
:status: published
|
||||
|
||||
I've been doing Advent of Code for a few years now, and every year I do it in my favorite language, Python.
|
||||
One thing that comes up a lot, is rotating matrices.
|
||||
|
||||
One way to do this, is to use Numpy, using ``np.rot90(mat)``, but not everyone wants to install Numpy just to do one small task.
|
||||
I know I don't always.
|
||||
|
||||
The way I always do it, that will support non-square matrixes, is to use zip.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
>>> matrix = [
|
||||
[1,2,3],
|
||||
[4,5,6],
|
||||
[7,8,9]
|
||||
]
|
||||
>>> rotated = list(zip(*matrix[::-1]))
|
||||
# And result is
|
||||
[[7, 4, 1],
|
||||
[8, 5, 2],
|
||||
[9, 6, 3]]
|
||||
|
||||
We can break this down bit by bit.
|
||||
|
||||
This will copy the list, with a -1 step, resulting in a reverse order
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
>>> matrix[::-1]
|
||||
[[7,8,9],
|
||||
[4,5,6],
|
||||
[1,2,3]]
|
||||
|
||||
Next we need to call zip in order to get the x-th item from each inner list, but first, we need to unpack it. If you'll notice, the unpacked version isn't wrapped with another list, which is what zip needs from us.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
# Too many lists
|
||||
>>> print(matrix[::-1])
|
||||
[[7, 8, 9], [4, 5, 6], [1, 2, 3]]
|
||||
|
||||
# Just right
|
||||
>>> print(*matrix[::-1])
|
||||
[7, 8, 9] [4, 5, 6] [1, 2, 3]
|
||||
|
||||
From there, we can pass this unpacked list of - in our case - three lists, to zip (and in Python 3 this returns a generator, so we need to call list again on it, or just use it)
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
>>> # Again, we get the rotated matrix
|
||||
>>> list(zip(*matrix[::-1]))
|
||||
[[7, 4, 1],
|
||||
[8, 5, 2],
|
||||
[9, 6, 3]]
|
||||
|
||||
|
||||
Notes
|
||||
-----
|
||||
|
||||
Small note: If you run this, you will actually get a list of tuples, so you can map those back to a list, if you need to update them for any reason.
|
||||
I just wanted square brackets in my examples.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
# This is just messy looking, so I didn't mention it until now
|
||||
>>> list(map(list, zip(*matrix[::-1])))
|
||||
|
||||
|
||||
As I mentioned, due to using ``zip`` this will work with non-square examples as well.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
>>> matrix = [
|
||||
... [1,2,3,4,5,6,7,8,9],
|
||||
... [9,8,7,6,5,4,3,2,1],
|
||||
... ]
|
||||
>>> print(list(zip(*matrix[::-1])))
|
||||
[(9, 1),
|
||||
(8, 2),
|
||||
(7, 3),
|
||||
(6, 4),
|
||||
(5, 5),
|
||||
(4, 6),
|
||||
(3, 7),
|
||||
(2, 8),
|
||||
(1, 9)]
|
||||
|
|
@ -40,7 +40,7 @@ FEED_ATOM = 'tyrel-dev.atom.xml'
|
|||
FEED_ALL_ATOM = 'tyrel-dev.all.xml'
|
||||
|
||||
|
||||
PLUGINS = ["webassets"]
|
||||
PLUGINS = ["webassets","syntax_highlighting"]
|
||||
|
||||
DEFAULT_PAGINATION = True
|
||||
DISPLAY_CATEGORIES_ON_MENU = False
|
||||
|
|
Loading…
Reference in New Issue
Block a user