Skip to content

Commit

Permalink
[ADD] pybrake new framework support: Turbogears2
Browse files Browse the repository at this point in the history
  • Loading branch information
smurf-U committed Sep 27, 2022
1 parent 3341047 commit b4a8a8e
Show file tree
Hide file tree
Showing 37 changed files with 1,641 additions and 3 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,7 @@ frameworks.
* [Sanic](https://docs.airbrake.io/docs/platforms/framework/python/sanic)
* [Starlette](https://docs.airbrake.io//docs/platforms/framework/python/starlette)
* [Tornado](https://docs.airbrake.io//docs/platforms/framework/python/tornado)
* [Turbogears2](https://docs.airbrake.io//docs/platforms/framework/python/turbogears2)

## Development

Expand Down
104 changes: 104 additions & 0 deletions examples/turbogears/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
# Turbogears2 Sample Application for Pybrake

## About the application

The example application provides three GET endpoints:

1. `/date` - returns server date and time.
2. `/locations` - returns list of available locations.
3. `/weather/{locationName}` - returns the weather details for the locations.

## Setup for MinimalApplication

### Steps to run the API

1. Install the dependencies for the application

```bash
pip install -r requirements.txt
```

2. Go to `weather_minimal` directory

3. You must get both `project_id` & `project_key`.

Find your `project_id` and `project_key` in your Airbrake account and
replace them in the below code in your project's `main.py` file.
```python
config.update_blueprint({
'PYBRAKE': {
"project_id": 99999,
"project_key": "xxxxxxxxxxxxxxxxxxxxxxxxxxxx",
}
})
config = init_app(config)
```
4. Run the localhost server
```bash
python main.py
```
## Setup for FullStackApplication
1. Install the dependencies for the application
```bash
pip install -r requirements.txt
```
2. Go to `weather-fullstack` directory
3. You must get both `project_id` & `project_key`.
Find your `project_id` and `project_key` in your Airbrake account and
replace them in the below code in your project's
`weather_fullstack/config/app_cfg.py` file.

```python
base_config.update_blueprint({
'PYBRAKE': {
"project_id": 452110,
"project_key": "9ea9da01b33172fd10d60cbacdd223f9",
}
})
base_config = init_app(base_config)
```

4. Run the localhost server

```bash
python setup.py develop
gearbox setup-app
gearbox serve
```

## Test Applications

1. To retrieve the responses, append the endpoints to the localhost URL.

Use the below curl commands to interact with the endpoints.

```bash
curl "http://localhost:8000/date"
curl "http://localhost:8000/locations"
curl "http://localhost:8000/weather/<austin/pune/santabarbara>"
```

The below curl command will raise `404 Not Found` error.

```bash
curl -I "http://localhost:8000/weather"
```

The below curl command will raise `500 Internal Server Error`.

```bash
# Should produce an intentional HTTP 500 error and report the error to
# Airbrake (since `washington` is in the supported cities list but there
# is no data for `washington`, an `if` condition is bypassed and the
# `data` variable is used but not initialized)
curl -I "http://localhost:8000/weather/washington"
```
7 changes: 7 additions & 0 deletions examples/turbogears/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
backlash
kajiki
pybrake
requests
TurboGears2
sqlalchemy
tg.devtools
1 change: 1 addition & 0 deletions examples/turbogears/weather-fullstack/MANIFEST.in
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
recursive-include weather_fullstack/templates *
24 changes: 24 additions & 0 deletions examples/turbogears/weather-fullstack/README.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
This file is for you to describe the weather-fullstack application. Typically
you would include information such as the information below:

Installation and Setup
======================

Install ``weather-fullstack`` using the setup.py script::

$ cd weather-fullstack
$ python setup.py develop

Create the project database for any model classes defined::

$ gearbox setup-app

Start the paste http server::

$ gearbox serve

While developing you may want the server to reload after changes in package files (or its dependencies) are saved. This can be achieved easily by adding the --reload option::

$ gearbox serve --reload --debug

Then you are ready to go.
164 changes: 164 additions & 0 deletions examples/turbogears/weather-fullstack/development.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
#
# weather-fullstack - TurboGears 2 development environment configuration
#
# The %(here)s variable will be replaced with the parent directory of this file
#
# This file is for deployment specific config options -- other configuration
# that is always required for the app is done in the config directory,
# and generally should not be modified by end users.

[DEFAULT]
# WARNING: *THE LINE BELOW MUST BE FALSE ON A PRODUCTION ENVIRONMENT*
# Debug mode will enable the interactive debugging tool, allowing ANYONE to
# execute malicious code after an exception is raised.
debug = false

# ERROR REPORTING BY EMAIL
# Uncomment to enable email error reporting, you probably want this
# on production to receive application crashes by email
#trace_errors.error_email = [email protected]
trace_errors.from_address = turbogears@localhost
trace_errors.smtp_server = localhost

# Uncomment if email server requires authentication
#trace_errors.smtp_use_tls = true
#trace_errors.smtp_username = unknown
#trace_errors.smtp_password = unknown

# Uncomment to enable additional context data for email error reporting
#trace_errors.dump_request = true
#trace_errors.dump_local_frames = true

# ERROR REPORTING TO SENTRY
# Uncomment to enable reporting errors to a Sentry server
#trace_errors.sentry_dsn = http://public:[email protected]/1

# REPORT SLOW REQUESTS
#trace_slowreqs.enable = true
#trace_slowreqs.interval = 25
#trace_slowreqs.exclude = /tw2/resources

[server:main]
use = egg:gearbox#wsgiref
host = 127.0.0.1
port = 8000

[app:main]
use = egg:weather-fullstack

# Default application language, when available this will be
# used when none of the browser requested languages is available.
#i18n.lang = en

cache_dir = %(here)s/data
session.key = weather_fullstack
session.secret = f9a6a628-ef0c-4a85-aa73-62a449e669f9

#By default session is store in cookies to avoid the overhead
#of having to manage a session storage. On production you might
#want to switch to a better session storage.
session.type = cookie
session.validate_key = f9a6a628-ef0c-4a85-aa73-62a449e669f9

# If you'd like to fine-tune the individual locations of the cache data dirs
# un-comment the desired settings here:
#cache.data_dir = %(here)s/data/cache

# Disable template autoreload to boost performances in production
# WARNING: if you want to deploy your application using a zipped egg
# (ie: if your application's setup.py defines zip-safe=True, then you
# MUST put "false" for the production environment because there will
# be no disk and real files to compare time with.
#auto_reload_templates = false

# Turn off static files serving from public/ directory
# this can be a speed boost if you have a proxy server already
# serving them for you.
#serve_static = false

#turn this setting to "min" if you would like tw to produce minified
#javascript files (if your library supports that)
toscawidgets.framework.resource_variant=debug

# pick the form for your database
# %(here) may include a ':' character on Windows environments; this can
# invalidate the URI when specifying a SQLite db via path name
# sqlalchemy.url=postgres://username:password@hostname:port/databasename
# sqlalchemy.url=mysql://username:password@hostname:port/databasename


# If you have sqlite, here's a simple default to get you started
# in development

sqlalchemy.url = sqlite:///%(here)s/devdata.db
#echo shouldn't be used together with the logging module.
sqlalchemy.echo = false
sqlalchemy.echo_pool = false
sqlalchemy.pool_recycle = 3600

# This line ensures that Genshi will render xhtml when sending the
# output. Change to html or xml, as desired.
templating.genshi.method = xhtml
templating.genshi.doctype = html5

# This might be required to make Genshi work on Python3.4
#templating.genshi.name_constant_patch = true

# the compiled template dir is a directory that must be readable and writable
# by your webserver. It will be used to store the resulting templates once
# compiled by the TemplateLookup system.
# During development you generally don't need this option since paste's HTTP
# server will have access to you development directories, but in production
# you'll most certainly want to have apache or nginx to write in a directory
# that does not contain any source code in any form for obvious security
# reasons. If disabled, None, False, or not writable, it will fall back
# to an in-memory cache.
templating.mako.compiled_templates_dir = %(here)s/data/templates

# Logging configuration
# Add additional loggers, handlers, formatters here
# Uses python's logging config file format
# http://docs.python.org/lib/logging-config-fileformat.html
[loggers]
keys = root, weather_fullstack, sqlalchemy, auth

[handlers]
keys = console

[formatters]
keys = generic

# If you create additional loggers, add them as a key to [loggers]
[logger_root]
level = INFO
handlers = console

[logger_weather_fullstack]
level = DEBUG
handlers =
qualname = weather_fullstack
[logger_sqlalchemy]
level = WARN
handlers =
qualname = sqlalchemy.engine
# "level = INFO" logs SQL queries.
# "level = DEBUG" logs SQL queries and results.
# "level = WARN" logs neither. (Recommended for production systems.)
# A logger for authentication, identification and authorization
# this is repoze.who:
[logger_auth]
level = WARN
handlers =
qualname = auth

# If you create additional handlers, add them as a key to [handlers]
[handler_console]
class = StreamHandler
args = (sys.stderr,)
level = NOTSET
formatter = generic

# If you create additional formatters, add them as a key to [formatters]
[formatter_generic]
format = %(asctime)s,%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
datefmt = %H:%M:%S
76 changes: 76 additions & 0 deletions examples/turbogears/weather-fullstack/migration/env.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
from __future__ import with_statement
from alembic import context
from sqlalchemy import engine_from_config, pool

# this is the Alembic Config object, which provides
# access to the values within the .ini file in use.
config = context.config

# Interpret the config file for Python logging.
# This line sets up loggers basically.
# from logging.config import fileConfig
# fileConfig(config.config_file_name)

# add your model's MetaData object here
# for 'autogenerate' support
# from myapp import mymodel
# target_metadata = mymodel.Base.metadata
from weather_fullstack import model
target_metadata = model.metadata

# other values from the config, defined by the needs of env.py,
# can be acquired:
# my_important_option = config.get_main_option("my_important_option")
# ... etc.


def run_migrations_offline():
"""Run migrations in 'offline' mode.
This configures the context with just a URL
and not an Engine, though an Engine is acceptable
here as well. By skipping the Engine creation
we don't even need a DBAPI to be available.
Calls to context.execute() here emit the given string to the
script output.
"""
url = config.get_main_option("sqlalchemy.url")
context.configure(url=url, version_table='migrate_version')

with context.begin_transaction():
context.run_migrations()


def run_migrations_online():
"""Run migrations in 'online' mode.
In this scenario we need to create an Engine
and associate a connection with the context.
"""
engine = engine_from_config(
config.get_section(config.config_ini_section),
prefix='sqlalchemy.',
poolclass=pool.NullPool
)

connection = engine.connect()
context.configure(
connection=connection,
target_metadata=target_metadata,
version_table='migrate_version'
)

try:
with context.begin_transaction():
context.run_migrations()
finally:
connection.close()


if context.is_offline_mode():
run_migrations_offline()
else:
run_migrations_online()
Loading

0 comments on commit b4a8a8e

Please sign in to comment.