monkinetic

Steve Ivy's weblog, XI Ed.

New Markbox invites have gone out

It's been a crazy road with more hair-pulling and teeth-gnashing than I had hoped, but I've scheduled the final set of invites for Markbox. Anyone who had signed up as of tonight to be notified will be sent an invite in the morning.

The hardest part of this for me is turning on Billing. Markbox has operating expenses that I need to recouop a little bit of so it can keep going, so Markbox is now $6/mo. through the end of the Beta. How much it will be thereafter remains to be seen. I have some ideas but I'm not going to commit to anything right now.

It's nearly midnight. I'm excited and exhausted. Those who say you can build and launch as web product on the side these days is technically, but not practically, correct. It's amazingly hard and after months and months working on this I'm still embarassed at some parts of it.

But I'm not going to let this stop me.

When in doubt...

...put it in a transaction.

This nerd advice brought to you by flask and MySQL.

p.s. Anyone remember the msql/mysql wars of the mid 90s?

SqlAlchemy Relationship Error: 'property of that name exists on mapper'

The Setup

I'm writing a web app in python with Flask and SqlAlchemy with MySQL.

the solution...

The Code

Starting with the following (slightly snipped for brevity) python/SqlAlchemy code in <project>/markbox/models.py:

class UserBlog(ModelBase):
    __tablename__ = 'user_blog'

    id = sa.Column(sa.Integer, primary_key=True)
    uid = sa.Column(strcol)
    # blog title
    name = sa.Column(strcol)

    # returns a query => blog.sync_stats.all()
    sync_stats = relationship(
        'models.SyncStats', backref='blog',
        lazy='dynamic')


class SyncStats(ModelBase):
    """
    Store various statistics about sync operations
    """
    __tablename__ = 'system_syncstats'

    id = sa.Column(sa.Integer, primary_key=True)
    uid = sa.Column(strcol, sa.ForeignKey('user_blogsettings.uid'))

And this code in <project>/markbox/tools/test.py:

import sys
import os

sys.path.append(os.path.abspath('.'))
sys.path.append(os.path.abspath('markbox'))
print sys.path

from markbox.models import UserBlog, SyncStats

from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, String, DateTime
from sqlalchemy.orm import sessionmaker

SQLALCHEMY_DATABASE_URI = "mysql://markbox_user:markbox@localhost/markbox"

engine = create_engine(SQLALCHEMY_DATABASE_URI, echo='debug')
Session = sessionmaker(bind=engine)
session = Session()

if __name__ == '__main__':
    blog = UserBlog.query.limit(1)

The Error

When run from the command line in <project>:

% python markbox/tools/test.py

I get:

['/Users/sivy/Projects/personal/markbox/markbox/tools', ..., '/Users/sivy/Projects/personal/markbox', '/Users/sivy/Projects/personal/markbox/markbox']
Traceback (most recent call last):
  File "markbox/tools/test.py", line 25, in <module>
    blog = UserBlog.query.limit(1)
  File "/Users/sivy/.virtualenvs/markbox/lib/python2.7/site-packages/sqlalchemy/orm/scoping.py", line 131, in __get__
    mapper = class_mapper(owner)
  File "/Users/sivy/.virtualenvs/markbox/lib/python2.7/site-packages/sqlalchemy/orm/util.py", line 1112, in class_mapper
    mapper = _inspect_mapped_class(class_, configure=configure)
  File "/Users/sivy/.virtualenvs/markbox/lib/python2.7/site-packages/sqlalchemy/orm/util.py", line 1045, in _inspect_mapped_class
    mapperlib.configure_mappers()
  File "/Users/sivy/.virtualenvs/markbox/lib/python2.7/site-packages/sqlalchemy/orm/mapper.py", line 2122, in configure_mappers
    mapper._post_configure_properties()
  File "/Users/sivy/.virtualenvs/markbox/lib/python2.7/site-packages/sqlalchemy/orm/mapper.py", line 1244, in _post_configure_properties
    prop.init()
  File "/Users/sivy/.virtualenvs/markbox/lib/python2.7/site-packages/sqlalchemy/orm/interfaces.py", line 231, in init
    self.do_init()
  File "/Users/sivy/.virtualenvs/markbox/lib/python2.7/site-packages/sqlalchemy/orm/properties.py", line 1031, in do_init
    self._generate_backref()
  File "/Users/sivy/.virtualenvs/markbox/lib/python2.7/site-packages/sqlalchemy/orm/properties.py", line 1220, in _generate_backref
    self, m))
sqlalchemy.exc.ArgumentError: Error creating backref 'blog' on relationship 'UserBlog.sync_stats': property of that name exists on mapper 'Mapper|SyncStats|system_syncstats'

What I've Done

I've already confirmed that:

  • the SyncStats model has no "blog" property (it used to have a method, decorated with @property).
  • I've deleted any existing *.pyc files to make sure that the interpreter is not picking up pre-compiled code.

The solution

So, the problem turned out to be that the models were being imported from two paths:

from models import UserBlog

and later:

from markbox.models import UserBlog

This caused the intilization code to be run twice, and the resulting error.

Crowning Moment of Heart Warming

My kids, wife, and Mom went to the movies today (Turbo, well-liked all around) and before they went they stopped by the drugstore and bought movies snacks. Apparently our 8yo daughter, remembering Daddy's favorite candy, convinced Mom to buy a box of Reese's Pieces.

After the movie and a couple more errands, they came home, at which time our youngest called out something akin to "No Peeeeeking" and disappeared into her room. 20 minutes later she appeared in my office with a note that said (she's somewhat developmentally delayed) "Daddy <her name> romm for You Lov <her name>". She excitedly communicated that this was a hint and I was to accompany her to her room, where I got to search her room for a present.

When I found and opened the small gift bag under her pillow containing a wrapped-with-a-bow box of candy, my heart simply melted. How did I deserve such love and adoration?

Reeses Pieces

If monkinetic Then app.net

I'm testing out a basic IFTTT recipe that reposts monkinetic posts to my app.net account.

Update: Sorry I didn't realize when I made the recipe that it was going to grab the last n existing posts and repost them as well. Whoops. Thankfully it only reposted the last 3 posts.

Why is Adobe Flash Installing Google Chrome?

So, like a sheep, I install the latest Adobe Flash (bleagh) this morning so I can watch the Superb Owl Iron Man 3 commercial, since Adobe's being a snot and pigging backing on the Superb Owl's popularity to get more Flash installs out there, and I see this:

Adobe Flash installing Google Chrome

Since when does Flash install Chrome? /me Googles

Apparently, since at least August of 2012 accordion to this Adobe Forum post:

For regularly scheduled Flash Player releases, such as our 11.4 release, users are notified of new features included in the release and may opt to download the latest player via http://get.adobe.com/flashplayer. This workflow allows users to optionally download software from select Adobe partners along with Flash Player. Adobe offsets the ongoing development costs of Flash Player, which is made available for free, by offering users these options. Bundling Google Chrome and Toolbar???

Hm.

A Modern Proverb

Three things you should be wary of,
A new kid in his prime,
A man with all the answers,
And code that runs first time.

From Idea to Reality

Back in September, I posted about an idea I had while commuting to work: DropDownMarkBox describes my frustration with publishing times on Scriptogram (an otherwise fine and good looking service) and how I thought I might build a similar system.

4 months later, working in my limited spare time, Markbox is a reality, in Beta, and getting better.

#winning

Dogfood

This site is now hosted on markbox, my new Dropbox and Markdown blogging platform.

Markbox is running on Google's AppEngine, which is a pretty great platform, even with its warts. All posts are sitting in my Dropbox (in /Apps/markbox/posts/) and template files live in /Apps/markbox/templates.

I can post from Mou, my favorite OS X Markdwn editor, or (as I am now) from within the app itself. It's pretty much my ideal blogging platform right now (it should be, I wrote it :-) ) and I've got even more ideas coming.

Markbox Progress

I released some new features to Markbox Beta users today: an overhauled template system that now supports template includes, and new template sync options. Read the blog post!

markbox: for nerds and their words