Thu 16 April 2020
Module not found Heroku
There are some bugs and problems that give a thrill once they're
solved. The best bugs are the ones that teach you something,
the worst bugs are the ones that indicate that you've not
improved your spelling and the difference between an l
and a 1
is large.
Figuring out why I was facing the following traceback in heroku provided a time consuming learning experience, but probably one that I won't forget.
heroku[web.1]: State changed from crashed to starting
heroku[web.1]: State changed from starting to crashed
heroku[web.1]: State changed from crashed to starting
app[web.1]: Traceback (most recent call last):
app[web.1]: File "/home/app/server/bin/server", line 3, in <module>
app[web.1]: from api.server import deploy
app[web.1]: ModuleNotFoundError: No module named 'api'
Why can't the module be found 🤔!
Worst of all, the dockerfile builds locally, and when I run it.
It's executing /home/app/server/bin/server
and ready to
receive traffic...
FROM python:3.8.2
ENV USER appuser
ENV HOME /home/${USER}
RUN mkdir -p ${HOME}/server
WORKDIR ${HOME}/server
ENV PATH ${HOME}/server/bin:${HOME}/.local/bin:$PATH
USER appuser
CMD ["server"]
I won't go into how long I spent on thinking it had something to do with permission. Looking back, it's quite clear that a permission has nothing to do with it, since the logs would say so.
Take a step back
The difference between the image on heroku and the image running locally. What probably made me assume it was a permission error was the quote from their docs:
containers are not run with root privileges in Heroku
So there was some funky business they're doing to the user I provided.
Get closer to the problem
Finding out that I could get inside the heroku container certainly helped me figure out the problem:
heroku run bash
I could now recreate the Module not found error. I tried using
pipenv
to install the module that was missing, however that
didn't work either. hmm.. Where are these modules installed??
Show me the site-packages:
python -m site
Heroku
sys.path = [
'/',
'/usr/local/lib/python38.zip',
'/usr/local/lib/python3.8',
'/usr/local/lib/python3.8/lib-dynload',
'/home/appuser/server/.local/lib/python3.8/site-packages',
'/home/appuser/server',
'/usr/local/lib/python3.8/site-packages',
]
USER_BASE: '/home/appuser/server/.local' (exists)
USER_SITE: '/home/appuser/server/.local/lib/python3.8/site-packages' (exists)
ENABLE_USER_SITE: True
Local Docker Container
sys.path = [
'/home/appuser/server',
'/usr/local/lib/python38.zip',
'/usr/local/lib/python3.8',
'/usr/local/lib/python3.8/lib-dynload',
'/home/hints/.local/lib/python3.8/site-packages',
'/usr/local/lib/python3.8/site-packages',
]
USER_BASE: '/home/appuser/.local' (exists)
USER_SITE: '/home/appuser/.local/lib/python3.8/site-packages' (exists)
ENABLE_USER_SITE: True
Right so they are not referencing the same site-packages. Are the site packages even installed in the heroku container?!?
$ ls /home/appuser/.local/lib/python3.8/site-packages
Flask-1.1.2.dist-info mccabe-0.6.1.dist-info
Flask_Alembic-2.0.1.dist-info mccabe.py
Flask_Cors-3.0.8.dist-info more_itertools
Flask_JWT_Extended-3.24.1.dist-info more_itertools-8.2.0.dist-info
Flask_SQLAlchemy-2.4.1.dist-info oauthlib
🎉 so they aren't missing...
Locally
echo $HOME
/home/hints
Heroku
$ echo $HOME
/home/hints/server
Ah.. So $HOME
has something to do with it.
Well I have $HOME=/home/appuser
and WORKDIR=/home/appuser/server
perhaps heroku is setting the work directory to the home
directory. 🤷♂️
ENV USER hints
ENV HOME /home/${USER}
RUN mkdir -p ${HOME}
WORKDIR ${HOME}
And sure enough fixing my deployment.
Thu 06 December 2018
Chain of Responsibility
Easily one of my favourite patterns from the gang of four is the chain of responsibility pattern. It aims to avoid coupling the object that sends a request to the handlers of the request. This is especially useful if the structure to our handlers follows a sense of hierarchy.
I've had very few opportunities to implement design patterns, but gaming has really helped me to envision a context where several designs can be applied as handy solutions to managing complexity.
So we will apply the chain of responsibility to a situation where we have gathered four of the most powerful wizards in a room, each of whom will test their power by casting a spell.
For this example we have our wizards as the objects which send requests.
class Wizard:
"""Create a wizard."""
def __init__(self, name: str, intelligence: int):
#: Identify the wizard by name
self.name = name
#: Intelligence as a proxy of a wizard's power.
self.intelligence = intelligence
def cast_spell(self, spell: Spell):
"""Have the wizard cast a spell."""
print(f"{self.name} casts {spell.name} spell.")
spell.cast(self)
We will make each behaviour of the spell, which is determined by the power of the wizard casting it, as an object handling a request. If the wizard does not meet the handler's requirements it passes the request on, to it's successor. This is where we have applied a sense of hierarchy to the handler.
To begin we have an Abstract Handler:
from abc import ABC
from abc import abstractmethod
class AbstractHandler(ABC):
def __init__(self, successor=None):
self._successor = successor
def handle(self, creature):
reaction = self._handle(creature)
if not reaction:
self._successor.handle(create)
@abstractmethod
def _handle(self, spell):
raise NotImplementedError("Must provide implementation in subclass.")
Now we can define our handler hierarchy:
class LowPowerFireSpell(AbstractHandler):
def _handle(self, creature):
if creature.intelligence < 10:
print("Spell backfires.")
return True
class MediumPowerFireSpell(AbstractHandler):
def _handle(self, creature):
if creature.intelligence < 20:
print("Small fire ball is cast.")
return True
class HighPowerFireSpell(AbstractHandler):
def _handle(self, creature):
if creature.intelligence < 30:
print("A fire ball blazes across the room")
return True
class GodlikePowerFireSpell(AbstractHandler):
def _handle(self, creature):
print("A Massive column of fire burns through the room!")
return True
Finally a single object to identify the spell chain.
class Spell:
def __init__(self, name: str):
#: Identifying the spell by a name
self.name = name
#: How the spell behaves at differing levels of user's power
self.chain = LowPowerFireSpell(
MediumPowerFireSpell(
HighPowerFireSpell(
GodlikePowerFireSpell()
)
)
)
def cast(self, creature):
self.chain.handle(creature)
To test their skill, we have a spell which casts a "Fire Ball". We have the following wizards present:
if __name__ == '__main__':
fire_spell = Spell('Fire Ball')
merlin = Wizard("Merlin", 8)
albus = Wizard("Albus", 18)
howl = Wizard("Howl", 28)
gandalf = Wizard("Gandalf", 38)
They are all gathered in a room, and take turns casting the same spell.
room = [merlin, albus, howl, gandalf]
for wizard in room:
wizard.cast_spell(fire_spell)
print("")
To which we should see the spell behave according to their intelligence:
(myenv) pc-name ~ $ python script.py
Merlin casts Fire Ball spell.
Spell backfires.
Albus casts Fire Ball spell.
Small fire ball is cast.
Howl casts Fire Ball spell.
A fire ball blazes across the room
Gandalf casts Fire Ball spell.
A Massive column of fire burns through the room!
(myenv) pc-name ~ $
Thu 11 October 2018
Iterator Design Pattern
Before I started reading the gang of 4 ["Go4"], I was convinced I would not need an iterator. After all, in python, they are already implemented:
x = ['a', 'b', 'c']
for i in x:
print(i)
In the frame of python lists as aggregate objects, the intent of an iterator is satisfied.
Provide a way to access the elements of an aggregate object sequentially without exposing its underlying representations.
Displaying notes
Here I explain, how the iterator became my favourite design pattern.
I have written about representation of lists before, and I don't think this will be my last time. When implementing the drop-downs in foolscap to allow a user to see sections contained in their note, I ran into an issue of complexity where I had blocks of conditionals dictating what should be displayed to a user. I wanted the user to have an indication that a note contains sections, and for them to be able to toggle a drop-down to see each section. Similar to:
(+) | circleci |
| docker |
Where my "circleci"
note would contain sections
and the "docker"
note does not. Then expanding:
<-> | circleci |
└─ | -workflow |
| docker |
This is where I realised the abstraction power of an
iterator, And I could hide the collapsed sections
behind an "if"
conditional in an iterator.
class Menu:
def __init__(self, items):
self.items = items
def visible(self):
"""Yield the next appropriate item for display."""
for item in self.items:
yield item.title
if hasattr(item, 'expand') and item.expand:
for sub_item in item.sub_items:
yield sub_item.title
Supporting further traversal policies in my Menu
class is straightforward, and
drawing becomes absurdly simplified:
def draw(menu):
"""Draw all viewable menu items."""
for item in menu.visible():
draw_item(item)
After this I thought of a more complex aggregate structure that I could traverse, like a tree depth first.
Realising the abstraction strength of the iterator, one finds its definition of intent far more compelling.
Provide a way to access the elements of an aggregate object sequentially without exposing its underlying representations.
Wed 10 October 2018
Random VM Name
Something I found to be cute about the docker engine is it's feature to create a random name for your containers, when one is not specified.
I've had some good ones e.g:
objective_galileo
distracted_euclid
Occasionally I'd be spinning up the odd VM and
have to provide some generic name like
dev-sebastien
. So instead I thought my own
arbitrary name generation could save some time
here.
Random names
The idea was to combine <adjective>-<pokemon>
and use this as the VM parameter.
Thus defining the following in .create_name.sh
function gen_name()
{
pokemon=(
"pidgey"
"pikachu"
"cubone"
)
adjectives=(
"hungry"
"adorable"
"jittery"
)
select_pokemon=${pokemon[$RANDOM % {#pokemon[@]}] }
select_desc=${adjectives[$RANDOM % {#adjectives[@]}] }
local result=sebastien-$select_desc-$select_pokemon
echo "$result"
}
Call this in your .bash_aliases
file.
source .create_name.sh
And every time you run gen_name
in your command
line, you'll get a new "vm" name.
I've coupled this with:
create_instance(){
gcloud compute instances create $(gen_name);
}
Here are some of the names of my machines:
sebastien-livid-quagsire
sebastien-lonely-metapod
sebastien-gentle-rattata
Tue 09 October 2018
Foolscap List Ordering
Foolscap was my answer to losing all my notes and forgetting the exact file I saved it.
Was it on Desktop or next to the project?
Thus I decided to write an application that took care of the saving and finding of my notes.
Unordered Lists
One thing I have taken for granted is the ordering of my files in any file system. I only realised how important it was after unordered dictionaries in python allocated my notes random positions on the list.
The random ordering meant if I have note "M" in
mind, it could appear anywhere on the list. So my
eyes would track down n
positions in the list to
find "M". An O(n)
operation for my eyes.
After growing tired (a whole day of O(n)
eye
operations), I wrote the rule to provide me the
list in alphabetical order. This was great my
brain automatically switched to doing a binary
search for note "M". O(log n)
Ordered Lists
Now that finding note "M" was optimised for my eyes, my finger had to press the down key until my cursor was on the note of choice. This wasn't good enough, I was referring to note "M" several times a day and the other notes I'd reference once a month were adding computation time to my finger.
This is where I introduced two of the most powerful rules of Foolscap. Since I tracked the number of views, and time it was last viewed or modified I could implement the following ordering:
1: LastView/Modified/RecentlyCreated
2: MostViewed
3: 2ndMostViewed
4: 3rdMostViewed
5: A
6: Z
This was neat!
I had significantly cut down the amount of time it took for me to get to the notes I was using most frequently.
Search Lists
Searching needed a slightly different ordering since applying the rules above to your search results will likely be meaningless. The meaningless will come from your inability to predict what will appear in the list to begin with.
Python has a neat method for it's strings.
note_title.startswith("text")
Which I used as the initial search feature. A
search by the prefix of my note title. To me this
made sense since my notes are titled by their
subject matter, e.g. "linux", "elastic"
.
The iteration to this search functionality was to include the conditional:
if "text" in note_title:
I still wanted to provide the user with the result of the initial prefix search as the first result in the list.
This is when I fathomed this solution:
search = [title for title, _ in notes.items()
if query in title]
# Sort by the position the query appears in the title
return sorted(search, key=lambda title: title.index(query))
Pretty neat!