Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 60ca950
Showing
38 changed files
with
1,732 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
# temp files | ||
**pyc | ||
**pyo | ||
|
||
# swap files | ||
**swp | ||
**~ | ||
|
||
# build directory (setup.py) | ||
build/ | ||
dist/ | ||
**pyscale.egg-info/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
include README.rst | ||
graft pyscale/files |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
General purpose Python framework for writing highly scalable applications. | ||
|
||
About | ||
--------------------------------------------------- | ||
A typical application consists of several modules. Each module has its own | ||
process, stores a pidfile in 'tmp/pids', and has a logfile in 'logs'. | ||
|
||
A RPC protocol is implemented on top of zeromq in order to allow for | ||
inter-module communication. Modules have an auto-adjustable number of workers | ||
in order to cope with a high number of requests. These rpc requests will block | ||
until that module becomes available. | ||
Read more about zeromq at http://zguide.zeromq.org/ | ||
|
||
Each module consists of several gevent greenlets. A basic module will already | ||
contain a few greenlets that handle incoming rpc requests. You can spawn | ||
additional greenlets for your own needs. | ||
Read more about gevent at http://www.gevent.org/ | ||
|
||
|
||
Tasks | ||
--------------------------------------------------- | ||
You can manage and debug your modules using built-in tasks. Type 'cake' at a | ||
bash prompt when inside your project to see available tasks and what they do. | ||
You can also define your own taks. | ||
|
||
Commands | ||
--------------------------------------------------- | ||
To create a new project: | ||
|
||
:: | ||
|
||
$ pyscale new <name> | ||
|
||
To generate a new module: | ||
|
||
:: | ||
|
||
$ pyscale generate <name> | ||
|
||
To start, stop, debug, view logs and more check out available cake tasks: | ||
|
||
:: | ||
|
||
$ cake | ||
$ cake start | ||
$ cake stop | ||
$ cake status | ||
$ cake log | ||
$ cake console | ||
|
||
Usage | ||
--------------------------------------------------- | ||
To execute an rpc request on another module: | ||
|
||
:: | ||
|
||
self.sock('modname').method(*args, **kwargs) | ||
|
||
You can also use properties, and chain requests: | ||
|
||
:: | ||
|
||
self.sock('modname').prop.method() | ||
|
||
You can also issue requests on all available modules: | ||
|
||
:: | ||
|
||
self.multisock('*').method() | ||
|
||
|
||
To spawn another gevent greenlet in a current module: | ||
|
||
:: | ||
|
||
self.jobs.spawn(func) | ||
|
||
To debug your application use logs and the console. | ||
|
||
Requirements | ||
--------------------------------------------------- | ||
System Dependencies: | ||
* zeromq | ||
* atd | ||
|
||
Python Dependencies: | ||
* pyzmq | ||
* gevent | ||
* gevent_zeromq | ||
* cake | ||
* nose |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
#! /usr/bin/env python2.6 | ||
# -*- coding: utf-8 -*- | ||
|
||
import sys | ||
|
||
from cake.color import puts, fore | ||
from pyscale.lib import PyscaleError | ||
from pyscale.tools.generators import new, generate | ||
|
||
|
||
# main | ||
if __name__ == '__main__': | ||
command, arg = sys.argv[1:] | ||
|
||
try: | ||
if command in ['new', 'n']: | ||
new(arg) | ||
elif command in ['generate', 'g']: | ||
generate(arg) | ||
except PyscaleError as ex: | ||
puts(fore.red(ex)) |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
#! /usr/bin/env python2.6 | ||
# -*- coding: utf-8 -*- | ||
|
||
import logging | ||
|
||
from lib.module import Module | ||
|
||
|
||
# Module | ||
class {{module}}(Module): | ||
pass | ||
|
||
|
||
# main | ||
if __name__ == '__main__': | ||
{{module}}().run() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
#! /usr/bin/env python2.6 | ||
# -*- coding: utf-8 -*- | ||
|
||
from pyscale.tools.tasks import * |
Empty file.
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
#! /usr/bin/env python2.6 | ||
# -*- coding: utf-8 -*- | ||
|
||
import os | ||
import os.path as osp | ||
import logging | ||
|
||
class Configuration(object): | ||
def __init__(self, env='development'): | ||
self.env = os.environ.get('APP_ENV') or env | ||
self.root = osp.abspath('.') | ||
|
||
@property | ||
def log_level(self): | ||
if self.env == 'production': | ||
return logging.WARNING | ||
else: | ||
return logging.DEBUG |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
#! /usr/bin/env python2.6 | ||
# -*- coding: utf-8 -*- | ||
|
||
from pyscale.lib.module import BaseModule | ||
|
||
|
||
class Module(BaseModule): | ||
""" Module Class (daemon) """ | ||
|
||
# notifications | ||
def notice(self, msg): | ||
pass | ||
|
||
def alert(self, msg): | ||
pass | ||
|
||
def error(self, msg): | ||
pass |
Empty file.
Empty file.
Empty file.
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
#! /usr/bin/env python2.6 | ||
# -*- coding: utf-8 -*- | ||
|
||
import sys | ||
|
||
from pyscale.tools.console import main | ||
from pyscale.tools.console import api as _api | ||
from pyscale.tools.console import reinit as _reinit | ||
|
||
|
||
self = sys.modules[__name__] | ||
self.sockets = [] | ||
|
||
|
||
def api(modules=None): | ||
if modules == None: | ||
modules = self.all | ||
|
||
_api(modules) | ||
|
||
def reinit(info=True): | ||
_reinit(self, info) | ||
|
||
|
||
main(self) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
#! /usr/bin/env python2.6 | ||
# -*- coding: utf-8 -*- | ||
|
||
from pyscale.tools.logger import main | ||
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
#! /usr/bin/env python2.6 | ||
# -*- coding: utf-8 -*- | ||
|
||
from .decorators import * | ||
from .errors import * |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
#! /usr/bin/env python2.6 | ||
# -*- coding: utf-8 -*- | ||
|
||
def api(method): | ||
""" Basic decorator for module API methods """ | ||
method.api = True | ||
return method |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
#! /usr/bin/env python2.6 | ||
# -*- coding: utf-8 -*- | ||
|
||
|
||
class PyscaleError(Exception): | ||
def __init__(self, msg): | ||
self.msg = msg | ||
|
||
def __str__(self): | ||
return self.msg | ||
|
||
|
||
class ReqError(Exception): | ||
def __init__(self, msg): | ||
self.msg = msg | ||
|
||
def __getattr__(self, key): | ||
return self | ||
|
||
def __setattr__(self, key, name): | ||
if key == 'msg': | ||
return super(ReqError, self).__setattr__(key, name) | ||
return self | ||
|
||
def __delattr__(self, key): | ||
if key == 'msg': | ||
return super(ReqError, self).__delattr__(key, name) | ||
return self | ||
|
||
def __call__(self, *args, **kwargs): | ||
return self | ||
|
||
def __str__(self): | ||
return '(error: %s)' % self.msg | ||
|
||
def __repr__(self): | ||
return str(self) | ||
|
||
def __nonzero__(self): | ||
return False |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
#! /usr/bin/env python2.6 | ||
# -*- coding: utf-8 -*- | ||
|
||
import sys | ||
import logging | ||
import logging.handlers | ||
import traceback | ||
|
||
|
||
class MyFormatter(logging.Formatter): | ||
def format(self, record): | ||
record.fname = "[%s:%s]" % (record.filename, record.lineno) | ||
return logging.Formatter.format(self, record) | ||
|
||
|
||
EXCEPTION_PREFIX = ' => ' | ||
|
||
def log_exception(msg=None): | ||
""" Custom exception log helper """ | ||
if msg is None: | ||
msg = traceback.format_exc() | ||
|
||
lines = msg.split('\n') | ||
lines = [ '%s%s' % (EXCEPTION_PREFIX, line) for line in lines if line] | ||
msg = '\n' + '\n'.join(lines) + '\n' | ||
|
||
logging.log(75, '\n%s' % msg) | ||
|
||
def log_status(msg): | ||
""" Always log regardless of level """ | ||
logging.log(100, msg) | ||
|
||
|
||
def config_logger(stream=sys.stdout, level=logging.DEBUG): | ||
logger = logging.getLogger() | ||
logger.setLevel(level) | ||
|
||
|
||
# handler | ||
if stream in [sys.stdout, sys.stderr]: | ||
handler = logging.StreamHandler(stream) | ||
else: | ||
handler = logging.handlers.RotatingFileHandler(stream, maxBytes=409600, backupCount=3) | ||
logger.addHandler(handler) | ||
|
||
# formatter | ||
formatter = MyFormatter( | ||
fmt = '%(asctime)s %(levelname)-8s %(fname)-20s %(message)s', | ||
datefmt = '%b %d %Y %H:%M:%S', | ||
) | ||
handler.setFormatter(formatter) | ||
|
||
# custom levels | ||
logging.addLevelName(75, 'EXCEPT') | ||
logging.exception = log_exception | ||
|
||
logging.addLevelName(100, 'STATUS') | ||
logging.status = log_status | ||
|
||
|
||
# test | ||
if __name__ == '__main__': | ||
config_logger() | ||
|
||
logging.warning('test') | ||
logging.info('test') | ||
logging.debug('test') | ||
logging.error('test') | ||
|
||
try: err_var | ||
except Exception as ex: | ||
logging.exception() | ||
|
||
logging.status('test') |
Oops, something went wrong.