"Welcome To My Brain Dump."

May 02, 2012

Back For More - GSOC Round Two

After GSOC last year, I decided that I definitely wanted to partake when the opportunity rolled around this year. I talked with a few individuals in the Pyramid community about this during Pycon, and later on in the mailing lists. After a few weeks, we got the ball rolling and a few ideas were thrown around for a possible project. The first idea that came up involved modifying the pyramid debug toolbar to include some new introspection features, by leveraging a relatively new tool called Pyrasite. After a few discussions, we came to the conclusion that although this new feature would be really cool, we would passing up a golden opportunity to get a long awaited perk rolled out for pyramid. What is this feature you might ask? Wait for it. A WINDOWS INSTALLER! And better Windows support in general. I know, I know, most of us are linux/mac hackers/elitists, and wouldn't really give Windows a second thought. The fact of the matter is, is that there a number of Windows Python users. We would be completely ignoring a huge potential user base if we continued to only consider the user experience of linux/mac users. So this brings us to the present.

I have been tasked with creating a Windows installer primarily in the first half of GSOC, and then during the second half, I will explore potential ways to make the Windows experience even better. I am extremely new to development for the win32api, and had to do some research to even have a clue of where to begin. I discovered that there are a number of tools for creating installers. The major ones are NSIS, Windows Installer, and Install Shield. NSIS seemed like the best option, as it is the only one that was open source, and it was even actively used by large companies such as Google and Yahoo. After reading a few blog posts about it, however, I discovered that it had one major flaw. It's scripting language. A number of users reported that it was an absolute nightmare to do anything that wasn't already packaged in the tool. So basically....if you need to do something beyond the scope of the 10 or so widgets, you're going to have a bad time. NSIS isn't alone either, most users of any of these major installer-creation tools complained that the scripting languages were clunky and hard to use.

I have come to the conclusion that I will be far better of if I write my own installer from scratch in C++. This will give me the added benefit of improving my C++ skills, learning the win32api, and making an incredibly custom installer for the Pyramid community. I will be able to customize the look and feel of the installer, and give Pyramid a very cool "cover." This blog post was what really convinced me that this task is definitely possible. At first I was really skeptical of this project, as I'm not an avid Window's user for anything besides gaming, but now I am actually pretty psyched to get started! What do people think about my course of action? E-mail me.

December 05, 2011

Upboat This Post Again

So previously, I started making a tutorial that went into great depth about the entire process of making a webapp in Pyramid and treated the social voting functionality as more of supplemental knowledge; however, in the end I decided that it would better serve the community to make a far shorter "guide" on how to implement social voting in a web site. So here it is. It should also be known that I recently made a much prettier version of this tutorial that can be found here.

Adding Social Voting to Your Pyramid App

So you've been to Reddit, Digg, StackOverflow, and the billion other sites that use social voting, and you love the concept of your users rating the importance of your content completely for free. This guide will go through the basic steps of implementing such a system, and also give you some working source code to see how I created one. I'm not really calling this a "tutorial" per se, as I am not going to really go through anything step by step. I am mostly going to give you the higher level details. Then using the code I have provided, and the concepts I introduce, you should be able to go out into the big wide world and write your own. This seems fitting, as social voting is a piece of functionality that is very closely connected to your data, so having you create some dummy app with social voting might not be the best use of your time. Due to this, I would say that this guide is probably written for moderate/advanced Pyramid/SQLAlchemy users. So let's start.

So first things first, I have created a very simple social voting implementation here. In order to test it out, run the follow commands:

jayd3e ~/Projects/Upboat $ python setup.py develop
jayd3e ~/Projects/Upboat $ python demos/demo.py

You should see something like this get printed out:

serving on 0.0.0.0:5020 view at http://127.0.0.1:5020

You can then view the application by going to http://127.0.0.1:5020 as it mentions. Basically this page just demonstrates that a single user can click on the up/down vote arrows, and have those actions persisted in the database. The demo really doesn't show much, as it only uses a single global user id, but if you were to actually implement this on a working site, with multiple users, each up/down vote would be linked to their respective user. So anyway, how does it work?

Database Representation Of the Data

Let's start with the obvious things. In order for something to get voted on, you need the "voted" and the "voter." In other words, you need an object of some sort, usually a comment, post, or link, and a user to say they either like or dislike that object. So using this knowledge we can create a primitive voting system(represented below in database tables):

        users                                            posts
--------------------               ------------------------------------------------
|  id   |   name   |               |  id  |  title  |  body  |  owner  |  score   | 
--------------------               ------------------------------------------------

So here we have a pretty normal situation, you have a bunch of user created posts, that contain a title, text body, and an owner. We could easily allow these posts to be voted upon by adding an up/down vote arrow next to each post in user interface, and then have a view that receives the id of the post and whether it was upvoted or downvoted. This view would then find the respective post, and would either increment or decrement the score field by 1. The problems with this system should be pretty obvious, under this system a user would be able to voted for things multiple times, b/c we're not tracking who has voted on what post. It is also a problem, because our users would not be able to see what they have voted on. So the questions arises, how do you keep track of every single time a user clicks on an up/down vote arrow? If you think about it, every time someone votes on a piece of content, they are creating a link between their user and that piece of content on the back-end. So now as we get further into the problem, we can start seeing a many-to-many relationship emerge, b/c every time a vote is made, that aforementioned "link" can be represented like this:

            users_posts
-----------------------------------
|  user_id  |  post_id  |  vote  |
-----------------------------------

So every time a user clicks on an arrow, a record is stored in the database that persists that specific user(user_id) voting on a specific post(post_id) in a way that is indicated by the 'vote' field in some way, either as a string('up or 'down') or a integer(-1 or 1). I like the number approach better, as you can then sum all of votes for a specific post to arrive at the score of that post.

On a side note, many-to-many relationships, or more specifically an association objects, are incredibly common for solving problems such as these, where you have a number of "links" between objects being made. The difference between a many-to-many relationship and an association object patterns are that in SQLAlchemy, a many-to-many relationship uses a "secondary" table in order to relate two tables while an association object uses another model that inherits from the Base. A standard many-to-many ends up looking something like this:

UserGroupModel = Table('users_groups', Base.metadata,
                       Column('user_id', Integer, ForeignKey('users.id'), primary_key=True),
                       Column('group_id', Integer, ForeignKey('groups.id'), primary_key=True)
)

class GroupModel(Base):
    __tablename__ = 'groups'

    id = Column(Integer, primary_key=True)
    name = Column(String(50))

    def __init__(self, **fields):
        self.__dict__.update(fields)

    def __repr__(self):
        return "<Group('%s', '%s')>" % (self.id,
                                        self.name)

class UserModel(Base):
    __tablename__ = 'users'

    id = Column(Integer, primary_key=True)
    identifier = Column(String(50))
    password = Column(String(40))
    groups = relationship(GroupModel,
                          secondary=UserGroupModel,
                          backref="users")

    def __init__(self, **fields):
        self.__dict__.update(fields)

    def __repr__(self):
        return "<User('%s', '%s')>" % (self.id,
                                       self.identifier)

While on the other hand, an association object uses a completely separate model, which inherits from the base just like the rest of them, in order to create the relationship. This opens up the possibility to stick other values on the intermediary model which store extra data about the link. We'll use this concept to store whether a vote is an up/down vote later. One caveat of the association object pattern, however, is that you have to interact with the intermediary model directly and use association proxies, as opposed to it being completely transparent in a standard many-to-many. You can read more on this topic here. From the demo code, this is an example of an association object:

class ObjectsModel(Base):
    __tablename__ = 'objects'

    id = Column(Integer, primary_key=True)
    score = Column(Integer(100), default=0)
    voted_users = association_proxy('users_objects', 'users')

    def __init__(self, **fields):
        self.__dict__.update(fields)

    def __repr__(self):
        return "<Objects('%s')>" % (self.id)

class UsersModel(Base):
    __tablename__ = 'users'

    id = Column(Integer, primary_key=True)
    voted_objects = association_proxy('users_objects', 'objects')

    def __init__(self, **fields):
        self.__dict__.update(fields)

    def __repr__(self):
        return "<Users('%s', '%s', '%s')>" % (self.id)

class UsersObjectsModel(Base):
    __tablename__ = 'users_objects'

    id = Column(Integer, primary_key=True)
    user_id = Column(Integer, ForeignKey('users.id'))
    object_id = Column(Integer, ForeignKey('objects.id'))
    vote = Column(Integer(1))

    users = relationship(UsersModel,
                         backref="users_objects")
    objects = relationship(ObjectsModel,
                           backref="users_objects")

    def __init__(self, **fields):
        self.__dict__.update(fields)

    def __repr__(self):
        return "<UsersComments('%s', '%s', '%s')>" % (self.user_id,
                                                      self.object_id,
                                                      self.vote)

For another example of a use of association objects, recently I made an app that is used for making Dota 2 guides. In this app, I had a number of users adding items from a list of about 125 into different sections of each guide. I used a an association object to create a relationship between my "guide" model and my "user" model each time someone dragged an item into a section of a guide. This got me to a point where I could see which items were added to which guide; however, I needed to see exactly which section of the guide the item was added to, so I add some metadata to the relationship. Putting a "section" field on the intermediary model allowed me to see exactly which section of the guide the user added the item to. I tend to always like to use association objects as opposed to many-to-many relationships, as it always gives me to add metadata to the relationship later on.

Pyramid-Specific Stuff

So now we know how the data is represented in the database, and how we keep track of each user voting on content. Now let's look at the stuff we add to our Pyramid configuration. Believe it or not, you can get away with only having to add a single route and a single view to your application. Let's check out the route first:

config.add_route('toggle_vote', '/toggle_vote/{user_id}/{object_id}/{vote}')

Knowing how it looks in the database, this looks pretty appropriate, right? Every time a user votes on something, we make this request and pass in the id of the user(could alternately be their username or something), the id of the object(comment, post, article, etc), and the orientation of their vote. This can be directed to from a link, but the cleaner approach is to spawn an AJAX request each time a user clicks on an up/down arrow, which is the approach I take in the demo. Either way, once you make a request that matches this route, a view like this is called:

class ToggleVoteHandler(object):
    def __init__(self, request):
        self.request = request
        self.here = request.environ['PATH_INFO']
        self.matchdict = request.matchdict

    @view_config(route_name='toggle_vote', renderer='json')
    def toggle_vote(self):
        user_id = self.matchdict['user_id']
        object_id = self.matchdict['object_id']
        vote = self.matchdict['vote']

        db = self.request.db
        voted_object = db.query(ObjectsModel).filter_by(id=object_id).first()
        if vote=='up':
            vote = 1
        elif vote=='down':
            vote = -1
        else:
            return {'status' : 'unchanged', 'score' : voted_object.score}

        users_objects = db.query(UsersObjectsModel).filter_by(user_id=user_id,
                                                              object_id=object_id).first()
        # Vote exists                                                             
        if users_objects:
            if users_objects.vote != vote:
                users_objects.vote = vote
                db.flush()
                status = 'changed'
            else:
                db.delete(users_objects)
                db.flush()
                status = 'deleted'

        # Vote doesn't exist
        else:
            users_objects = UsersObjectsModel(user_id=user_id,
                                              object_id=object_id,
                                              vote=vote)
            db.add(users_objects)
            db.flush()
            status = 'added'

        score = self.calculateScore(voted_object)
        voted_object.score = score
        db.flush()
        return {'status' : status, 'score' : score}

    def calculateScore(self, voted_object):
        score = 0
        for users_objects in voted_object.users_objects:
            score += users_objects.vote
        return score

So this view pretty much does all of the business logic we have talked about, plus a little extra. It get's the user_id, object_id, and the vote through the matchdict, and makes sure that the vote is a valid value of '-1' or '1'. Then it tries to find out if the user has voted on this specific object before. If they have, it then further checks if the vote is of the same orientation or not, and either changes the vote or deletes the relationship(if the user clicks on the same orientation a second time, they are trying to remove their vote) respectively. If they haven't voted on this object before, the view creates a link between the user and the object with the specified vote orientation. Lastly all of the votes related with the object are summed and the score is return in a JSON object, as well as a status string that I included for the front-end. So this process should be fairly straight forward, once you get the hang of the way the data is managed in the database, as the view is the element of the application that is actually doing all of the heavy lifting to store/correct the data. Now all that is left is the front-end.

Let's Get the Client Talking To Us

The last step in getting this system to work, is we need a way to get the client to tell us when a user clicks on a up or down arrow. As I mentioned before, you could make each arrow an anchor tag to the appropriate view, but this wouldn't provide for a very responsive interface. So what I have done is, added an onclick event to the up/down arrows, which sends a request to the Pyramid app which is handled by the 'toggle_vote' view. Here is what the voting buttons look like next to each post in the demo.

<div class="vote">
    <div class="${up}" onClick="javascript: toggle_vote(this, ${user_id}, ${object.id}, 'up');"></div>
    <div class="${down}" onClick="javascript: toggle_vote(this, ${user_id}, ${object.id}, 'down');"></div>
</div>

This calls a javascript function called, appropriately, 'toggle_vote', which does all of the interfacey changes once a vote is made. It looks like this:

toggle_vote = function(node, user_id, object_id, vote) {
    object_vote = node.parentNode;
    object = object_vote.parentNode;

    removeActiveClass = function(node) {
        index = node.className.indexOf(" active");
        node.className = (index != -1) ? node.className.substring(0, index) : node.className;
    };

    addActiveClass = function(node) {
        node.className = node.className + " active";
    };

    removeAllActiveClasses = function(parent) {
        $.each(parent.children, function(index, child) {
            removeActiveClass(child); 
        });
    };

    setScore = function(score) {
        object_score = undefined;
        $.each(object.children, function(index, child) {
            if (child.className == "score") {
                object_score = child;   
            }
        });
        object_score.innerHTML = String(score);
    };

    toggleVoteCallback = function(data) {
        if (data.status != "unchanged") {
            if (node.className.indexOf("active") != -1) {
                removeAllActiveClasses(object_vote);
            }
            else {
                removeAllActiveClasses(object_vote);
                addActiveClass(node);
            }
        }

        setScore(data.score);
    };

    $.ajax({
    type: "GET",
        url: "/toggle_vote/" + user_id + "/" + object_id + "/" + vote,
        success: toggleVoteCallback
    });
};

I'm sure their is an easier way to do some of these things with some jQuery magic unknown to me, but essentially what it does, is it first sends a AJAX GET request to the 'toggle_vote' view that we talked about previously. Then according to the status string, it changes the up/down arrows to either be inactive or active, which translates to either being of the 'active' class or not. Lastly it takes the current score of the object(the sum of all of its votes) and updates the part of the interface that displays the score. I decided on going with this method, as it ensures an updated value of the score; however, this also means that if a user votes on something at the same time as another user, one of them will see the score go up by two, which is not a desired outcome and might confuse people, so something to keep in mind. So that's that. The full process of adding social voting to your site.

**Note On Security: This demo is not exactly secure, because we can't verify that a request is coming from the user specified as the 'user_id'. So to improve this example, we could add a CSRF check or something to verify that it truly is the user voting on an object. That could be for another day.

December 03, 2011

Troubles With Postgresql on Mac OSX Lion

So I just spent much too long solving a problem with Postgres on Lion. I was getting an error like this:

psql: could not connect to server: Permission denied
Is the server running locally and accepting
connections on Unix domain socket "/var/pgsql_socket/.s.PGSQL.5432"?

The problem ended up being caused by the fact that Lion comes with a version of Postgres pre-installed so all of the major scripts like createdb, psql, and pg_ctl were all pointing to the executables in /usr/bin(where the pre-installed version was), as opposed to /usr/local/bin(where homebrew installed my postgres). I solved this by adding this line to my ~/.profile file:

export PATH=usr/local/bin:/usr/local/sbin:$PATH

After that all I had to do was use this command to initialize the database:

initdb /usr/local/var/postgres

One little quirk that I ran into, was this command actually starts the database daemon as well, so there is not need to run 'pg_ctl -D $DIR start'. You should be able to interact with the database with the current user after following the above two simple steps.

December 02, 2011

Helping Out the Dota 2 Community

So I felt bad about using up so much of playdota.com's bandwidth over the course of my last shenanigans, so I decided that I would help the community out a bit, as I really love the games that this group of people play. I recently got into the Dota 2 beta, and have been playing it pretty frequently. I was scanning the dev forums and came across this thread, where a number of people were sharing configurations for in-game hero guides. Towards the end, a few people were talking about creating a C# GUI to make it easier to create guides and generate the respective text files. While I was reading this, I was thinking to myself how stupid of an approach this was in this modern age. I mean think about it, this guy is going to create a gui of some kind, and then a hundred or so people might download. After that happens, how does he plan on adding new items/heroes as they are added into the game? What about bug fixes, how does he plan on pushing updates? This would be just as simple to create a web application for, and it would be a thousand times better, as I could add new items/heroes to a central database and push updates instantly. So I have decided that I am going to create such a "guide creator" web application that will meet the requirements laid out in that thread. I'm calling it D2. This will go along nicely with my idea to create a MOBA search engine of sorts, that will be able to provide a live search for all heroes/items/guides in the MOBA genre. This will provide me with a solid set of user-created guides to begin the search engine later. My plan is that I will get done with it this weekend, which is a little ambitious, but seeing as I am starting development on Project Ocelot soon, I don't have a lot of time. So I really plan on pushing myself this weekend to get this done.

December 02, 2011

Upboat This Post

So I am huge redditor. I use reddit as a news source, for entertainment, as a gaming community, and the list goes on. One of the biggest reddit claims to fame is their social voting system and the algorithms they use to sort their content. On reddit, you can pretty much vote on everything, and the site is able to very cleverly use all of this data to sort the content and decide upon which posts/comments/replies are going to be more relevant to the user, thus improving their overall experience with the web app. On a recent site that I made for the Reprap community(still undeployed and in a certain state of "site limbo"), I implemented a very primitive version of a reddit-like social voting system. I decided that I wanted to pull this functionality out, and create a demo/tutorial to demonstrate how I accomplished this. So the following is the aforementioned tutorial, which I plan on putting in the Pyramid cookbook once it is completed.

This tutorial will take you through all of the steps of creating a very simple reddit-like application using Pyramid. I assume that you have absolutely no experience with Pyramid, but at the same time builds a very usable real-world application and uses a number of conventions created by the Pyramid community, so noobs and advanced users are both welcome. I also ask that you actually type out all of the code samples given(even the comments, as a lot of information is hidden them), so that way by the end of the guide, you have a full working application. For the lazy, all of the source code will be located here. This tutorial is organized as follows:

  1. Setting Up Your Environment
  2. Writing the Base Site
  3. Upboat All the Things

Setting Up Your Environment

Most tutorials will use a scaffold to get something to display in a browser quickly and easily; however, I have chosen to just show you how to write all of the base files, as I like the idea that after you're done with this tutorial, you will know what each line of your application does(which is a very comfortable feeling). So first things first, let's talk about directory/file structure. As we go along, I am going to show you what the file structure should look like at every stage of the process. So that way you can follow along and go through each step in creating your app. First things first, let's setup your project directory and virtualenv. Your file structure will look like this after your done:

Upboat/
|-- env

Make a directory entitled 'Upboat' and cd into it. The next stage will use virtualenv to create a virtual python environment, that will allow you to keep your package management for this application separate from the rest of your system. I always like to install virtualenv on the system python. Use the following command:

jayd3e ~/Projects/Upboat $ easy_install virtualenv

Now that we have virtualenv, we need to compile the version of python we want to use. Pyramid is compatible with 2.5, 2.6, and 2.7, but I personally like to always use 2.7. In order to download and install 2.7, in a directory other than your project directory, use the following commands:

jayd3e ~/opt $ wget http://www.python.org/ftp/python/2.7/Python-2.7.tgz
jayd3e ~/opt $ tar xvzf Python-2.7.tgz
jayd3e ~/opt $ cd Python-2.7
jayd3e ~/opt $ ./configure
jayd3e ~/opt $ make; make install

Ok great now we have a python to use within our virtualenv. Finally to create the virtualenv, use the following command from with the root directory of your project:

jayd3e ~/Projects/Upboat $ virtualenv --no-site-packages --python=/path/to/Python-2.7/bin/python env

This tells virtualenv to create an environment in a folder called 'env' in the current directory, which uses the python that we compiled, but doesn't include any of the packages already installed in that python. So now the directory structure should look familiar, a root project directory with an virtualenv inside of it. Now let's activate this virtualenv by typing these commands:

jayd3e ~/Projects/Upboat $ cd env/bin
jayd3e ~/Projects/Upboat/env/bin $ . activate

On most systems, a period is an alias for 'source'. Your prompt should now look something like this:

(env) jayd3e ~/Projects/Upboat/env/bin $

This means that virtualenv has altered the system path in such a way, that if you now call 'python' you will be calling the python within your virtualenv, this goes the same for a variety of other executables, like 'easy_install' and 'pip'. You should have this virtualenv activated while doing the rest of the steps in this guide. So now let's add some more files into the mix.

Upboat/
|-- env
|-- upboat
|    |-- __init__.py
|-- README
|-- CHANGES
`-- setup.py

Easy enough. This is where any new application should begin, with a standard setuptools package. The README file, by convention, contains a description(detailed or not) of what the package does, and may also include instructions on how to install/use the package. It is helpful to know that both github and bitbucket use the README file in the root of a repository in order to display a description of the repo. This is what your README file should look like:

# Upboat/README
A simple reddit-like application that allows people to post links, and vote on them.

The CHANGES file contains a list of changes made between versions, and is usually the main source for your software's patch notes. We haven't written anything yet, so we don't really have anything to include in this file quite yet. The 'upboat' folder is the folder that is actually representative of your module. By convention it is usually your project name, in our case 'Upboat', written in all lowercase. It is also important to note, that the init.py file is what actually makes it a python module and accessible through 'import upboat.' We will also be putting all of our configuration for data Pyramid in the init.py file. Lastly, the setup.py file contains specific information about your application that will assist setuptools in installing the correct dependencies for your package and also in distributing your application. Let's make it look something like this:

# Upboat/setup.py
import os
from setuptools import setup

# locates the README and CHANGES file, and reads their contents into strings
here = os.path.abspath(os.path.dirname(__file__))
README = open(os.path.join(here, 'README')).read()
CHANGES = open(os.path.join(here, 'CHANGES')).read()

# specifies the entry points of our application
entry_points = """
      [paste.app_factory]
      main = upboat:main
      """

# specifies a list of required packages for your application
requires = ['pyramid',
                  'sqlalchemy',
                  'mako']

# the main function call to setuptools to define your package
setup(name='Upboat',
          version='0.1dev',
          description='',
          long_description=README + '\n\n' + CHANGES,
          install_requires=requires,
          url='http://localhost',
          packages=['upboat'],
          test_suite='upboat.tests',
          entry_points = entry_points
)

While your looking at setup.py, I would like to briefly talk about entry points. Entry points are pretty awesome and have a variety of different applications. The beauty of entry points is that they basically make other applications, that have no knowledge of your application, aware that you exist. Let me give you an example that directly relates to Pyramid. So I'm sure by now you have scoured Pyramid's docs, and you know what a Pyramid scaffold is. If you don't, a scaffold is essentially just a pre-built directory structure and some basic pre-written files that you can build off of to create your own application. Going on, you use the 'pcreate' command to locate the scaffold and copy all of the different files and directories within it, to the directory your new project is located in. The 'pcreate' command doesn't know where all of the potential scaffolds could be, because realistically, they could be anywhere. A user might want to create their own scaffold in fact, and put it into a custom directory. So how exactly does pcreate find all of the available scaffold throughout the entire system you may ask? Through entry points! What 'pcreate' basically does is it uses the 'pkg_resources' module to ask the current Python for all of the packages that have registered to a specific entry point, and then uses that list of scaffolds to find the one that you specify when you use 'pcreate'. It basically provides a really simple way to implement plugins at the package level. Now let's take a look at how your package uses entry points. As you can see in the entry points section of your setup.py, we are registering the 'main' function within the 'upboat' module to the 'paste.app_factory' entry point. This way, later when we go to serve our application, paster will be able to find the function that returns a wsgi app.

So now we are at the point where we have set up your Python "package" for the application. In fact, if you run:

jayd3e ~/opt $ make; make install

You should then be able to launch a python interpreter, and access your module by typing 'import upboat'. Obviously there is nothing in it, so you won't be able to do a whole lot, but you should still be able to access it. Moving right along, we now want to create the actual Pyramid elements of our application, now that we have a working module of our own. Here is what it will look like when we're done.

Upboat/
|-- README
|-- CHANGES
|-- development.ini
|-- production.ini
|-- upboat
|   |-- __init__.py
|   |-- static
|   |   |-- css
|   |       |-- reset.css
|   |       |-- style.css
|   |       `-- type.css
|   |   |-- img
|   |   `-- js
|   |-- templates
|   |   `-- index.mako
|   |-- views.py
|   |-- resources.py
|   `-- models.py
|-- env
`-- setup.py

Pyramid makes absolutely no assumptions about where each element of your code is, so it is entirely up to you on how to organize it. This may seem daunting at first, but there is a great amount of freedom that comes with this fact and allows you to make your app as large or as small as you want. So let's start creating all of these files. The development.ini file is a file specific to Paster, which is the web server we are going to be using. It is consumed by the 'paster serve' command to make sense of our wsgi application. Our development.ini is going to look like this:

**Note: I have decided that this tutorial is much too broad, and it would require me to rewrite a lot of Upboat's current code to act more like an actual website. I decided that most of the topics I was talking about have already been discuss to great lengths in the docs, so not only would I be adding very little value, I would only be making the process more confusing by adding another resource. I have decided to strictly focus on the task of implementing social voting in a site, and create a quick description of Upboat's source, as it would better serve the community.