فهرست منبع

Merge pull request #1531 from TechEmpower/python-turbogears

Python turbogears
Brittany Mazza 10 سال پیش
والد
کامیت
63ebd4c17a

+ 1 - 0
.travis.yml

@@ -127,6 +127,7 @@ env:
     - "TESTDIR=Python/flask"
     - "TESTDIR=Python/pyramid"
     - "TESTDIR=Python/tornado"
+    - "TESTDIR=Python/turbogears"
     - "TESTDIR=Python/uwsgi"
     - "TESTDIR=Python/web2py"
     - "TESTDIR=Python/wheezyweb"

+ 40 - 0
frameworks/Python/turbogears/README.md

@@ -0,0 +1,40 @@
+# TurboGears Benchmark Test 
+
+Single file test, [app.py](app.py)
+
+## Description
+
+TurboGears framework (http://turbogears.org)
+
+### Database
+
+MySQL
+
+### Server
+
+* Gunicorn + Meinheld
+
+## Test URLs
+### JSON Encoding
+
+http://localhost:8080/json
+
+### Plaintext
+
+http://localhost:8080/plaintext
+
+### DB
+
+http://localhost:8080/db
+
+### Query
+
+http://localhost:8080/queries?queries=2
+
+### Update
+
+http://localhost:8080/updates?queries=2
+
+### Fortune
+
+http://localhost:8080/fortune

+ 93 - 0
frameworks/Python/turbogears/app.py

@@ -0,0 +1,93 @@
+import os
+import sys
+import json
+from functools import partial
+from operator import attrgetter
+from random import randint
+
+import bleach
+
+from tg import expose, TGController, AppConfig
+
+from jinja2 import Environment, PackageLoader
+
+from sqlalchemy.orm import scoped_session, sessionmaker
+from sqlalchemy import create_engine
+
+from models.Fortune import Fortune
+from models.World import World
+
+DBDRIVER = 'mysql'
+DBHOSTNAME = os.environ.get('DBHOST', 'localhost')
+DATABASE_URI = '%s://benchmarkdbuser:benchmarkdbpass@%s:3306/hello_world?charset=utf8' % (DBDRIVER, DBHOSTNAME)
+
+db_engine = create_engine(DATABASE_URI)
+Session = sessionmaker(bind=db_engine)
+db_session = Session()
+
+env = Environment(loader=PackageLoader("app", "templates"))
+
+def getQueryNum(queryString):
+    try:
+        num_queries = int(queryString)
+        if num_queries < 1:
+            return 1
+        if num_queries > 500:
+            return 500
+        return num_queries
+    except ValueError:
+         return 1
+
+class RootController(TGController):
+
+    @expose(content_type="text/plain")
+    def plaintext(self):
+        return "Hello, World!"
+
+    @expose("json")
+    def json(self):
+        return {"message": "Hello, World!"}
+
+    @expose("json")
+    def db(self):
+        wid = randint(1, 10000)
+        world = db_session.query(World).get(wid).serialize()
+        return world
+
+    @expose("json")
+    def updates(self, queries=1):
+        num_queries = getQueryNum(queries)
+        worlds = []
+        rp = partial(randint, 1, 10000)
+        ids = [rp() for _ in xrange(num_queries)]
+        ids.sort()
+        for id in ids:
+            world = db_session.query(World).get(id)
+            world.randomNumber = rp()
+            worlds.append(world.serialize())
+        return json.dumps(worlds)
+
+    @expose("json")
+    def queries(self, queries=1):
+        num_queries = getQueryNum(queries)
+        rp = partial(randint, 1, 10000)
+        get = db_session.query(World).get
+        worlds = [get(rp()).serialize() for _ in xrange(num_queries)]
+        return json.dumps(worlds)
+
+
+    @expose()
+    def fortune(self):
+        fortunes = db_session.query(Fortune).all()
+        fortunes.append(Fortune(id=0, message="Additional fortune added at request time."))
+        fortunes.sort(key=attrgetter("message"))
+        for f in fortunes:
+            f.message = bleach.clean(f.message)
+            template = env.get_template("fortunes.html")
+        return template.render(fortunes=fortunes)
+
+config = AppConfig(minimal=True, root_controller=RootController())
+config.renderers.append("jinja")
+
+app = config.make_wsgi_app()
+

+ 27 - 0
frameworks/Python/turbogears/benchmark_config.json

@@ -0,0 +1,27 @@
+{
+  "framework": "turbogears",
+  "tests": [{
+    "default": {
+      "setup_file": "setup",
+      "json_url": "/json",
+      "db_url": "/db",
+      "query_url": "/queries?queries=",
+      "fortune_url": "/fortune",
+      "update_url": "/updates?queries=",
+      "plaintext_url": "/plaintext",
+      "port": 8080,
+      "approach": "Realistic",
+      "classification": "Micro",
+      "database": "MySQL",
+      "framework": "TurboGears",
+      "language": "Python",
+      "orm": "Full",
+      "platform": "Meinheld",
+      "webserver": "None",
+      "os": "Linux",
+      "database_os": "Linux",
+      "display_name": "TurboGears",
+      "notes": "CPython 2.7"
+    }
+  }]
+}

+ 25 - 0
frameworks/Python/turbogears/gunicorn_conf.py

@@ -0,0 +1,25 @@
+import multiprocessing
+import os
+import sys
+
+_is_pypy = hasattr(sys, 'pypy_version_info')
+_is_travis = os.environ.get('TRAVIS') == 'true'
+
+workers = multiprocessing.cpu_count() * 3
+if _is_travis:
+    workers = 2
+
+bind = "0.0.0.0:8080"
+keepalive = 120
+errorlog = '-'
+pidfile = 'gunicorn.pid'
+
+if _is_pypy:
+    worker_class = "tornado"
+else:
+    worker_class = "meinheld.gmeinheld.MeinheldWorker"
+
+    def post_fork(server, worker):
+        # Disalbe access log
+        import meinheld.server
+        meinheld.server.set_access_logger(None)

+ 19 - 0
frameworks/Python/turbogears/install.sh

@@ -0,0 +1,19 @@
+#!/bin/bash
+
+export PY2_ROOT=$IROOT/py2
+export PY2=$PY2_ROOT/bin/python
+export PY2_PIP=$PY2_ROOT/bin/pip
+
+export PY3_ROOT=$IROOT/py3
+export PY3=$PY3_ROOT/bin/python3
+export PY3_PIP=$PY3_ROOT/bin/pip3
+
+mkdir -p $IROOT/.pip_cache
+export PIP_DOWNLOAD_CACHE=$IROOT/.pip_cache
+
+fw_depends python2 python3
+
+$PY2_PIP install --install-option="--prefix=${PY2_ROOT}" -r $TROOT/requirements.txt
+
+$PY3_PIP install --install-option="--prefix=${PY3_ROOT}" -r $TROOT/requirements.txt
+

+ 17 - 0
frameworks/Python/turbogears/models/Fortune.py

@@ -0,0 +1,17 @@
+from sqlalchemy.ext.declarative import declarative_base
+from sqlalchemy import Column
+from sqlalchemy.types import String, Integer
+
+Base = declarative_base()
+
+class Fortune(Base):
+    __tablename__ = "fortune"
+
+    id = Column(Integer, primary_key = True)
+    message = Column(String)
+
+    def serialize(self):
+        return {
+            'id' : int(self.id),
+            'message' : self.message
+        }

+ 17 - 0
frameworks/Python/turbogears/models/World.py

@@ -0,0 +1,17 @@
+from sqlalchemy.ext.declarative import declarative_base
+from sqlalchemy import Column
+from sqlalchemy.types import String, Integer
+
+Base = declarative_base()
+
+class World(Base):
+    __tablename__ = "world"
+
+    id = Column(Integer, primary_key = True)
+    randomNumber = Column(Integer)
+
+    def serialize(self):
+        return {
+            'id' : int(self.id),
+            'randomNumber' : int(self.randomNumber)
+        }

+ 0 - 0
frameworks/Python/turbogears/models/__init__.py


+ 11 - 0
frameworks/Python/turbogears/requirements.txt

@@ -0,0 +1,11 @@
+tg.devtools==2.3.4
+
+bleach==1.4.1
+
+SQLAlchemy==0.9.9
+zope.sqlalchemy==0.7.6
+mysqlclient==1.3.6
+jinja2==2.7.3
+
+gunicorn==19.3.0
+meinheld==0.5.7

+ 7 - 0
frameworks/Python/turbogears/setup.sh

@@ -0,0 +1,7 @@
+#!/bin/bash
+
+export PY2_ROOT=$IROOT/py2
+export PY2=$PY2_ROOT/bin/python
+export PY2_GUNICORN=$PY2_ROOT/bin/gunicorn
+
+$PY2_GUNICORN app:app -c gunicorn_conf.py &

+ 20 - 0
frameworks/Python/turbogears/templates/fortunes.html

@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html>
+    <head>
+        <title>Fortunes</title>
+    </head>
+    <body>
+        <table>
+            <tr>
+                <th>id</th>
+                <th>message</th>
+            </tr>
+            {%for fortune in fortunes %}
+                <tr>
+                    <td>{{ fortune.id }}</td>
+                    <td>{{ fortune.message }}</td>
+                </tr>
+            {% endfor %}
+        </table>
+    </body>
+</html>