``, escaping and extra stuff
62 | ``
63 | def test():
64 | return "this is Python code"
65 | ``:python
66 |
67 | """
68 |
69 | class WikiPanel(wx.Panel):
70 |
71 | def __init__(self, parent):
72 | wx.Panel.__init__(self, parent)
73 |
74 | sizer = wx.BoxSizer(wx.VERTICAL)
75 | self.SetSizer(sizer)
76 |
77 | bookstyle = fnb.FNB_NODRAG | fnb.FNB_SMART_TABS
78 | self.book = fnb.FlatNotebook(self, wx.ID_ANY, agwStyle=bookstyle)
79 |
80 | sizer.Add(self.book,1, wx.ALL | wx.EXPAND)
81 |
82 | # Add some pages to the second notebook
83 |
84 | self.text = wx.TextCtrl(self.book, -1, SAMPLE_WIKI_TEXT, style=wx.TE_MULTILINE)
85 | self.book.AddPage(self.text, "Edition")
86 |
87 | self.html = wx.html.HtmlWindow(self, -1, wx.DefaultPosition, wx.Size(400, 300))
88 | if "gtk2" in wx.PlatformInfo:
89 | self.html.SetStandardFonts()
90 | self.book.AddPage(self.html, "Preview")
91 |
92 | sizer.Layout()
93 | self.SendSizeEvent()
94 |
95 | self.Bind(fnb.EVT_FLATNOTEBOOK_PAGE_CHANGING, self.OnPageChanging)
96 | self.Bind(fnb.EVT_FLATNOTEBOOK_PAGE_CHANGED, self.OnPageChanged)
97 |
98 | #self.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown)
99 |
100 | def OnPageChanging(self, event):
101 | page = event.GetOldSelection()
102 | if page==0:
103 | # save current cursor position
104 | self.sel = self.text.GetSelection()
105 | if page==1:
106 | # restore previous selection (really needed?)
107 | self.text.SetSelection(*self.sel)
108 | event.Skip()
109 |
110 | def OnPageChanged(self, event):
111 | page = event.GetSelection()
112 | if page==0:
113 | wx.CallAfter(self.text.SetFocus)
114 | if page==1:
115 | self.html.SetPage(render(self.text.GetValue()))
116 | event.Skip()
117 |
118 |
119 | class SimpleWiki(wx.Frame):
120 |
121 | def __init__(self):
122 | wx.Frame.__init__(self, None)
123 |
124 | self.panel = WikiPanel(self)
125 | self.Show()
126 |
127 | if __name__ == '__main__':
128 | app = wx.App()
129 | browser = SimpleWiki()
130 | #browser.panel.Open(url)
131 | app.MainLoop()
132 |
133 |
134 |
135 |
136 |
--------------------------------------------------------------------------------
/psp2py/ABOUT:
--------------------------------------------------------------------------------
1 | Write something about this app.
2 | Developed with web2py.
--------------------------------------------------------------------------------
/psp2py/LICENSE:
--------------------------------------------------------------------------------
1 | The web2py welcome app is licensed under public domain
2 | (except for the css and js files that it includes, which have their own third party licenses).
3 |
4 | You can modify this license when you add your own code.
5 |
--------------------------------------------------------------------------------
/psp2py/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/reingart/rad2py/e4802ade132d569225e8be7eca830d2f888aa5f9/psp2py/__init__.py
--------------------------------------------------------------------------------
/psp2py/controllers/default.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # this file is released under public domain and you can use without limitations
3 |
4 | #########################################################################
5 | ## This is a samples controller
6 | ## - index is the default action of any application
7 | ## - user is required for authentication and authorization
8 | ## - download is for downloading files uploaded in the db (does streaming)
9 | ## - call exposes all registered services (none by default)
10 | #########################################################################
11 |
12 | def index():
13 | """
14 | example action using the internationalization operator T and flash
15 | rendered by views/default/index.html or views/generic.html
16 | """
17 | return dict(message=T('Hello World'))
18 |
19 | def user():
20 | """
21 | exposes:
22 | http://..../[app]/default/user/login
23 | http://..../[app]/default/user/logout
24 | http://..../[app]/default/user/register
25 | http://..../[app]/default/user/profile
26 | http://..../[app]/default/user/retrieve_password
27 | http://..../[app]/default/user/change_password
28 | use @auth.requires_login()
29 | @auth.requires_membership('group name')
30 | @auth.requires_permission('read','table name',record_id)
31 | to decorate functions that need access control
32 | """
33 | return dict(form=auth())
34 |
35 |
36 | def download():
37 | """
38 | allows downloading of uploaded files
39 | http://..../[app]/default/download/[filename]
40 | """
41 | return response.download(request,db)
42 |
43 |
44 | def call():
45 | """
46 | exposes services. for example:
47 | http://..../[app]/default/call/jsonrpc
48 | decorate with @services.jsonrpc the functions to expose
49 | supports xml, json, xmlrpc, jsonrpc, amfrpc, rss, csv
50 | """
51 | return service()
52 |
53 |
54 | @auth.requires_signature()
55 | def data():
56 | """
57 | http://..../[app]/default/data/tables
58 | http://..../[app]/default/data/create/[table]
59 | http://..../[app]/default/data/read/[table]/[id]
60 | http://..../[app]/default/data/update/[table]/[id]
61 | http://..../[app]/default/data/delete/[table]/[id[
62 | http://..../[app]/default/data/select/[table]
63 | http://..../[app]/default/data/search/[table]
64 | but URLs bust be signed, i.e. linked with
65 | A('table',_href=URL('data/tables',user_signature=True))
66 | or with the signed load operator
67 | LOAD('default','data.load',args='tables',ajax=True,user_signature=True)
68 | """
69 | return dict(form=crud())
70 |
--------------------------------------------------------------------------------
/psp2py/controllers/projects.py:
--------------------------------------------------------------------------------
1 | # coding: utf8
2 | # try something like
3 |
4 | def index():
5 | return dict(form=crud.select(db.psp_project, linkto='show'))
6 |
7 | def search():
8 | form, table=crud.search(db.psp_project, linkto='edit')
9 | return dict(form=form, table=table)
10 |
11 | def create():
12 | return dict(form=crud.create(db.psp_project))
13 |
14 | def show():
15 | project_id = request.args[1]
16 | project = db(db.psp_project.id==project_id).select().first()
17 | times = db(db.psp_time_summary.project_id==project_id).select(
18 | db.psp_time_summary.phase,
19 | db.psp_time_summary.plan,
20 | db.psp_time_summary.actual,
21 | db.psp_time_summary.interruption,
22 | db.psp_time_summary.off_task)
23 | times = times.sort(lambda x: PSP_PHASES.index(x.phase))
24 | defects = db(db.psp_defect.project_id==project_id).select(
25 | db.psp_defect.number,
26 | db.psp_defect.summary,
27 | db.psp_defect.type,
28 | db.psp_defect.inject_phase,
29 | db.psp_defect.remove_phase,
30 | db.psp_defect.fix_time,
31 | db.psp_defect.fix_defect,
32 | orderby=db.psp_defect.number,
33 | )
34 | form = crud.read(db.psp_project, project_id)
35 | return dict(project=project, form=form, times=times, defects=defects)
36 |
37 | def edit():
38 | return dict(form=crud.update(db.psp_project, request.args[1]))
39 |
--------------------------------------------------------------------------------
/psp2py/controllers/services.py:
--------------------------------------------------------------------------------
1 | # coding: utf8
2 | # try something like
3 |
4 | from gluon.tools import Service
5 | service = Service(globals())
6 |
7 | def call():
8 | session.forget()
9 | return service()
10 |
11 | response.generic_patterns = ['*.json', '*.html']
12 |
13 | def get_project_id(project_name):
14 | "Find the project and create a new one if it doesn't exists"
15 | project = db(db.psp_project.name==project_name).select().first()
16 | if project:
17 | project_id = project.project_id
18 | else:
19 | project_id = db.psp_project.insert(name=project_name)
20 | return project_id
21 |
22 | @service.jsonrpc
23 | def get_projects():
24 | projects = db(db.psp_project.project_id>0).select()
25 | return [project.name for project in projects]
26 |
27 | @service.jsonrpc
28 | def save_project(project_name, defects, time_summaries, comments):
29 | project_id = get_project_id(project_name)
30 |
31 | # clean and store defects:
32 | db(db.psp_defect.project_id==project_id).delete()
33 | for defect in defects:
34 | defect['project_id'] = project_id
35 | defect.pop("id", None)
36 | defect.pop("defect_id", None)
37 | # JSON seems adding time ("2014-11-12 00:00:00"), remove it
38 | if ' ' in defect['date']:
39 | defect['date'] = defect['date'].split(' ')[0]
40 | db.psp_defect.insert(**defect)
41 |
42 | # clean and store time summaries:
43 | db(db.psp_time_summary.project_id==project_id).delete()
44 | for time_summary in time_summaries:
45 | time_summary['project_id'] = project_id
46 | if 'id' in time_summary:
47 | del time_summary['id']
48 | db.psp_time_summary.insert(**time_summary)
49 |
50 | # clean and store comments:
51 | db(db.psp_comment.project_id==project_id).delete()
52 | for comment in comments:
53 | comment['project_id'] = project_id
54 | if 'id' in comment:
55 | del comment['id']
56 | db.psp_comment.insert(**comment)
57 |
58 | return True
59 |
60 | @service.jsonrpc
61 | def load_project(project_name):
62 | project_id = get_project_id(project_name)
63 | defects = db(db.psp_defect.project_id==project_id).select()
64 | time_summaries = db(db.psp_time_summary.project_id==project_id).select()
65 | comments = db(db.psp_comment.project_id==project_id).select()
66 | return defects, time_summaries, comments
67 |
68 |
69 | @service.jsonrpc
70 | def update_project(project_name, actual_loc, reuse_library_entries):
71 | "Update counted LOC and reuse library entries (postmortem)"
72 |
73 | project_id = get_project_id(project_name)
74 |
75 | # update total loc counted:
76 | if project:
77 | db(db.psp_project.project_id==project_id).update(actual_loc=actual_loc)
78 |
79 | # clean and store reuse library entries:
80 | if project:
81 | db(db.psp_reuse_library.project_id==project_id).delete()
82 | for entry in reuse_library_entries:
83 | entry['project_id'] = project_id
84 | db.psp_reuse_library.insert(**entry)
85 |
86 | return True
87 |
--------------------------------------------------------------------------------
/psp2py/controllers/tests.py:
--------------------------------------------------------------------------------
1 | # coding: utf8
2 |
3 | from statistics import calc_correlation, calc_significance, calc_linear_regression, calc_student_t_probability
4 |
5 | # test TABLE A12 [HUMPHREY95] p.514
6 | x_values = [186, 699, 132, 272, 291, 331, 199, 1890, 788, 1601]
7 | y_values = [15.0, 69.9, 6.5, 22.4, 28.4, 65.9, 19.4,198.7, 38.8, 138.2]
8 |
9 | def correlation():
10 | r = calc_correlation(x_values, y_values)
11 | return {'r2': r**2, 'ok': round(r**2, 4)==0.9107}
12 |
13 | def linear_regression():
14 | b0, b1 = calc_linear_regression(x_values, y_values)
15 | return {'b0': b0, 'b1': b1, 'ok': round(b0,3)==-0.351 and round(b1,3)==0.095}
16 |
17 | def significance():
18 | # [HUMPHREY95] p.515
19 | t, r2, n = calc_significance(x_values, y_values)
20 | p = calc_student_t_probability(t, n-1)
21 | return {'loc': x_values, 'hours': y_values, 'n': n, 'r2': r2, 't': t, 'ok': round(t, 4)==9.0335, 'p': p}
22 |
--------------------------------------------------------------------------------
/psp2py/controllers/webservices.py:
--------------------------------------------------------------------------------
1 | from gluon.admin import *
2 | from gluon.fileutils import abspath, read_file, write_file
3 | from gluon.tools import Service
4 | from glob import glob
5 | import shutil
6 | import platform
7 | import time
8 | import base64
9 |
10 |
11 | service = Service(globals())
12 |
13 | def requires_admin(action):
14 | "decorator that prevents access to action if not admin password"
15 |
16 | def f(*a, **b):
17 |
18 | basic = request.env.http_authorization
19 | if not basic or not basic[:6].lower() == 'basic ':
20 | raise HTTP(401,"Wrong credentials")
21 | (username, password) = base64.b64decode(basic[6:]).split(':')
22 | if not verify_password(password) or not is_manager():
23 | time.sleep(10)
24 | raise HTTP(403,"Not authorized")
25 | return action(*a, **b)
26 |
27 | f.__doc__ = action.__doc__
28 | f.__name__ = action.__name__
29 | f.__dict__.update(action.__dict__)
30 | return f
31 |
32 |
33 |
34 | @service.jsonrpc
35 | @requires_admin
36 | def login():
37 | "dummy function to test credentials"
38 | return True
39 |
40 |
41 | @service.jsonrpc
42 | @requires_admin
43 | def list_apps():
44 | "list installed applications"
45 | regex = re.compile('^\w+$')
46 | apps = [f for f in os.listdir(apath(r=request)) if regex.match(f)]
47 | return apps
48 |
49 |
50 | @service.jsonrpc
51 | @requires_admin
52 | def list_apps():
53 | "list installed applications"
54 | regex = re.compile('^\w+$')
55 | apps = [f for f in os.listdir(apath(r=request)) if regex.match(f)]
56 | return apps
57 |
58 | @service.jsonrpc
59 | @requires_admin
60 | def list_files(app):
61 | files = listdir(apath('%s/' % app, r=request), '.*\.py$')
62 | return [x.replace('\\','/') for x in files]
63 |
64 | @service.jsonrpc
65 | @requires_admin
66 | def read_file(filename):
67 | """ Visualize object code """
68 | f = open(apath(filename, r=request), "rb")
69 | try:
70 | data = f.read().replace('\r','')
71 | finally:
72 | f.close()
73 | return data
74 |
75 | @service.jsonrpc
76 | @requires_admin
77 | def write_file(filename, data):
78 | f = open(apath(filename, r=request), "wb")
79 | try:
80 | f.write(data.replace('\r\n', '\n').strip() + '\n')
81 | finally:
82 | f.close()
83 |
84 |
85 | def call():
86 | session.forget()
87 | return service()
88 |
89 |
--------------------------------------------------------------------------------
/psp2py/controllers/wiki.py:
--------------------------------------------------------------------------------
1 | # coding: utf8
2 |
3 | # simple wiki functionalities
4 |
5 | def index():
6 | "List all pages"
7 | rows = db(db.wiki.id>0).select(db.wiki.page, db.wiki.title)
8 | return dict(rows=rows)
9 |
10 | def view():
11 | "Show a page"
12 | if not request.args:
13 | page = 'index'
14 | else:
15 | page = '/'.join(request.args)
16 |
17 | rows = db(db.wiki.page==page).select()
18 |
19 | if rows:
20 | text = MARKMIN(rows[0].text)
21 | title = rows[0].title
22 | else:
23 | text = T('page not found!')
24 | title = page
25 |
26 | return dict(text=text, title=title)
27 |
28 | def load():
29 | "Show basic html view for GUI IDE"
30 | return view()
31 |
32 | def edit():
33 | "Edit/Create a page"
34 | if request.args:
35 | page = '/'.join(request.args)
36 | rows = db(db.wiki.page==page).select()
37 | else:
38 | rows = None
39 | page = ""
40 |
41 | if rows:
42 | form = SQLFORM(db.wiki, rows[0])
43 | else:
44 | form = SQLFORM(db.wiki)
45 | form.vars.page = page
46 |
47 | if form.accepts(request.vars, session):
48 | session.flash = "Page updated!"
49 | redirect(URL("view", args=request.args))
50 |
51 | return dict(form=form)
52 |
--------------------------------------------------------------------------------
/psp2py/cron/crontab:
--------------------------------------------------------------------------------
1 | #crontab
--------------------------------------------------------------------------------
/psp2py/languages/hu-hu.py:
--------------------------------------------------------------------------------
1 | # coding: utf8
2 | {
3 | '"update" is an optional expression like "field1=\'newvalue\'". You cannot update or delete the results of a JOIN': '"update" is an optional expression like "field1=\'newvalue\'". You cannot update or delete the results of a JOIN',
4 | '%Y-%m-%d': '%Y.%m.%d.',
5 | '%Y-%m-%d %H:%M:%S': '%Y.%m.%d. %H:%M:%S',
6 | '%s rows deleted': '%s sorok t\xc3\xb6rl\xc5\x91dtek',
7 | '%s rows updated': '%s sorok friss\xc3\xadt\xc5\x91dtek',
8 | 'Available databases and tables': 'El\xc3\xa9rhet\xc5\x91 adatb\xc3\xa1zisok \xc3\xa9s t\xc3\xa1bl\xc3\xa1k',
9 | 'Cannot be empty': 'Nem lehet \xc3\xbcres',
10 | 'Check to delete': 'T\xc3\xb6rl\xc3\xa9shez v\xc3\xa1laszd ki',
11 | 'Client IP': 'Client IP',
12 | 'Controller': 'Controller',
13 | 'Copyright': 'Copyright',
14 | 'Current request': 'Jelenlegi lek\xc3\xa9rdez\xc3\xa9s',
15 | 'Current response': 'Jelenlegi v\xc3\xa1lasz',
16 | 'Current session': 'Jelenlegi folyamat',
17 | 'DB Model': 'DB Model',
18 | 'Database': 'Adatb\xc3\xa1zis',
19 | 'Delete:': 'T\xc3\xb6r\xc3\xb6l:',
20 | 'Description': 'Description',
21 | 'E-mail': 'E-mail',
22 | 'Edit': 'Szerkeszt',
23 | 'Edit This App': 'Alkalmaz\xc3\xa1st szerkeszt',
24 | 'Edit current record': 'Aktu\xc3\xa1lis bejegyz\xc3\xa9s szerkeszt\xc3\xa9se',
25 | 'First name': 'First name',
26 | 'Group ID': 'Group ID',
27 | 'Hello World': 'Hello Vil\xc3\xa1g',
28 | 'Import/Export': 'Import/Export',
29 | 'Index': 'Index',
30 | 'Internal State': 'Internal State',
31 | 'Invalid Query': 'Hib\xc3\xa1s lek\xc3\xa9rdez\xc3\xa9s',
32 | 'Invalid email': 'Invalid email',
33 | 'Last name': 'Last name',
34 | 'Layout': 'Szerkezet',
35 | 'Main Menu': 'F\xc5\x91men\xc3\xbc',
36 | 'Menu Model': 'Men\xc3\xbc model',
37 | 'Name': 'Name',
38 | 'New Record': '\xc3\x9aj bejegyz\xc3\xa9s',
39 | 'No databases in this application': 'Nincs adatb\xc3\xa1zis ebben az alkalmaz\xc3\xa1sban',
40 | 'Origin': 'Origin',
41 | 'Password': 'Password',
42 | 'Powered by': 'Powered by',
43 | 'Query:': 'Lek\xc3\xa9rdez\xc3\xa9s:',
44 | 'Record ID': 'Record ID',
45 | 'Registration key': 'Registration key',
46 | 'Reset Password key': 'Reset Password key',
47 | 'Role': 'Role',
48 | 'Rows in table': 'Sorok a t\xc3\xa1bl\xc3\xa1ban',
49 | 'Rows selected': 'Kiv\xc3\xa1lasztott sorok',
50 | 'Stylesheet': 'Stylesheet',
51 | 'Sure you want to delete this object?': 'Biztos t\xc3\xb6rli ezt az objektumot?',
52 | 'Table name': 'Table name',
53 | 'The "query" is a condition like "db.table1.field1==\'value\'". Something like "db.table1.field1==db.table2.field2" results in a SQL JOIN.': 'The "query" is a condition like "db.table1.field1==\'value\'". Something like "db.table1.field1==db.table2.field2" results in a SQL JOIN.',
54 | 'Timestamp': 'Timestamp',
55 | 'Update:': 'Friss\xc3\xadt:',
56 | 'Use (...)&(...) for AND, (...)|(...) for OR, and ~(...) for NOT to build more complex queries.': 'Use (...)&(...) for AND, (...)|(...) for OR, and ~(...) for NOT to build more complex queries.',
57 | 'User ID': 'User ID',
58 | 'View': 'N\xc3\xa9zet',
59 | 'Welcome %s': 'Welcome %s',
60 | 'Welcome to web2py': 'Isten hozott a web2py-ban',
61 | 'appadmin is disabled because insecure channel': 'az appadmin a biztons\xc3\xa1gtalan csatorna miatt letiltva',
62 | 'cache': 'gyors\xc3\xadt\xc3\xb3t\xc3\xa1r',
63 | 'change password': 'jelsz\xc3\xb3 megv\xc3\xa1ltoztat\xc3\xa1sa',
64 | 'Online examples': 'online p\xc3\xa9ld\xc3\xa1k\xc3\xa9rt kattints ide',
65 | 'Administrative interface': 'az adminisztr\xc3\xa1ci\xc3\xb3s fel\xc3\xbclet\xc3\xa9rt kattints ide',
66 | 'customize me!': 'v\xc3\xa1ltoztass meg!',
67 | 'data uploaded': 'adat felt\xc3\xb6ltve',
68 | 'database': 'adatb\xc3\xa1zis',
69 | 'database %s select': 'adatb\xc3\xa1zis %s kiv\xc3\xa1laszt\xc3\xa1s',
70 | 'db': 'db',
71 | 'design': 'design',
72 | 'done!': 'k\xc3\xa9sz!',
73 | 'edit profile': 'profil szerkeszt\xc3\xa9se',
74 | 'export as csv file': 'export\xc3\xa1l csv f\xc3\xa1jlba',
75 | 'insert new': '\xc3\xbaj beilleszt\xc3\xa9se',
76 | 'insert new %s': '\xc3\xbaj beilleszt\xc3\xa9se %s',
77 | 'invalid request': 'hib\xc3\xa1s k\xc3\xa9r\xc3\xa9s',
78 | 'login': 'bel\xc3\xa9p',
79 | 'logout': 'kil\xc3\xa9p',
80 | 'lost password': 'elveszett jelsz\xc3\xb3',
81 | 'new record inserted': '\xc3\xbaj bejegyz\xc3\xa9s felv\xc3\xa9ve',
82 | 'next 100 rows': 'k\xc3\xb6vetkez\xc5\x91 100 sor',
83 | 'or import from csv file': 'vagy bet\xc3\xb6lt\xc3\xa9s csv f\xc3\xa1jlb\xc3\xb3l',
84 | 'previous 100 rows': 'el\xc5\x91z\xc5\x91 100 sor',
85 | 'record': 'bejegyz\xc3\xa9s',
86 | 'record does not exist': 'bejegyz\xc3\xa9s nem l\xc3\xa9tezik',
87 | 'record id': 'bejegyz\xc3\xa9s id',
88 | 'register': 'regisztr\xc3\xa1ci\xc3\xb3',
89 | 'selected': 'kiv\xc3\xa1lasztott',
90 | 'state': '\xc3\xa1llapot',
91 | 'table': 't\xc3\xa1bla',
92 | 'unable to parse csv file': 'nem lehet a csv f\xc3\xa1jlt beolvasni',
93 | }
94 |
--------------------------------------------------------------------------------
/psp2py/languages/hu.py:
--------------------------------------------------------------------------------
1 | # coding: utf8
2 | {
3 | '"update" is an optional expression like "field1=\'newvalue\'". You cannot update or delete the results of a JOIN': '"update" is an optional expression like "field1=\'newvalue\'". You cannot update or delete the results of a JOIN',
4 | '%Y-%m-%d': '%Y.%m.%d.',
5 | '%Y-%m-%d %H:%M:%S': '%Y.%m.%d. %H:%M:%S',
6 | '%s rows deleted': '%s sorok t\xc3\xb6rl\xc5\x91dtek',
7 | '%s rows updated': '%s sorok friss\xc3\xadt\xc5\x91dtek',
8 | 'Available databases and tables': 'El\xc3\xa9rhet\xc5\x91 adatb\xc3\xa1zisok \xc3\xa9s t\xc3\xa1bl\xc3\xa1k',
9 | 'Cannot be empty': 'Nem lehet \xc3\xbcres',
10 | 'Check to delete': 'T\xc3\xb6rl\xc3\xa9shez v\xc3\xa1laszd ki',
11 | 'Client IP': 'Client IP',
12 | 'Controller': 'Controller',
13 | 'Copyright': 'Copyright',
14 | 'Current request': 'Jelenlegi lek\xc3\xa9rdez\xc3\xa9s',
15 | 'Current response': 'Jelenlegi v\xc3\xa1lasz',
16 | 'Current session': 'Jelenlegi folyamat',
17 | 'DB Model': 'DB Model',
18 | 'Database': 'Adatb\xc3\xa1zis',
19 | 'Delete:': 'T\xc3\xb6r\xc3\xb6l:',
20 | 'Description': 'Description',
21 | 'E-mail': 'E-mail',
22 | 'Edit': 'Szerkeszt',
23 | 'Edit This App': 'Alkalmaz\xc3\xa1st szerkeszt',
24 | 'Edit current record': 'Aktu\xc3\xa1lis bejegyz\xc3\xa9s szerkeszt\xc3\xa9se',
25 | 'First name': 'First name',
26 | 'Group ID': 'Group ID',
27 | 'Hello World': 'Hello Vil\xc3\xa1g',
28 | 'Import/Export': 'Import/Export',
29 | 'Index': 'Index',
30 | 'Internal State': 'Internal State',
31 | 'Invalid Query': 'Hib\xc3\xa1s lek\xc3\xa9rdez\xc3\xa9s',
32 | 'Invalid email': 'Invalid email',
33 | 'Last name': 'Last name',
34 | 'Layout': 'Szerkezet',
35 | 'Main Menu': 'F\xc5\x91men\xc3\xbc',
36 | 'Menu Model': 'Men\xc3\xbc model',
37 | 'Name': 'Name',
38 | 'New Record': '\xc3\x9aj bejegyz\xc3\xa9s',
39 | 'No databases in this application': 'Nincs adatb\xc3\xa1zis ebben az alkalmaz\xc3\xa1sban',
40 | 'Origin': 'Origin',
41 | 'Password': 'Password',
42 | 'Powered by': 'Powered by',
43 | 'Query:': 'Lek\xc3\xa9rdez\xc3\xa9s:',
44 | 'Record ID': 'Record ID',
45 | 'Registration key': 'Registration key',
46 | 'Reset Password key': 'Reset Password key',
47 | 'Role': 'Role',
48 | 'Rows in table': 'Sorok a t\xc3\xa1bl\xc3\xa1ban',
49 | 'Rows selected': 'Kiv\xc3\xa1lasztott sorok',
50 | 'Stylesheet': 'Stylesheet',
51 | 'Sure you want to delete this object?': 'Biztos t\xc3\xb6rli ezt az objektumot?',
52 | 'Table name': 'Table name',
53 | 'The "query" is a condition like "db.table1.field1==\'value\'". Something like "db.table1.field1==db.table2.field2" results in a SQL JOIN.': 'The "query" is a condition like "db.table1.field1==\'value\'". Something like "db.table1.field1==db.table2.field2" results in a SQL JOIN.',
54 | 'Timestamp': 'Timestamp',
55 | 'Update:': 'Friss\xc3\xadt:',
56 | 'Use (...)&(...) for AND, (...)|(...) for OR, and ~(...) for NOT to build more complex queries.': 'Use (...)&(...) for AND, (...)|(...) for OR, and ~(...) for NOT to build more complex queries.',
57 | 'User ID': 'User ID',
58 | 'View': 'N\xc3\xa9zet',
59 | 'Welcome %s': 'Welcome %s',
60 | 'Welcome to web2py': 'Isten hozott a web2py-ban',
61 | 'appadmin is disabled because insecure channel': 'az appadmin a biztons\xc3\xa1gtalan csatorna miatt letiltva',
62 | 'cache': 'gyors\xc3\xadt\xc3\xb3t\xc3\xa1r',
63 | 'change password': 'jelsz\xc3\xb3 megv\xc3\xa1ltoztat\xc3\xa1sa',
64 | 'Online examples': 'online p\xc3\xa9ld\xc3\xa1k\xc3\xa9rt kattints ide',
65 | 'Administrative interface': 'az adminisztr\xc3\xa1ci\xc3\xb3s fel\xc3\xbclet\xc3\xa9rt kattints ide',
66 | 'customize me!': 'v\xc3\xa1ltoztass meg!',
67 | 'data uploaded': 'adat felt\xc3\xb6ltve',
68 | 'database': 'adatb\xc3\xa1zis',
69 | 'database %s select': 'adatb\xc3\xa1zis %s kiv\xc3\xa1laszt\xc3\xa1s',
70 | 'db': 'db',
71 | 'design': 'design',
72 | 'done!': 'k\xc3\xa9sz!',
73 | 'edit profile': 'profil szerkeszt\xc3\xa9se',
74 | 'export as csv file': 'export\xc3\xa1l csv f\xc3\xa1jlba',
75 | 'insert new': '\xc3\xbaj beilleszt\xc3\xa9se',
76 | 'insert new %s': '\xc3\xbaj beilleszt\xc3\xa9se %s',
77 | 'invalid request': 'hib\xc3\xa1s k\xc3\xa9r\xc3\xa9s',
78 | 'login': 'bel\xc3\xa9p',
79 | 'logout': 'kil\xc3\xa9p',
80 | 'lost password': 'elveszett jelsz\xc3\xb3',
81 | 'new record inserted': '\xc3\xbaj bejegyz\xc3\xa9s felv\xc3\xa9ve',
82 | 'next 100 rows': 'k\xc3\xb6vetkez\xc5\x91 100 sor',
83 | 'or import from csv file': 'vagy bet\xc3\xb6lt\xc3\xa9s csv f\xc3\xa1jlb\xc3\xb3l',
84 | 'previous 100 rows': 'el\xc5\x91z\xc5\x91 100 sor',
85 | 'record': 'bejegyz\xc3\xa9s',
86 | 'record does not exist': 'bejegyz\xc3\xa9s nem l\xc3\xa9tezik',
87 | 'record id': 'bejegyz\xc3\xa9s id',
88 | 'register': 'regisztr\xc3\xa1ci\xc3\xb3',
89 | 'selected': 'kiv\xc3\xa1lasztott',
90 | 'state': '\xc3\xa1llapot',
91 | 'table': 't\xc3\xa1bla',
92 | 'unable to parse csv file': 'nem lehet a csv f\xc3\xa1jlt beolvasni',
93 | }
94 |
--------------------------------------------------------------------------------
/psp2py/languages/it-it.py:
--------------------------------------------------------------------------------
1 | # coding: utf8
2 | {
3 | '"update" is an optional expression like "field1=\'newvalue\'". You cannot update or delete the results of a JOIN': '"update" è un\'espressione opzionale come "campo1=\'nuovo valore\'". Non si può fare "update" o "delete" dei risultati di un JOIN ',
4 | '%Y-%m-%d': '%d/%m/%Y',
5 | '%Y-%m-%d %H:%M:%S': '%d/%m/%Y %H:%M:%S',
6 | '%s rows deleted': '%s righe ("record") cancellate',
7 | '%s rows updated': '%s righe ("record") modificate',
8 | 'Available databases and tables': 'Database e tabelle disponibili',
9 | 'Cannot be empty': 'Non può essere vuoto',
10 | 'Check to delete': 'Seleziona per cancellare',
11 | 'Client IP': 'Client IP',
12 | 'Controller': 'Controller',
13 | 'Copyright': 'Copyright',
14 | 'Current request': 'Richiesta (request) corrente',
15 | 'Current response': 'Risposta (response) corrente',
16 | 'Current session': 'Sessione (session) corrente',
17 | 'DB Model': 'Modello di DB',
18 | 'Database': 'Database',
19 | 'Delete:': 'Cancella:',
20 | 'Description': 'Descrizione',
21 | 'E-mail': 'E-mail',
22 | 'Edit': 'Modifica',
23 | 'Edit This App': 'Modifica questa applicazione',
24 | 'Edit current record': 'Modifica record corrente',
25 | 'First name': 'Nome',
26 | 'Group ID': 'ID Gruppo',
27 | 'Hello World': 'Salve Mondo',
28 | 'Hello World in a flash!': 'Salve Mondo in un flash!',
29 | 'Import/Export': 'Importa/Esporta',
30 | 'Index': 'Indice',
31 | 'Internal State': 'Stato interno',
32 | 'Invalid Query': 'Richiesta (query) non valida',
33 | 'Invalid email': 'Email non valida',
34 | 'Last name': 'Cognome',
35 | 'Layout': 'Layout',
36 | 'Main Menu': 'Menu principale',
37 | 'Menu Model': 'Menu Modelli',
38 | 'Name': 'Nome',
39 | 'New Record': 'Nuovo elemento (record)',
40 | 'No databases in this application': 'Nessun database presente in questa applicazione',
41 | 'Origin': 'Origine',
42 | 'Password': 'Password',
43 | 'Powered by': 'Powered by',
44 | 'Query:': 'Richiesta (query):',
45 | 'Record ID': 'Record ID',
46 | 'Registration key': 'Chiave di Registazione',
47 | 'Reset Password key': 'Resetta chiave Password ',
48 | 'Role': 'Ruolo',
49 | 'Rows in table': 'Righe nella tabella',
50 | 'Rows selected': 'Righe selezionate',
51 | 'Stylesheet': 'Foglio di stile (stylesheet)',
52 | 'Sure you want to delete this object?': 'Vuoi veramente cancellare questo oggetto?',
53 | 'Table name': 'Nome tabella',
54 | 'The "query" is a condition like "db.table1.field1==\'value\'". Something like "db.table1.field1==db.table2.field2" results in a SQL JOIN.': 'La richiesta (query) è una condizione come ad esempio "db.tabella1.campo1==\'valore\'". Una condizione come "db.tabella1.campo1==db.tabella2.campo2" produce un "JOIN" SQL.',
55 | 'The output of the file is a dictionary that was rendered by the view': 'L\'output del file è un "dictionary" che è stato visualizzato dalla vista',
56 | 'This is a copy of the scaffolding application': "Questa è una copia dell'applicazione di base (scaffold)",
57 | 'Timestamp': 'Ora (timestamp)',
58 | 'Update:': 'Aggiorna:',
59 | 'Use (...)&(...) for AND, (...)|(...) for OR, and ~(...) for NOT to build more complex queries.': 'Per costruire richieste (query) più complesse si usano (...)&(...) come "e" (AND), (...)|(...) come "o" (OR), e ~(...) come negazione (NOT).',
60 | 'User ID': 'ID Utente',
61 | 'View': 'Vista',
62 | 'Welcome %s': 'Benvenuto %s',
63 | 'Welcome to web2py': 'Benvenuto su web2py',
64 | 'Which called the function': 'che ha chiamato la funzione',
65 | 'You are successfully running web2py': 'Stai eseguendo web2py con successo',
66 | 'You can modify this application and adapt it to your needs': 'Puoi modificare questa applicazione adattandola alle tue necessità',
67 | 'You visited the url': "Hai visitato l'URL",
68 | 'appadmin is disabled because insecure channel': 'Amministrazione (appadmin) disabilitata: comunicazione non sicura',
69 | 'cache': 'cache',
70 | 'change password': 'Cambia password',
71 | 'Online examples': 'Vedere gli esempi',
72 | 'Administrative interface': "Interfaccia amministrativa",
73 | 'customize me!': 'Personalizzami!',
74 | 'data uploaded': 'dati caricati',
75 | 'database': 'database',
76 | 'database %s select': 'database %s select',
77 | 'db': 'db',
78 | 'design': 'progetta',
79 | 'Documentation': 'Documentazione',
80 | 'done!': 'fatto!',
81 | 'edit profile': 'modifica profilo',
82 | 'export as csv file': 'esporta come file CSV',
83 | 'hello world': 'salve mondo',
84 | 'insert new': 'inserisci nuovo',
85 | 'insert new %s': 'inserisci nuovo %s',
86 | 'invalid request': 'richiesta non valida',
87 | 'located in the file': 'presente nel file',
88 | 'login': 'accesso',
89 | 'logout': 'uscita',
90 | 'lost password?': 'dimenticato la password?',
91 | 'new record inserted': 'nuovo record inserito',
92 | 'next 100 rows': 'prossime 100 righe',
93 | 'not authorized': 'non autorizzato',
94 | 'or import from csv file': 'oppure importa da file CSV',
95 | 'previous 100 rows': '100 righe precedenti',
96 | 'record': 'record',
97 | 'record does not exist': 'il record non esiste',
98 | 'record id': 'record id',
99 | 'register': 'registrazione',
100 | 'selected': 'selezionato',
101 | 'state': 'stato',
102 | 'table': 'tabella',
103 | 'unable to parse csv file': 'non riesco a decodificare questo file CSV',
104 | }
105 |
--------------------------------------------------------------------------------
/psp2py/languages/it.py:
--------------------------------------------------------------------------------
1 | # coding: utf8
2 | {
3 | '"update" is an optional expression like "field1=\'newvalue\'". You cannot update or delete the results of a JOIN': '"update" è un\'espressione opzionale come "campo1=\'nuovo valore\'". Non si può fare "update" o "delete" dei risultati di un JOIN ',
4 | '%Y-%m-%d': '%d/%m/%Y',
5 | '%Y-%m-%d %H:%M:%S': '%d/%m/%Y %H:%M:%S',
6 | '%s rows deleted': '%s righe ("record") cancellate',
7 | '%s rows updated': '%s righe ("record") modificate',
8 | 'Available databases and tables': 'Database e tabelle disponibili',
9 | 'Cannot be empty': 'Non può essere vuoto',
10 | 'Check to delete': 'Seleziona per cancellare',
11 | 'Client IP': 'Client IP',
12 | 'Controller': 'Controller',
13 | 'Copyright': 'Copyright',
14 | 'Current request': 'Richiesta (request) corrente',
15 | 'Current response': 'Risposta (response) corrente',
16 | 'Current session': 'Sessione (session) corrente',
17 | 'DB Model': 'Modello di DB',
18 | 'Database': 'Database',
19 | 'Delete:': 'Cancella:',
20 | 'Description': 'Descrizione',
21 | 'E-mail': 'E-mail',
22 | 'Edit': 'Modifica',
23 | 'Edit This App': 'Modifica questa applicazione',
24 | 'Edit current record': 'Modifica record corrente',
25 | 'First name': 'Nome',
26 | 'Group ID': 'ID Gruppo',
27 | 'Hello World': 'Salve Mondo',
28 | 'Hello World in a flash!': 'Salve Mondo in un flash!',
29 | 'Import/Export': 'Importa/Esporta',
30 | 'Index': 'Indice',
31 | 'Internal State': 'Stato interno',
32 | 'Invalid Query': 'Richiesta (query) non valida',
33 | 'Invalid email': 'Email non valida',
34 | 'Last name': 'Cognome',
35 | 'Layout': 'Layout',
36 | 'Main Menu': 'Menu principale',
37 | 'Menu Model': 'Menu Modelli',
38 | 'Name': 'Nome',
39 | 'New Record': 'Nuovo elemento (record)',
40 | 'No databases in this application': 'Nessun database presente in questa applicazione',
41 | 'Origin': 'Origine',
42 | 'Password': 'Password',
43 | 'Powered by': 'Powered by',
44 | 'Query:': 'Richiesta (query):',
45 | 'Record ID': 'Record ID',
46 | 'Registration key': 'Chiave di Registazione',
47 | 'Reset Password key': 'Resetta chiave Password ',
48 | 'Role': 'Ruolo',
49 | 'Rows in table': 'Righe nella tabella',
50 | 'Rows selected': 'Righe selezionate',
51 | 'Stylesheet': 'Foglio di stile (stylesheet)',
52 | 'Sure you want to delete this object?': 'Vuoi veramente cancellare questo oggetto?',
53 | 'Table name': 'Nome tabella',
54 | 'The "query" is a condition like "db.table1.field1==\'value\'". Something like "db.table1.field1==db.table2.field2" results in a SQL JOIN.': 'La richiesta (query) è una condizione come ad esempio "db.tabella1.campo1==\'valore\'". Una condizione come "db.tabella1.campo1==db.tabella2.campo2" produce un "JOIN" SQL.',
55 | 'The output of the file is a dictionary that was rendered by the view': 'L\'output del file è un "dictionary" che è stato visualizzato dalla vista',
56 | 'This is a copy of the scaffolding application': "Questa è una copia dell'applicazione di base (scaffold)",
57 | 'Timestamp': 'Ora (timestamp)',
58 | 'Update:': 'Aggiorna:',
59 | 'Use (...)&(...) for AND, (...)|(...) for OR, and ~(...) for NOT to build more complex queries.': 'Per costruire richieste (query) più complesse si usano (...)&(...) come "e" (AND), (...)|(...) come "o" (OR), e ~(...) come negazione (NOT).',
60 | 'User ID': 'ID Utente',
61 | 'View': 'Vista',
62 | 'Welcome %s': 'Benvenuto %s',
63 | 'Welcome to web2py': 'Benvenuto su web2py',
64 | 'Which called the function': 'che ha chiamato la funzione',
65 | 'You are successfully running web2py': 'Stai eseguendo web2py con successo',
66 | 'You can modify this application and adapt it to your needs': 'Puoi modificare questa applicazione adattandola alle tue necessità',
67 | 'You visited the url': "Hai visitato l'URL",
68 | 'appadmin is disabled because insecure channel': 'Amministrazione (appadmin) disabilitata: comunicazione non sicura',
69 | 'cache': 'cache',
70 | 'change password': 'Cambia password',
71 | 'Online examples': 'Vedere gli esempi',
72 | 'Administrative interface': "Interfaccia amministrativa",
73 | 'customize me!': 'Personalizzami!',
74 | 'data uploaded': 'dati caricati',
75 | 'database': 'database',
76 | 'database %s select': 'database %s select',
77 | 'db': 'db',
78 | 'design': 'progetta',
79 | 'Documentation': 'Documentazione',
80 | 'done!': 'fatto!',
81 | 'edit profile': 'modifica profilo',
82 | 'export as csv file': 'esporta come file CSV',
83 | 'hello world': 'salve mondo',
84 | 'insert new': 'inserisci nuovo',
85 | 'insert new %s': 'inserisci nuovo %s',
86 | 'invalid request': 'richiesta non valida',
87 | 'located in the file': 'presente nel file',
88 | 'login': 'accesso',
89 | 'logout': 'uscita',
90 | 'lost password?': 'dimenticato la password?',
91 | 'new record inserted': 'nuovo record inserito',
92 | 'next 100 rows': 'prossime 100 righe',
93 | 'not authorized': 'non autorizzato',
94 | 'or import from csv file': 'oppure importa da file CSV',
95 | 'previous 100 rows': '100 righe precedenti',
96 | 'record': 'record',
97 | 'record does not exist': 'il record non esiste',
98 | 'record id': 'record id',
99 | 'register': 'registrazione',
100 | 'selected': 'selezionato',
101 | 'state': 'stato',
102 | 'table': 'tabella',
103 | 'unable to parse csv file': 'non riesco a decodificare questo file CSV',
104 | }
105 |
--------------------------------------------------------------------------------
/psp2py/languages/pl-pl.py:
--------------------------------------------------------------------------------
1 | # coding: utf8
2 | {
3 | '"update" is an optional expression like "field1=\'newvalue\'". You cannot update or delete the results of a JOIN': '"Uaktualnij" jest dodatkowym wyra\xc5\xbceniem postaci "pole1=\'nowawarto\xc5\x9b\xc4\x87\'". Nie mo\xc5\xbcesz uaktualni\xc4\x87 lub usun\xc4\x85\xc4\x87 wynik\xc3\xb3w z JOIN:',
4 | '%Y-%m-%d': '%Y-%m-%d',
5 | '%Y-%m-%d %H:%M:%S': '%Y-%m-%d %H:%M:%S',
6 | '%s rows deleted': 'Wierszy usuni\xc4\x99tych: %s',
7 | '%s rows updated': 'Wierszy uaktualnionych: %s',
8 | 'Available databases and tables': 'Dost\xc4\x99pne bazy danych i tabele',
9 | 'Cannot be empty': 'Nie mo\xc5\xbce by\xc4\x87 puste',
10 | 'Change Password': 'Change Password',
11 | 'Check to delete': 'Zaznacz aby usun\xc4\x85\xc4\x87',
12 | 'Controller': 'Controller',
13 | 'Copyright': 'Copyright',
14 | 'Current request': 'Aktualne \xc5\xbc\xc4\x85danie',
15 | 'Current response': 'Aktualna odpowied\xc5\xba',
16 | 'Current session': 'Aktualna sesja',
17 | 'DB Model': 'DB Model',
18 | 'Database': 'Database',
19 | 'Delete:': 'Usu\xc5\x84:',
20 | 'Edit': 'Edit',
21 | 'Edit Profile': 'Edit Profile',
22 | 'Edit This App': 'Edit This App',
23 | 'Edit current record': 'Edytuj aktualny rekord',
24 | 'Hello World': 'Witaj \xc5\x9awiecie',
25 | 'Import/Export': 'Importuj/eksportuj',
26 | 'Index': 'Index',
27 | 'Internal State': 'Stan wewn\xc4\x99trzny',
28 | 'Invalid Query': 'B\xc5\x82\xc4\x99dne zapytanie',
29 | 'Layout': 'Layout',
30 | 'Login': 'Zaloguj',
31 | 'Logout': 'Logout',
32 | 'Lost Password': 'Przypomnij has\xc5\x82o',
33 | 'Main Menu': 'Main Menu',
34 | 'Menu Model': 'Menu Model',
35 | 'New Record': 'Nowy rekord',
36 | 'No databases in this application': 'Brak baz danych w tej aplikacji',
37 | 'Powered by': 'Powered by',
38 | 'Query:': 'Zapytanie:',
39 | 'Register': 'Zarejestruj',
40 | 'Rows in table': 'Wiersze w tabeli',
41 | 'Rows selected': 'Wybrane wiersze',
42 | 'Stylesheet': 'Stylesheet',
43 | 'Sure you want to delete this object?': 'Czy na pewno chcesz usun\xc4\x85\xc4\x87 ten obiekt?',
44 | 'The "query" is a condition like "db.table1.field1==\'value\'". Something like "db.table1.field1==db.table2.field2" results in a SQL JOIN.': '"Zapytanie" jest warunkiem postaci "db.tabela1.pole1==\'warto\xc5\x9b\xc4\x87\'". Takie co\xc5\x9b jak "db.tabela1.pole1==db.tabela2.pole2" oznacza SQL JOIN.',
45 | 'Update:': 'Uaktualnij:',
46 | 'Use (...)&(...) for AND, (...)|(...) for OR, and ~(...) for NOT to build more complex queries.': 'U\xc5\xbcyj (...)&(...) jako AND, (...)|(...) jako OR oraz ~(...) jako NOT do tworzenia bardziej skomplikowanych zapyta\xc5\x84.',
47 | 'View': 'View',
48 | 'Welcome %s': 'Welcome %s',
49 | 'Welcome to web2py': 'Witaj w web2py',
50 | 'appadmin is disabled because insecure channel': 'appadmin is disabled because insecure channel',
51 | 'cache': 'cache',
52 | 'change password': 'change password',
53 | 'Online examples': 'Kliknij aby przej\xc5\x9b\xc4\x87 do interaktywnych przyk\xc5\x82ad\xc3\xb3w',
54 | 'Administrative interface': 'Kliknij aby przej\xc5\x9b\xc4\x87 do panelu administracyjnego',
55 | 'customize me!': 'dostosuj mnie!',
56 | 'data uploaded': 'dane wys\xc5\x82ane',
57 | 'database': 'baza danych',
58 | 'database %s select': 'wyb\xc3\xb3r z bazy danych %s',
59 | 'db': 'baza danych',
60 | 'design': 'projektuj',
61 | 'done!': 'zrobione!',
62 | 'edit profile': 'edit profile',
63 | 'export as csv file': 'eksportuj jako plik csv',
64 | 'insert new': 'wstaw nowy rekord tabeli',
65 | 'insert new %s': 'wstaw nowy rekord do tabeli %s',
66 | 'invalid request': 'B\xc5\x82\xc4\x99dne \xc5\xbc\xc4\x85danie',
67 | 'login': 'login',
68 | 'logout': 'logout',
69 | 'new record inserted': 'nowy rekord zosta\xc5\x82 wstawiony',
70 | 'next 100 rows': 'nast\xc4\x99pne 100 wierszy',
71 | 'or import from csv file': 'lub zaimportuj z pliku csv',
72 | 'previous 100 rows': 'poprzednie 100 wierszy',
73 | 'record': 'record',
74 | 'record does not exist': 'rekord nie istnieje',
75 | 'record id': 'id rekordu',
76 | 'register': 'register',
77 | 'selected': 'wybranych',
78 | 'state': 'stan',
79 | 'table': 'tabela',
80 | 'unable to parse csv file': 'nie mo\xc5\xbcna sparsowa\xc4\x87 pliku csv',
81 | }
82 |
--------------------------------------------------------------------------------
/psp2py/languages/pl.py:
--------------------------------------------------------------------------------
1 | # coding: utf8
2 | {
3 | '"update" is an optional expression like "field1=\'newvalue\'". You cannot update or delete the results of a JOIN': '"Uaktualnij" jest dodatkowym wyra\xc5\xbceniem postaci "pole1=\'nowawarto\xc5\x9b\xc4\x87\'". Nie mo\xc5\xbcesz uaktualni\xc4\x87 lub usun\xc4\x85\xc4\x87 wynik\xc3\xb3w z JOIN:',
4 | '%Y-%m-%d': '%Y-%m-%d',
5 | '%Y-%m-%d %H:%M:%S': '%Y-%m-%d %H:%M:%S',
6 | '%s rows deleted': 'Wierszy usuni\xc4\x99tych: %s',
7 | '%s rows updated': 'Wierszy uaktualnionych: %s',
8 | 'Authentication': 'Uwierzytelnienie',
9 | 'Available databases and tables': 'Dost\xc4\x99pne bazy danych i tabele',
10 | 'Cannot be empty': 'Nie mo\xc5\xbce by\xc4\x87 puste',
11 | 'Change Password': 'Zmie\xc5\x84 has\xc5\x82o',
12 | 'Check to delete': 'Zaznacz aby usun\xc4\x85\xc4\x87',
13 | 'Check to delete:': 'Zaznacz aby usun\xc4\x85\xc4\x87:',
14 | 'Client IP': 'IP klienta',
15 | 'Controller': 'Kontroler',
16 | 'Copyright': 'Copyright',
17 | 'Current request': 'Aktualne \xc5\xbc\xc4\x85danie',
18 | 'Current response': 'Aktualna odpowied\xc5\xba',
19 | 'Current session': 'Aktualna sesja',
20 | 'DB Model': 'Model bazy danych',
21 | 'Database': 'Baza danych',
22 | 'Delete:': 'Usu\xc5\x84:',
23 | 'Description': 'Opis',
24 | 'E-mail': 'Adres e-mail',
25 | 'Edit': 'Edycja',
26 | 'Edit Profile': 'Edytuj profil',
27 | 'Edit This App': 'Edytuj t\xc4\x99 aplikacj\xc4\x99',
28 | 'Edit current record': 'Edytuj obecny rekord',
29 | 'First name': 'Imi\xc4\x99',
30 | 'Function disabled': 'Funkcja wy\xc5\x82\xc4\x85czona',
31 | 'Group ID': 'ID grupy',
32 | 'Hello World': 'Witaj \xc5\x9awiecie',
33 | 'Import/Export': 'Importuj/eksportuj',
34 | 'Index': 'Indeks',
35 | 'Internal State': 'Stan wewn\xc4\x99trzny',
36 | 'Invalid Query': 'B\xc5\x82\xc4\x99dne zapytanie',
37 | 'Invalid email': 'B\xc5\x82\xc4\x99dny adres email',
38 | 'Last name': 'Nazwisko',
39 | 'Layout': 'Uk\xc5\x82ad',
40 | 'Login': 'Zaloguj',
41 | 'Logout': 'Wyloguj',
42 | 'Lost Password': 'Przypomnij has\xc5\x82o',
43 | 'Main Menu': 'Menu g\xc5\x82\xc3\xb3wne',
44 | 'Menu Model': 'Model menu',
45 | 'Name': 'Nazwa',
46 | 'New Record': 'Nowy rekord',
47 | 'No databases in this application': 'Brak baz danych w tej aplikacji',
48 | 'Origin': '\xc5\xb9r\xc3\xb3d\xc5\x82o',
49 | 'Password': 'Has\xc5\x82o',
50 | "Password fields don't match": 'Pola has\xc5\x82a nie s\xc4\x85 zgodne ze sob\xc4\x85',
51 | 'Powered by': 'Zasilane przez',
52 | 'Query:': 'Zapytanie:',
53 | 'Record ID': 'ID rekordu',
54 | 'Register': 'Zarejestruj',
55 | 'Registration key': 'Klucz rejestracji',
56 | 'Role': 'Rola',
57 | 'Rows in table': 'Wiersze w tabeli',
58 | 'Rows selected': 'Wybrane wiersze',
59 | 'Stylesheet': 'Arkusz styl\xc3\xb3w',
60 | 'Submit': 'Wy\xc5\x9blij',
61 | 'Sure you want to delete this object?': 'Czy na pewno chcesz usun\xc4\x85\xc4\x87 ten obiekt?',
62 | 'Table name': 'Nazwa tabeli',
63 | 'The "query" is a condition like "db.table1.field1==\'value\'". Something like "db.table1.field1==db.table2.field2" results in a SQL JOIN.': '"Zapytanie" jest warunkiem postaci "db.tabela1.pole1==\'warto\xc5\x9b\xc4\x87\'". Takie co\xc5\x9b jak "db.tabela1.pole1==db.tabela2.pole2" oznacza SQL JOIN.',
64 | 'Timestamp': 'Znacznik czasu',
65 | 'Update:': 'Uaktualnij:',
66 | 'Use (...)&(...) for AND, (...)|(...) for OR, and ~(...) for NOT to build more complex queries.': 'U\xc5\xbcyj (...)&(...) jako AND, (...)|(...) jako OR oraz ~(...) jako NOT do tworzenia bardziej skomplikowanych zapyta\xc5\x84.',
67 | 'User %(id)s Registered': 'U\xc5\xbcytkownik %(id)s zosta\xc5\x82 zarejestrowany',
68 | 'User ID': 'ID u\xc5\xbcytkownika',
69 | 'Verify Password': 'Potwierd\xc5\xba has\xc5\x82o',
70 | 'View': 'Widok',
71 | 'Welcome %s': 'Welcome %s',
72 | 'Welcome to web2py': 'Witaj w web2py',
73 | 'appadmin is disabled because insecure channel': 'administracja aplikacji wy\xc5\x82\xc4\x85czona z powodu braku bezpiecznego po\xc5\x82\xc4\x85czenia',
74 | 'cache': 'cache',
75 | 'change password': 'change password',
76 | 'Online examples': 'Kliknij aby przej\xc5\x9b\xc4\x87 do interaktywnych przyk\xc5\x82ad\xc3\xb3w',
77 | 'Administrative interface': 'Kliknij aby przej\xc5\x9b\xc4\x87 do panelu administracyjnego',
78 | 'customize me!': 'dostosuj mnie!',
79 | 'data uploaded': 'dane wys\xc5\x82ane',
80 | 'database': 'baza danych',
81 | 'database %s select': 'wyb\xc3\xb3r z bazy danych %s',
82 | 'db': 'baza danych',
83 | 'design': 'projektuj',
84 | 'done!': 'zrobione!',
85 | 'edit profile': 'edit profile',
86 | 'export as csv file': 'eksportuj jako plik csv',
87 | 'insert new': 'wstaw nowy rekord tabeli',
88 | 'insert new %s': 'wstaw nowy rekord do tabeli %s',
89 | 'invalid request': 'B\xc5\x82\xc4\x99dne \xc5\xbc\xc4\x85danie',
90 | 'login': 'login',
91 | 'logout': 'logout',
92 | 'new record inserted': 'nowy rekord zosta\xc5\x82 wstawiony',
93 | 'next 100 rows': 'nast\xc4\x99pne 100 wierszy',
94 | 'or import from csv file': 'lub zaimportuj z pliku csv',
95 | 'previous 100 rows': 'poprzednie 100 wierszy',
96 | 'record': 'rekord',
97 | 'record does not exist': 'rekord nie istnieje',
98 | 'record id': 'id rekordu',
99 | 'register': 'register',
100 | 'selected': 'wybranych',
101 | 'state': 'stan',
102 | 'table': 'tabela',
103 | 'unable to parse csv file': 'nie mo\xc5\xbcna sparsowa\xc4\x87 pliku csv',
104 | }
105 |
--------------------------------------------------------------------------------
/psp2py/languages/pt-pt.py:
--------------------------------------------------------------------------------
1 | # coding: utf8
2 | {
3 | '"update" is an optional expression like "field1=\'newvalue\'". You cannot update or delete the results of a JOIN': '"update" é uma expressão opcional como "field1=\'newvalue\'". Não pode actualizar ou eliminar os resultados de um JOIN',
4 | '%Y-%m-%d': '%Y-%m-%d',
5 | '%Y-%m-%d %H:%M:%S': '%Y-%m-%d %H:%M:%S',
6 | '%s rows deleted': '%s linhas eliminadas',
7 | '%s rows updated': '%s linhas actualizadas',
8 | 'About': 'About',
9 | 'Author Reference Auth User': 'Author Reference Auth User',
10 | 'Author Reference Auth User.username': 'Author Reference Auth User.username',
11 | 'Available databases and tables': 'bases de dados e tabelas disponíveis',
12 | 'Cannot be empty': 'não pode ser vazio',
13 | 'Category Create': 'Category Create',
14 | 'Category Select': 'Category Select',
15 | 'Check to delete': 'seleccione para eliminar',
16 | 'Comment Create': 'Comment Create',
17 | 'Comment Select': 'Comment Select',
18 | 'Content': 'Content',
19 | 'Controller': 'Controlador',
20 | 'Copyright': 'Direitos de cópia',
21 | 'Created By': 'Created By',
22 | 'Created On': 'Created On',
23 | 'Current request': 'pedido currente',
24 | 'Current response': 'resposta currente',
25 | 'Current session': 'sessão currente',
26 | 'DB Model': 'Modelo de BD',
27 | 'Database': 'Base de dados',
28 | 'Delete:': 'Eliminar:',
29 | 'Edit': 'Editar',
30 | 'Edit This App': 'Edite esta aplicação',
31 | 'Edit current record': 'Edição de registo currente',
32 | 'Email': 'Email',
33 | 'First Name': 'First Name',
34 | 'For %s #%s': 'For %s #%s',
35 | 'Hello World': 'Olá Mundo',
36 | 'Import/Export': 'Importar/Exportar',
37 | 'Index': 'Índice',
38 | 'Internal State': 'Estado interno',
39 | 'Invalid Query': 'Consulta Inválida',
40 | 'Last Name': 'Last Name',
41 | 'Layout': 'Esboço',
42 | 'Main Menu': 'Menu Principal',
43 | 'Menu Model': 'Menu do Modelo',
44 | 'Modified By': 'Modified By',
45 | 'Modified On': 'Modified On',
46 | 'Name': 'Name',
47 | 'New Record': 'Novo Registo',
48 | 'No Data': 'No Data',
49 | 'No databases in this application': 'Não há bases de dados nesta aplicação',
50 | 'Password': 'Password',
51 | 'Post Create': 'Post Create',
52 | 'Post Select': 'Post Select',
53 | 'Powered by': 'Suportado por',
54 | 'Query:': 'Interrogação:',
55 | 'Replyto Reference Post': 'Replyto Reference Post',
56 | 'Rows in table': 'Linhas numa tabela',
57 | 'Rows selected': 'Linhas seleccionadas',
58 | 'Stylesheet': 'Folha de estilo',
59 | 'Sure you want to delete this object?': 'Tem a certeza que deseja eliminar este objecto?',
60 | 'The "query" is a condition like "db.table1.field1==\'value\'". Something like "db.table1.field1==db.table2.field2" results in a SQL JOIN.': 'A "query" é uma condição do tipo "db.table1.field1==\'value\'". Algo como "db.table1.field1==db.table2.field2" resultaria num SQL JOIN.',
61 | 'Title': 'Title',
62 | 'Update:': 'Actualização:',
63 | 'Use (...)&(...) for AND, (...)|(...) for OR, and ~(...) for NOT to build more complex queries.': 'Utilize (...)&(...) para AND, (...)|(...) para OR, e ~(...) para NOT para construir interrogações mais complexas.',
64 | 'Username': 'Username',
65 | 'View': 'Vista',
66 | 'Welcome %s': 'Bem-vindo(a) %s',
67 | 'Welcome to Gluonization': 'Bem vindo ao Web2py',
68 | 'Welcome to web2py': 'Bem-vindo(a) ao web2py',
69 | 'When': 'When',
70 | 'appadmin is disabled because insecure channel': 'appadmin está desactivada pois o canal é inseguro',
71 | 'cache': 'cache',
72 | 'change password': 'alterar palavra-chave',
73 | 'Online examples': 'Exemplos online',
74 | 'Administrative interface': 'Painel administrativo',
75 | 'create new category': 'create new category',
76 | 'create new comment': 'create new comment',
77 | 'create new post': 'create new post',
78 | 'customize me!': 'Personaliza-me!',
79 | 'data uploaded': 'informação enviada',
80 | 'database': 'base de dados',
81 | 'database %s select': 'selecção de base de dados %s',
82 | 'db': 'bd',
83 | 'design': 'design',
84 | 'done!': 'concluído!',
85 | 'edit category': 'edit category',
86 | 'edit comment': 'edit comment',
87 | 'edit post': 'edit post',
88 | 'edit profile': 'Editar perfil',
89 | 'export as csv file': 'exportar como ficheiro csv',
90 | 'insert new': 'inserir novo',
91 | 'insert new %s': 'inserir novo %s',
92 | 'invalid request': 'Pedido Inválido',
93 | 'login': 'login',
94 | 'logout': 'logout',
95 | 'new record inserted': 'novo registo inserido',
96 | 'next 100 rows': 'próximas 100 linhas',
97 | 'or import from csv file': 'ou importe a partir de ficheiro csv',
98 | 'previous 100 rows': '100 linhas anteriores',
99 | 'record': 'registo',
100 | 'record does not exist': 'registo inexistente',
101 | 'record id': 'id de registo',
102 | 'register': 'register',
103 | 'search category': 'search category',
104 | 'search comment': 'search comment',
105 | 'search post': 'search post',
106 | 'select category': 'select category',
107 | 'select comment': 'select comment',
108 | 'select post': 'select post',
109 | 'selected': 'seleccionado(s)',
110 | 'show category': 'show category',
111 | 'show comment': 'show comment',
112 | 'show post': 'show post',
113 | 'state': 'estado',
114 | 'table': 'tabela',
115 | 'unable to parse csv file': 'não foi possível carregar ficheiro csv',
116 | }
117 |
--------------------------------------------------------------------------------
/psp2py/languages/pt.py:
--------------------------------------------------------------------------------
1 | # coding: utf8
2 | {
3 | '"update" is an optional expression like "field1=\'newvalue\'". You cannot update or delete the results of a JOIN': '"update" é uma expressão opcional como "field1=\'newvalue\'". Não pode actualizar ou eliminar os resultados de um JOIN',
4 | '%Y-%m-%d': '%Y-%m-%d',
5 | '%Y-%m-%d %H:%M:%S': '%Y-%m-%d %H:%M:%S',
6 | '%s rows deleted': '%s linhas eliminadas',
7 | '%s rows updated': '%s linhas actualizadas',
8 | 'About': 'About',
9 | 'Author Reference Auth User': 'Author Reference Auth User',
10 | 'Author Reference Auth User.username': 'Author Reference Auth User.username',
11 | 'Available databases and tables': 'bases de dados e tabelas disponíveis',
12 | 'Cannot be empty': 'não pode ser vazio',
13 | 'Category Create': 'Category Create',
14 | 'Category Select': 'Category Select',
15 | 'Check to delete': 'seleccione para eliminar',
16 | 'Comment Create': 'Comment Create',
17 | 'Comment Select': 'Comment Select',
18 | 'Content': 'Content',
19 | 'Controller': 'Controlador',
20 | 'Copyright': 'Direitos de cópia',
21 | 'Created By': 'Created By',
22 | 'Created On': 'Created On',
23 | 'Current request': 'pedido currente',
24 | 'Current response': 'resposta currente',
25 | 'Current session': 'sessão currente',
26 | 'DB Model': 'Modelo de BD',
27 | 'Database': 'Base de dados',
28 | 'Delete:': 'Eliminar:',
29 | 'Edit': 'Editar',
30 | 'Edit This App': 'Edite esta aplicação',
31 | 'Edit current record': 'Edição de registo currente',
32 | 'Email': 'Email',
33 | 'First Name': 'First Name',
34 | 'For %s #%s': 'For %s #%s',
35 | 'Hello World': 'Olá Mundo',
36 | 'Import/Export': 'Importar/Exportar',
37 | 'Index': 'Índice',
38 | 'Internal State': 'Estado interno',
39 | 'Invalid Query': 'Consulta Inválida',
40 | 'Last Name': 'Last Name',
41 | 'Layout': 'Esboço',
42 | 'Main Menu': 'Menu Principal',
43 | 'Menu Model': 'Menu do Modelo',
44 | 'Modified By': 'Modified By',
45 | 'Modified On': 'Modified On',
46 | 'Name': 'Name',
47 | 'New Record': 'Novo Registo',
48 | 'No Data': 'No Data',
49 | 'No databases in this application': 'Não há bases de dados nesta aplicação',
50 | 'Password': 'Password',
51 | 'Post Create': 'Post Create',
52 | 'Post Select': 'Post Select',
53 | 'Powered by': 'Suportado por',
54 | 'Query:': 'Interrogação:',
55 | 'Replyto Reference Post': 'Replyto Reference Post',
56 | 'Rows in table': 'Linhas numa tabela',
57 | 'Rows selected': 'Linhas seleccionadas',
58 | 'Stylesheet': 'Folha de estilo',
59 | 'Sure you want to delete this object?': 'Tem a certeza que deseja eliminar este objecto?',
60 | 'The "query" is a condition like "db.table1.field1==\'value\'". Something like "db.table1.field1==db.table2.field2" results in a SQL JOIN.': 'A "query" é uma condição do tipo "db.table1.field1==\'value\'". Algo como "db.table1.field1==db.table2.field2" resultaria num SQL JOIN.',
61 | 'Title': 'Title',
62 | 'Update:': 'Actualização:',
63 | 'Use (...)&(...) for AND, (...)|(...) for OR, and ~(...) for NOT to build more complex queries.': 'Utilize (...)&(...) para AND, (...)|(...) para OR, e ~(...) para NOT para construir interrogações mais complexas.',
64 | 'Username': 'Username',
65 | 'View': 'Vista',
66 | 'Welcome %s': 'Bem-vindo(a) %s',
67 | 'Welcome to Gluonization': 'Bem vindo ao Web2py',
68 | 'Welcome to web2py': 'Bem-vindo(a) ao web2py',
69 | 'When': 'When',
70 | 'appadmin is disabled because insecure channel': 'appadmin está desactivada pois o canal é inseguro',
71 | 'cache': 'cache',
72 | 'change password': 'alterar palavra-chave',
73 | 'Online examples': 'Exemplos online',
74 | 'Administrative interface': 'Painel administrativo',
75 | 'create new category': 'create new category',
76 | 'create new comment': 'create new comment',
77 | 'create new post': 'create new post',
78 | 'customize me!': 'Personaliza-me!',
79 | 'data uploaded': 'informação enviada',
80 | 'database': 'base de dados',
81 | 'database %s select': 'selecção de base de dados %s',
82 | 'db': 'bd',
83 | 'design': 'design',
84 | 'done!': 'concluído!',
85 | 'edit category': 'edit category',
86 | 'edit comment': 'edit comment',
87 | 'edit post': 'edit post',
88 | 'edit profile': 'Editar perfil',
89 | 'export as csv file': 'exportar como ficheiro csv',
90 | 'insert new': 'inserir novo',
91 | 'insert new %s': 'inserir novo %s',
92 | 'invalid request': 'Pedido Inválido',
93 | 'login': 'login',
94 | 'logout': 'logout',
95 | 'new record inserted': 'novo registo inserido',
96 | 'next 100 rows': 'próximas 100 linhas',
97 | 'or import from csv file': 'ou importe a partir de ficheiro csv',
98 | 'previous 100 rows': '100 linhas anteriores',
99 | 'record': 'registo',
100 | 'record does not exist': 'registo inexistente',
101 | 'record id': 'id de registo',
102 | 'register': 'register',
103 | 'search category': 'search category',
104 | 'search comment': 'search comment',
105 | 'search post': 'search post',
106 | 'select category': 'select category',
107 | 'select comment': 'select comment',
108 | 'select post': 'select post',
109 | 'selected': 'seleccionado(s)',
110 | 'show category': 'show category',
111 | 'show comment': 'show comment',
112 | 'show post': 'show post',
113 | 'state': 'estado',
114 | 'table': 'tabela',
115 | 'unable to parse csv file': 'não foi possível carregar ficheiro csv',
116 | }
117 |
--------------------------------------------------------------------------------
/psp2py/languages/ru-ru.py:
--------------------------------------------------------------------------------
1 | # coding: utf8
2 | {
3 | '"update" is an optional expression like "field1=\'newvalue\'". You cannot update or delete the results of a JOIN': '"Изменить" - необязательное выражение вида "field1=\'новое значение\'". Результаты операции JOIN нельзя изменить или удалить.',
4 | '%Y-%m-%d': '%Y-%m-%d',
5 | '%Y-%m-%d %H:%M:%S': '%Y-%m-%d %H:%M:%S',
6 | '%s rows deleted': '%s строк удалено',
7 | '%s rows updated': '%s строк изменено',
8 | 'Available databases and tables': 'Базы данных и таблицы',
9 | 'Cannot be empty': 'Пустое значение недопустимо',
10 | 'Change Password': 'Смените пароль',
11 | 'Check to delete': 'Удалить',
12 | 'Check to delete:': 'Удалить:',
13 | 'Client IP': 'Client IP',
14 | 'Current request': 'Текущий запрос',
15 | 'Current response': 'Текущий ответ',
16 | 'Current session': 'Текущая сессия',
17 | 'Delete:': 'Удалить:',
18 | 'Description': 'Описание',
19 | 'E-mail': 'E-mail',
20 | 'Edit Profile': 'Редактировать профиль',
21 | 'Edit current record': 'Редактировать текущую запись',
22 | 'First name': 'Имя',
23 | 'Group ID': 'Group ID',
24 | 'Hello World': 'Заработало!',
25 | 'Import/Export': 'Импорт/экспорт',
26 | 'Internal State': 'Внутренне состояние',
27 | 'Invalid Query': 'Неверный запрос',
28 | 'Invalid email': 'Неверный email',
29 | 'Invalid login': 'Неверный логин',
30 | 'Invalid password': 'Неверный пароль',
31 | 'Last name': 'Фамилия',
32 | 'Logged in': 'Вход выполнен',
33 | 'Logged out': 'Выход выполнен',
34 | 'Login': 'Вход',
35 | 'Logout': 'Выход',
36 | 'Lost Password': 'Забыли пароль?',
37 | 'Name': 'Name',
38 | 'New Record': 'Новая запись',
39 | 'New password': 'Новый пароль',
40 | 'No databases in this application': 'В приложении нет баз данных',
41 | 'Old password': 'Старый пароль',
42 | 'Origin': 'Происхождение',
43 | 'Password': 'Пароль',
44 | "Password fields don't match": 'Пароли не совпадают',
45 | 'Query:': 'Запрос:',
46 | 'Record ID': 'ID записи',
47 | 'Register': 'Зарегистрироваться',
48 | 'Registration key': 'Ключ регистрации',
49 | 'Remember me (for 30 days)': 'Запомнить меня (на 30 дней)',
50 | 'Reset Password key': 'Сбросить ключ пароля',
51 | 'Role': 'Роль',
52 | 'Rows in table': 'Строк в таблице',
53 | 'Rows selected': 'Выделено строк',
54 | 'Submit': 'Отправить',
55 | 'Sure you want to delete this object?': 'Подтвердите удаление объекта',
56 | 'Table name': 'Имя таблицы',
57 | 'The "query" is a condition like "db.table1.field1==\'value\'". Something like "db.table1.field1==db.table2.field2" results in a SQL JOIN.': '"Запрос" - это условие вида "db.table1.field1==\'значение\'". Выражение вида "db.table1.field1==db.table2.field2" формирует SQL JOIN.',
58 | 'Timestamp': 'Отметка времени',
59 | 'Update:': 'Изменить:',
60 | 'Use (...)&(...) for AND, (...)|(...) for OR, and ~(...) for NOT to build more complex queries.': 'Для построение сложных запросов используйте операторы "И": (...)&(...), "ИЛИ": (...)|(...), "НЕ": ~(...).',
61 | 'User %(id)s Logged-in': 'Пользователь %(id)s вошёл',
62 | 'User %(id)s Logged-out': 'Пользователь %(id)s вышел',
63 | 'User %(id)s Password changed': 'Пользователь %(id)s сменил пароль',
64 | 'User %(id)s Profile updated': 'Пользователь %(id)s обновил профиль',
65 | 'User %(id)s Registered': 'Пользователь %(id)s зарегистрировался',
66 | 'User ID': 'ID пользователя',
67 | 'Verify Password': 'Повторите пароль',
68 | 'Welcome to web2py': 'Добро пожаловать в web2py',
69 | 'Online examples': 'примеры он-лайн',
70 | 'Administrative interface': 'административный интерфейс',
71 | 'customize me!': 'настройте внешний вид!',
72 | 'data uploaded': 'данные загружены',
73 | 'database': 'база данных',
74 | 'database %s select': 'выбор базы данных %s',
75 | 'db': 'БД',
76 | 'design': 'дизайн',
77 | 'done!': 'готово!',
78 | 'export as csv file': 'экспорт в csv-файл',
79 | 'insert new': 'добавить',
80 | 'insert new %s': 'добавить %s',
81 | 'invalid request': 'неверный запрос',
82 | 'login': 'вход',
83 | 'logout': 'выход',
84 | 'new record inserted': 'новая запись добавлена',
85 | 'next 100 rows': 'следующие 100 строк',
86 | 'or import from csv file': 'или импорт из csv-файла',
87 | 'password': 'пароль',
88 | 'previous 100 rows': 'предыдущие 100 строк',
89 | 'profile': 'профиль',
90 | 'record does not exist': 'запись не найдена',
91 | 'record id': 'id записи',
92 | 'selected': 'выбрано',
93 | 'state': 'состояние',
94 | 'table': 'таблица',
95 | 'unable to parse csv file': 'нечитаемый csv-файл',
96 | }
97 |
--------------------------------------------------------------------------------
/psp2py/languages/sk-sk.py:
--------------------------------------------------------------------------------
1 | # coding: utf8
2 | {
3 | '"update" is an optional expression like "field1=\'newvalue\'". You cannot update or delete the results of a JOIN': '"update" je voliteľný výraz ako "field1=\'newvalue\'". Nemôžete upravovať alebo zmazať výsledky JOINu',
4 | '%Y-%m-%d': '%d.%m.%Y',
5 | '%Y-%m-%d %H:%M:%S': '%d.%m.%Y %H:%M:%S',
6 | '%s rows deleted': '%s zmazaných záznamov',
7 | '%s rows updated': '%s upravených záznamov',
8 | 'Available databases and tables': 'Dostupné databázy a tabuľky',
9 | 'Cannot be empty': 'Nemôže byť prázdne',
10 | 'Check to delete': 'Označiť na zmazanie',
11 | 'Controller': 'Controller',
12 | 'Copyright': 'Copyright',
13 | 'Current request': 'Aktuálna požiadavka',
14 | 'Current response': 'Aktuálna odpoveď',
15 | 'Current session': 'Aktuálne sedenie',
16 | 'DB Model': 'DB Model',
17 | 'Database': 'Databáza',
18 | 'Delete:': 'Zmazať:',
19 | 'Description': 'Popis',
20 | 'Edit': 'Upraviť',
21 | 'Edit Profile': 'Upraviť profil',
22 | 'Edit current record': 'Upraviť aktuálny záznam',
23 | 'First name': 'Krstné meno',
24 | 'Group ID': 'ID skupiny',
25 | 'Hello World': 'Ahoj svet',
26 | 'Import/Export': 'Import/Export',
27 | 'Index': 'Index',
28 | 'Internal State': 'Vnútorný stav',
29 | 'Invalid email': 'Neplatný email',
30 | 'Invalid Query': 'Neplatná otázka',
31 | 'Invalid password': 'Nesprávne heslo',
32 | 'Last name': 'Priezvisko',
33 | 'Layout': 'Layout',
34 | 'Logged in': 'Prihlásený',
35 | 'Logged out': 'Odhlásený',
36 | 'Lost Password': 'Stratené heslo?',
37 | 'Menu Model': 'Menu Model',
38 | 'Name': 'Meno',
39 | 'New Record': 'Nový záznam',
40 | 'New password': 'Nové heslo',
41 | 'No databases in this application': 'V tejto aplikácii nie sú databázy',
42 | 'Old password': 'Staré heslo',
43 | 'Origin': 'Pôvod',
44 | 'Password': 'Heslo',
45 | 'Powered by': 'Powered by',
46 | 'Query:': 'Otázka:',
47 | 'Record ID': 'ID záznamu',
48 | 'Register': 'Zaregistrovať sa',
49 | 'Registration key': 'Registračný kľúč',
50 | 'Remember me (for 30 days)': 'Zapamätaj si ma (na 30 dní)',
51 | 'Reset Password key': 'Nastaviť registračný kľúč',
52 | 'Role': 'Rola',
53 | 'Rows in table': 'riadkov v tabuľke',
54 | 'Rows selected': 'označených riadkov',
55 | 'Submit': 'Odoslať',
56 | 'Stylesheet': 'Stylesheet',
57 | 'Sure you want to delete this object?': 'Ste si istí, že chcete zmazať tento objekt?',
58 | 'Table name': 'Názov tabuľky',
59 | 'The "query" is a condition like "db.table1.field1==\'value\'". Something like "db.table1.field1==db.table2.field2" results in a SQL JOIN.': '"query" je podmienka ako "db.table1.field1==\'value\'". Niečo ako "db.table1.field1==db.table2.field2" má za výsledok SQL JOIN.',
60 | 'The output of the file is a dictionary that was rendered by the view': 'Výstup zo súboru je slovník, ktorý bol zobrazený vo view',
61 | 'This is a copy of the scaffolding application': 'Toto je kópia skeletu aplikácie',
62 | 'Timestamp': 'Časová pečiatka',
63 | 'Update:': 'Upraviť:',
64 | 'Use (...)&(...) for AND, (...)|(...) for OR, and ~(...) for NOT to build more complex queries.': 'Použite (...)&(...) pre AND, (...)|(...) pre OR a ~(...) pre NOT na poskladanie komplexnejších otázok.',
65 | 'User %(id)s Logged-in': 'Používateľ %(id)s prihlásený',
66 | 'User %(id)s Logged-out': 'Používateľ %(id)s odhlásený',
67 | 'User %(id)s Password changed': 'Používateľ %(id)s zmenil heslo',
68 | 'User %(id)s Profile updated': 'Používateľ %(id)s upravil profil',
69 | 'User %(id)s Registered': 'Používateľ %(id)s sa zaregistroval',
70 | 'User ID': 'ID používateľa',
71 | 'Verify Password': 'Zopakujte heslo',
72 | 'View': 'Zobraziť',
73 | 'Welcome to web2py': 'Vitajte vo web2py',
74 | 'Which called the function': 'Ktorý zavolal funkciu',
75 | 'You are successfully running web2py': 'Úspešne ste spustili web2py',
76 | 'You can modify this application and adapt it to your needs': 'Môžete upraviť túto aplikáciu a prispôsobiť ju svojim potrebám',
77 | 'You visited the url': 'Navštívili ste URL',
78 | 'appadmin is disabled because insecure channel': 'appadmin je zakázaný bez zabezpečeného spojenia',
79 | 'cache': 'cache',
80 | 'Online examples': 'pre online príklady kliknite sem',
81 | 'Administrative interface': 'pre administrátorské rozhranie kliknite sem',
82 | 'customize me!': 'prispôsob ma!',
83 | 'data uploaded': 'údaje naplnené',
84 | 'database': 'databáza',
85 | 'database %s select': 'databáza %s výber',
86 | 'db': 'db',
87 | 'design': 'návrh',
88 | 'Documentation': 'Dokumentácia',
89 | 'done!': 'hotovo!',
90 | 'export as csv file': 'exportovať do csv súboru',
91 | 'insert new': 'vložiť nový záznam ',
92 | 'insert new %s': 'vložiť nový záznam %s',
93 | 'invalid request': 'Neplatná požiadavka',
94 | 'located in the file': 'nachádzajúci sa v súbore ',
95 | 'login': 'prihlásiť',
96 | 'logout': 'odhlásiť',
97 | 'lost password?': 'stratené heslo?',
98 | 'new record inserted': 'nový záznam bol vložený',
99 | 'next 100 rows': 'ďalších 100 riadkov',
100 | 'or import from csv file': 'alebo naimportovať z csv súboru',
101 | 'password': 'heslo',
102 | 'previous 100 rows': 'predchádzajúcich 100 riadkov',
103 | 'record': 'záznam',
104 | 'record does not exist': 'záznam neexistuje',
105 | 'record id': 'id záznamu',
106 | 'register': 'registrovať',
107 | 'selected': 'označených',
108 | 'state': 'stav',
109 | 'table': 'tabuľka',
110 | 'unable to parse csv file': 'nedá sa načítať csv súbor',
111 | }
112 |
--------------------------------------------------------------------------------
/psp2py/models/db.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # this file is released under public domain and you can use without limitations
3 |
4 | #########################################################################
5 | ## This scaffolding model makes your app work on Google App Engine too
6 | #########################################################################
7 |
8 | if request.env.web2py_runtime_gae: # if running on Google App Engine
9 | db = DAL('google:datastore') # connect to Google BigTable
10 | # optional DAL('gae://namespace')
11 | session.connect(request, response, db = db) # and store sessions and tickets there
12 | ### or use the following lines to store sessions in Memcache
13 | # from gluon.contrib.memdb import MEMDB
14 | # from google.appengine.api.memcache import Client
15 | # session.connect(request, response, db = MEMDB(Client()))
16 | else: # else use a normal relational database
17 | db = DAL('sqlite://storage.sqlite') # if not, use SQLite or other DB
18 |
19 | # by default give a view/generic.extension to all actions from localhost
20 | # none otherwise. a pattern can be 'controller/function.extension'
21 | response.generic_patterns = ['*'] if request.is_local else []
22 |
23 | #########################################################################
24 | ## Here is sample code if you need for
25 | ## - email capabilities
26 | ## - authentication (registration, login, logout, ... )
27 | ## - authorization (role based authorization)
28 | ## - services (xml, csv, json, xmlrpc, jsonrpc, amf, rss)
29 | ## - crud actions
30 | ## (more options discussed in gluon/tools.py)
31 | #########################################################################
32 |
33 | from gluon.tools import Mail, Auth, Crud, Service, PluginManager, prettydate
34 | mail = Mail() # mailer
35 | auth = Auth(db) # authentication/authorization
36 | crud = Crud(db) # for CRUD helpers using auth
37 | service = Service() # for json, xml, jsonrpc, xmlrpc, amfrpc
38 | plugins = PluginManager() # for configuring plugins
39 |
40 | mail.settings.server = 'logging' or 'smtp.gmail.com:587' # your SMTP server
41 | mail.settings.sender = 'you@gmail.com' # your email
42 | mail.settings.login = 'username:password' # your credentials or None
43 |
44 | auth.settings.hmac_key = 'sha512:89b9d005-19d8-47d3-b182-271fd9c7db8e' # before define_tables()
45 | auth.define_tables() # creates all needed tables
46 | auth.settings.mailer = mail # for user email verification
47 | auth.settings.registration_requires_verification = False
48 | auth.settings.registration_requires_approval = False
49 | auth.messages.verify_email = 'Click on the link http://'+request.env.http_host+URL('default','user',args=['verify_email'])+'/%(key)s to verify your email'
50 | auth.settings.reset_password_requires_verification = True
51 | auth.messages.reset_password = 'Click on the link http://'+request.env.http_host+URL('default','user',args=['reset_password'])+'/%(key)s to reset your password'
52 |
53 | #########################################################################
54 | ## If you need to use OpenID, Facebook, MySpace, Twitter, Linkedin, etc.
55 | ## register with janrain.com, uncomment and customize following
56 | # from gluon.contrib.login_methods.rpx_account import RPXAccount
57 | # auth.settings.actions_disabled = \
58 | # ['register','change_password','request_reset_password']
59 | # auth.settings.login_form = RPXAccount(request, api_key='...',domain='...',
60 | # url = "http://localhost:8000/%s/default/user/login" % request.application)
61 | ## other login methods are in gluon/contrib/login_methods
62 | #########################################################################
63 |
64 | crud.settings.auth = None # =auth to enforce authorization on crud
65 |
66 | #########################################################################
67 | ## Define your tables below (or better in another model file) for example
68 | ##
69 | ## >>> db.define_table('mytable',Field('myfield','string'))
70 | ##
71 | ## Fields can be 'string','text','password','integer','double','boolean'
72 | ## 'date','time','datetime','blob','upload', 'reference TABLENAME'
73 | ## There is an implicit 'id integer autoincrement' field
74 | ## Consult manual for more options, validators, etc.
75 | ##
76 | ## More API examples for controllers:
77 | ##
78 | ## >>> db.mytable.insert(myfield='value')
79 | ## >>> rows=db(db.mytable.myfield=='value').select(db.mytable.ALL)
80 | ## >>> for row in rows: print row.id, row.myfield
81 | #########################################################################
82 |
--------------------------------------------------------------------------------
/psp2py/models/db_psp.py:
--------------------------------------------------------------------------------
1 | # coding: utf8
2 |
3 | PSP_PHASES = ["planning", "design", "code", "review", "compile", "test", "postmortem"]
4 | PSP_TIMES = ["plan", "actual", "interruption"]
5 |
6 | PSP_DEFECT_TYPES = {10: 'Documentation', 20: 'Syntax', 30: 'Coding standard',
7 | 40: 'Assignment', 50: 'Interface', 60: 'Checking', 70: 'Data',
8 | 80: 'Function', 90: 'System', 100: 'Enviroment'}
9 |
10 | # function/class type classification for easier reuse and estimation:
11 | PSP_CATEGORIES = ["module", "model", "controller", "view"]
12 | PSP_SIZES = ["very small", "small", "medium", "large", "very large"]
13 |
14 | # Personal Software Process tables:
15 |
16 | db.define_table("psp_project",
17 | Field("project_id", "id"),
18 | Field("name", "string"),
19 | Field("description", "string"),
20 | Field("requeriments", "text"),
21 | Field("testing", "text"),
22 | Field("user_id", db.auth_user),
23 | #Field("instructor_id", db.auth_user),
24 | Field("started", "date"),
25 | Field("completed", "date"),
26 | Field("planned_loc", "integer", comment="Total new & changed (estimated program size)"),
27 | Field("actual_loc", "integer", comment="Total new & changed (measured program size)"),
28 | Field("planned_time", "double",
29 | comment=T("Original projected development time")),
30 | Field("time_lpi", "double", label=T("Time LPI"),
31 | comment="Total Time Lower Prediction Interval"),
32 | Field("time_upi", "double", label=T("Time UPI"),
33 | comment="Total Time Upper Prediction Interval"),
34 | format="%(name)s",
35 | )
36 |
37 |
38 | db.define_table("psp_time_summary",
39 | Field("id", "id"),
40 | Field("project_id", db.psp_project),
41 | Field("phase", "string", requires=IS_IN_SET(PSP_PHASES)),
42 | Field("plan", "integer"),
43 | Field("actual", "integer"),
44 | Field("off_task", "integer"),
45 | Field("interruption", "integer"),
46 | )
47 |
48 | db.define_table("psp_comment",
49 | Field("id", "id"),
50 | Field("project_id", db.psp_project),
51 | Field("phase", "string", requires=IS_IN_SET(PSP_PHASES)),
52 | Field("message", "text"),
53 | Field("delta", "integer"),
54 | )
55 |
56 | db.define_table("psp_defect",
57 | Field("id", "id"),
58 | Field("project_id", db.psp_project),
59 | Field("number", "integer"),
60 | Field("summary", "text"),
61 | Field("description", "text"),
62 | Field("date", "date"),
63 | Field("type", "string", requires=IS_IN_SET(PSP_DEFECT_TYPES)),
64 | Field("inject_phase", "string", requires=IS_IN_SET(PSP_PHASES)),
65 | Field("remove_phase", "string", requires=IS_IN_SET(PSP_PHASES)),
66 | Field("fix_time", "integer"),
67 | Field("fix_defect", "integer"),
68 | Field("filename", "string"),
69 | Field("lineno", "integer"),
70 | Field("offset", "integer"),
71 | Field("uuid", "string"),
72 | )
73 |
74 |
75 | def pretty_time(counter):
76 | "return formatted string of a time count in seconds (days/hours/min/seg)"
77 | # find time unit and convert to it
78 | if counter is None:
79 | return ""
80 | counter = int(counter)
81 | for factor, unit in ((1., 's'), (60., 'm'), (3600., 'h')):
82 | if counter < (60 * factor):
83 | break
84 | # only print fraction if it is not an integer result
85 | if counter % factor:
86 | return "%0.2f %s" % (counter/factor, unit)
87 | else:
88 | return "%d %s" % (counter/factor, unit)
89 |
90 | db.psp_time_summary.plan.represent = pretty_time
91 | db.psp_time_summary.actual.represent = pretty_time
92 | db.psp_time_summary.interruption.represent = pretty_time
93 | db.psp_time_summary.off_task.represent = pretty_time
94 | db.psp_defect.fix_time.represent = pretty_time
95 | db.psp_project.planned_time.represent = lambda x: x and ("%0.2f hs" % x) or ''
96 | db.psp_project.time_upi.represent = lambda x: x and ("%0.2f hs" % x) or ''
97 | db.psp_project.time_lpi.represent = lambda x: x and ("%0.2f hs" % x) or ''
98 |
99 |
100 | db.define_table("psp_reuse_library",
101 | Field("id", "id"),
102 | Field("project_id", db.psp_project),
103 | Field("filename", "string"),
104 | Field("class_name", "string"),
105 | Field("function_name", "string"),
106 | Field("category", "string",
107 | requires=IS_IN_SET(PSP_CATEGORIES),
108 | default="module"),
109 | Field("lineno", "integer"),
110 | Field("loc", "integer"),
111 | )
112 |
--------------------------------------------------------------------------------
/psp2py/models/db_wiki.py:
--------------------------------------------------------------------------------
1 | # coding: utf8
2 |
3 | db.define_table("wiki",
4 | Field("page", requires=IS_NOT_EMPTY()),
5 | Field("title", requires=IS_NOT_EMPTY()),
6 | Field("text", "text",
7 | requires=IS_NOT_EMPTY(),
8 | comment=XML(A(str(T('MARKMIN format')),_href='http://web2py.com/examples/static/markmin.html')),
9 | ),
10 | )
11 |
--------------------------------------------------------------------------------
/psp2py/models/menu.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # this file is released under public domain and you can use without limitations
3 | #########################################################################
4 | ## Customize your APP title, subtitle and menus here
5 | #########################################################################
6 |
7 | response.title = request.application
8 | response.subtitle = T('customize me!')
9 |
10 | #http://dev.w3.org/html5/markup/meta.name.html
11 | response.meta.author = 'Mariano Reingart'
12 | response.meta.description = 'Personal Software Process support webapp'
13 | response.meta.keywords = 'web2py, python, framework, psp'
14 | response.meta.generator = 'Web2py Enterprise Framework'
15 | response.meta.copyright = 'Copyright 2011'
16 |
17 |
18 | ##########################################
19 | ## this is the main application menu
20 | ## add/remove items as required
21 | ##########################################
22 |
23 | response.menu = [
24 | (T('Home'), False, URL('default','index'), []),
25 | (T('Projects'), False, URL('projects','index'), [
26 | (T('Search'), False, URL('projects','search'), []),
27 | (T('Create'), False, URL('projects','create'), []),
28 | ]),
29 | (T('PROBE'), False, URL('probe','index'), [
30 | (T('Categorize'), False, URL('probe','categorize'), []),
31 | (T('Reuse Library'), False, URL('probe','library'), []),
32 | (T('Size Log-Normal Distribution'), False, URL('probe','normal_distribution.png'), []),
33 | ]),
34 | (T('Estimate'), False, URL('estimate','index'), [
35 | (T('Correlation'), False, URL('estimate','correlation'), []),
36 | (T('Significance'), False, URL('estimate','significance'), []),
37 | (T('Time in phase'), False, URL('estimate','time_in_phase'), []),
38 | (T('Size vs Time Linear Regression'), False, URL('estimate','linear_regression.png'), []),
39 | ]),
40 | (T('Reports'), False, URL('reports','index'), [
41 | (T('Projects'), False, URL('reports','projects'), []),
42 | (T('Defects'), False, URL('reports','defects'), [
43 | (T('Pareto Distribution'), False, URL('reports','pareto_distribution.png'), []),
44 | (T('Average Fix Times'), False, URL('reports','average_fix_time.png'), []),
45 | ]),
46 | ]),
47 | (T('Wiki'), False, URL('wiki','index'), []),
48 | ]
49 |
--------------------------------------------------------------------------------
/psp2py/modules/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/reingart/rad2py/e4802ade132d569225e8be7eca830d2f888aa5f9/psp2py/modules/__init__.py
--------------------------------------------------------------------------------
/psp2py/modules/draws.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | def draw_linear_regression(x, y, x_label, y_label, title, body):
4 | "Plot a linear regression chart"
5 | # x and y are matplotlib pylab arrays, body is a StringIO
6 | import pylab
7 | import matplotlib
8 | # clear graph
9 | matplotlib.pyplot.clf()
10 | matplotlib.use('Agg')
11 | #nse = 0.3 * pylab.randn(len(x))
12 | #y = 2 + 3 * x + nse
13 | # the best fit line from polyfit ; you can do arbitrary order
14 | # polynomials but here we take advantage of a line being a first order
15 | # polynomial
16 | m, b = pylab.polyfit( x , y , 1 )
17 | # plot the data with blue circles and the best fit with a thick
18 | # solid black line
19 | pylab.plot(x, y, 'bo ', x, m * x+b , '-k' , linewidth=2)
20 | pylab.ylabel(y_label)
21 | pylab.xlabel(x_label)
22 | pylab.grid(True)
23 | pylab.title(title)
24 | pylab.savefig(body)
25 | return body.getvalue()
26 |
27 |
28 | def draw_normal_histogram(x, bins, y_label='', x_label='', title="", body=""):
29 | "Plot a histogram chart"
30 | # x are matplotlib pylab arrays, body is a StringIO
31 | import pylab
32 | import matplotlib
33 | # clear graph
34 | matplotlib.pyplot.clf()
35 | matplotlib.use('Agg')
36 | n, bins1, patches = pylab.hist(x, bins, histtype='bar', facecolor='green', alpha=0.75)
37 | #pylab.setp(patches, 'facecolor', 'g', 'alpha', 0.75)
38 | pylab.ylabel(y_label)
39 | pylab.xlabel(x_label)
40 | # add a line showing the expected distribution
41 | mu = pylab.mean(x)
42 | sigma = pylab.std(x)
43 | y = pylab.normpdf(bins, mu, sigma)
44 | l = pylab.plot(bins, y, 'k--', linewidth=1.5)
45 |
46 | pylab.title(title)
47 |
48 | pylab.grid(True)
49 | pylab.savefig(body)
50 | return body.getvalue()
51 |
52 |
53 | def draw_barchart(values, title, y_label, x_label, x_tick_labels, autolabel=False, text="", stacked=True, body=None):
54 | #!/usr/bin/env python
55 | # a bar plot with errorbars
56 | import pylab
57 | import matplotlib
58 | import numpy as np
59 | import matplotlib.pyplot as plt
60 |
61 |
62 | rects = []
63 | labels = []
64 | bottom = None # for stacked bars
65 |
66 | fig = plt.figure()
67 | ax = fig.add_subplot(111)
68 | ind = np.arange(len(values[0][3])) # the x locations for the groups
69 |
70 | for i, (label, width, color, heights) in enumerate(values):
71 | labels.append(label)
72 | w = not stacked and width or 0
73 | rects.append(ax.bar(ind+w*i, heights, width, bottom=bottom, color=color))
74 | if stacked:
75 | bottom = [x + i for x, i in zip(bottom or [0]*len(heights), heights)]
76 |
77 | # add some
78 | ax.set_ylabel(y_label)
79 | ax.set_xlabel(x_label)
80 | ax.set_title(title)
81 | ax.set_xticks(ind+width/2.)
82 | ax.set_xticklabels( x_tick_labels )
83 |
84 | ax.legend( [r[0] for r in rects], labels, loc="best")
85 |
86 | def draw_autolabel(rects):
87 | # attach some text labels
88 | for rect in rects:
89 | height = rect.get_height()
90 | ax.text(rect.get_x()+rect.get_width()/2., 1.05*height, '%d'%int(height),
91 | ha='center', va='bottom')
92 |
93 | if autolabel:
94 | for rect in rects:
95 | draw_autolabel(rect)
96 |
97 | pylab.grid(True)
98 |
99 | if text:
100 | plt.text(7.75, 27, text, size=12, rotation=0.,
101 | ha="center", va="center",
102 | bbox = dict(boxstyle="round",
103 | ec='black',
104 | fc='w',
105 | )
106 | )
107 | pylab.savefig(body)
108 | return body.getvalue()
109 |
110 |
111 | #Some simple functions to generate colours.
112 | def pastel(colour, weight=2.4):
113 | """ Convert colour into a nice pastel shade"""
114 | from matplotlib.colors import colorConverter
115 | import numpy as np
116 | rgb = np.asarray(colorConverter.to_rgb(colour))
117 | # scale colour
118 | maxc = max(rgb)
119 | if maxc < 1.0 and maxc > 0:
120 | # scale colour
121 | scale = 1.0 / maxc
122 | rgb = rgb * scale
123 | # now decrease saturation
124 | total = sum(rgb)
125 | slack = 0
126 | for x in rgb:
127 | slack += 1.0 - x
128 |
129 | # want to increase weight from total to weight
130 | # pick x s.t. slack * x == weight - total
131 | # x = (weight - total) / slack
132 | x = (weight - total) / slack
133 |
134 | rgb = [c + (x * (1.0-c)) for c in rgb]
135 |
136 | return rgb
137 |
138 | def get_colours(n):
139 | """ Return n pastel colours. """
140 | import numpy as np
141 | import matplotlib
142 | base = np.asarray([[1,0,0], [0,1,0], [0,0,1]])
143 |
144 | if n <= 3:
145 | return base[0:n]
146 |
147 | # how many new colours to we need to insert between
148 | # red and green and between green and blue?
149 | needed = (((n - 3) + 1) / 2, (n - 3) / 2)
150 |
151 | colours = []
152 | for start in (0, 1):
153 | for x in np.linspace(0, 1, needed[start]+2):
154 | colours.append((base[start] * (1.0 - x)) +
155 | (base[start+1] * x))
156 |
157 | return [pastel(c) for c in colours[0:n]]
158 |
--------------------------------------------------------------------------------
/psp2py/modules/integration.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | from math import e, pi, sqrt
4 |
5 |
6 | def compute_integral(f, x_low, x_high, w, n):
7 | "Compute the numerical approximation of a definite integral"
8 | # composite simpson rule
9 | term1 = f(x_low)
10 | term2 = 0
11 | for j in xrange(1, n, 2):
12 | term2 += f(x_low + j * w)
13 | term3 = 0
14 | for j in xrange(2, n, 2):
15 | term3 += f(x_low + j * w)
16 | term4 = f(x_high)
17 | y = w / 3.0 * (term1 + 4 * term2 + 2 * term3 + term4)
18 |
19 | return y
20 |
21 |
22 | def simpson_rule_integrate(f, x_low, x_high, error=0.00001):
23 | # 1. identify the upper and lower limits of the numerical integration
24 | if x_high < 0 and x_low == float("-infinity"):
25 | x_high = abs(x_high)
26 | x_low = 0
27 | p = -0.5
28 | elif x_low == float("-infinity"):
29 | x_low = 0
30 | p = 0.5
31 | else:
32 | p = 0
33 | # 2. select an initial number N and old result
34 | n = 20
35 | old_y = 0
36 | while True:
37 | # 3. divide the range to get the segment width
38 | w = (x_high - x_low) / n
39 | # 4. compute the numerical integration approximation
40 | y = compute_integral(f, x_low, x_high, w, n)
41 | # 5. compare with the old result if error is permisible
42 | if abs(y - old_y) <= error:
43 | if p >= 0:
44 | return p + y
45 | else:
46 | return - p - y
47 | old_y = y
48 | # 6. double N
49 | n = 2 * n
50 | # 7. repeat ...
51 |
52 |
53 | def factorial(x, step=1):
54 | "Calculate integer or float factorial (for gamma function, step=2)"
55 | if x > step:
56 | return x * factorial(x - step, step) / step
57 | return x / step
58 |
59 |
60 | def gamma(n, d=2):
61 | "Calculate gamma function value for a fraction (numerator & denominator)"
62 | # WARNING: only tested for d=2 !
63 | if n % 2 != 0 and d == 2:
64 | return factorial(n - 2, step=2.0) * sqrt(pi)
65 | else:
66 | i = n / d
67 | return factorial(i - 1)
68 |
69 |
70 | def f_normal_distribution(u):
71 | return (1 / (2 * pi) ** (0.5)) * e ** ((- u ** 2) / 2)
72 |
73 |
74 | def f_student_t_distribution(n):
75 | # student t distribution
76 | # n = degrees of freedom
77 | k = gamma(n + 1, 2) / (sqrt(n*pi) * gamma(n, 2))
78 | return lambda u: k * (1 + (u ** 2) / float(n)) ** (- (n +1) / 2.0)
79 |
--------------------------------------------------------------------------------
/psp2py/modules/statistics.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # coding: utf8
3 |
4 | import math
5 | from integration import f_student_t_distribution, simpson_rule_integrate
6 |
7 |
8 | def mean(values):
9 | "Calculate the average of the numbers given"
10 | return sum(values) / float(len(values))
11 |
12 |
13 | def calc_correlation(x_values, y_values):
14 | "Calculate strength of a relationship between two sets of data"
15 | # calculate aux variables
16 | n = len(x_values)
17 | sum_xy = sum([(x_values[i] * y_values[i]) for i in range(n)])
18 | sum_x = sum([(x_values[i]) for i in range(n)])
19 | sum_y = sum([(y_values[i]) for i in range(n)])
20 | sum_x2 = sum([(x_values[i] ** 2) for i in range(n)])
21 | sum_y2 = sum([(y_values[i] ** 2) for i in range(n)])
22 |
23 | # calculate corelation
24 | r = (n * sum_xy - (sum_x * sum_y)) / math.sqrt((n * sum_x2 - sum_x ** 2) * (n * sum_y2 - sum_y ** 2))
25 |
26 | return r
27 |
28 |
29 | def calc_significance(x_values, y_values):
30 | "Calculate the significance (likelihood of two set of data correlation)"
31 | n = len (x_values)
32 | r = calc_correlation(x_values, y_values)
33 | r2 = r**2
34 | t = abs(r)*math.sqrt(n - 2)/math.sqrt(1 - r**2)
35 | return t, r2, n
36 |
37 |
38 | def calc_linear_regression(x_values, y_values):
39 | "Calculate the linear regression parameters for a set of n values"
40 |
41 | # calculate aux variables
42 | x_avg = mean(x_values)
43 | y_avg = mean(y_values)
44 | n = len(x_values)
45 | sum_xy = sum([(x_values[i] * y_values[i]) for i in range(n)])
46 | sum_x2 = sum([(x_values[i] ** 2) for i in range(n)])
47 |
48 | # calculate regression coefficients
49 | b1 = (sum_xy - (n * x_avg * y_avg)) / (sum_x2 - n * (x_avg ** 2))
50 | b0 = y_avg - b1 * x_avg
51 |
52 | return (b0, b1)
53 |
54 |
55 | def calc_standard_deviation(values):
56 | "Calculate the standard deviation of a list of number values"
57 | x_avg = mean(values)
58 | n = len(values)
59 | sd = math.sqrt(sum([(x_i - x_avg)**2
60 | for x_i in values]) / float(n))
61 | return sd, x_avg
62 |
63 | def calc_student_t_probability(x, n):
64 | "Integrate t distribution from -infinity to x with n degrees of freedom"
65 | inf = float("infinity")
66 | p = simpson_rule_integrate(f_student_t_distribution(n), -inf, x)
67 | return p
68 |
69 | def calc_double_sided_student_t_probability(t, n):
70 | "Calculate the p-value using a double sided student t distribution"
71 | # integrate a finite area from the origin to t
72 | p_aux = simpson_rule_integrate(f_student_t_distribution(n), 0, t)
73 | # return the area of the two tails of the distribution (symmetrical)
74 | return (0.5 - p_aux) * 2
75 |
76 | def calc_double_sided_student_t_value(p, n):
77 | "Calculate the t-value using a double sided student t distribution"
78 | # replaces table lookup, thanks to http://statpages.org/pdfs.html
79 | v = dv = 0.5
80 | t = 0
81 | while dv > 0.000001:
82 | t = 1 / v - 1
83 | dv = dv / 2
84 | if calc_double_sided_student_t_probability(t, n) > p:
85 | v = v - dv
86 | else:
87 | v = v + dv
88 | return t
89 |
90 |
91 | def calc_variance(x_values, y_values, b0, b1):
92 | "Calculate the mean square deviation of the linear regeression line"
93 | # take the variance from the regression line instead of the data average
94 | sum_aux = sum([(y - b0 - b1 * x) ** 2 for x, y in zip(x_values, y_values)])
95 | n = float(len(x_values))
96 | return (1 / (n - 2.0)) * sum_aux
97 |
98 |
99 | def calc_prediction_interval(x_values, y_values, x_k, y_k, alpha):
100 | """Calculate the linear regression parameters for a set of n values
101 | then calculate the upper and lower prediction interval
102 |
103 | """
104 |
105 | # calculate aux variables
106 | x_avg = mean(x_values)
107 | y_avg = mean(y_values)
108 | n = len(x_values)
109 | sum_xy = sum([(x_values[i] * y_values[i]) for i in range(n)])
110 | sum_x2 = sum([(x_values[i] ** 2) for i in range(n)])
111 |
112 | # calculate regression coefficients
113 | b1 = (sum_xy - (n * x_avg * y_avg)) / (sum_x2 - n * (x_avg ** 2))
114 | b0 = y_avg - b1 * x_avg
115 |
116 | # calculate the t-value for the given alpha p-value
117 | t = calc_double_sided_student_t_value(1 - alpha, n - 2)
118 |
119 | # calculate the standard deviation
120 | sigma = math.sqrt(calc_variance(x_values, y_values, b0, b1))
121 |
122 | # calculate the range
123 | sum_xi_xavg = sum([(x - x_avg) ** 2 for x in x_values], 0.0)
124 | aux = 1 + (1 / float(n)) + ((x_k - x_avg) ** 2) / sum_xi_xavg
125 | p_range = t * sigma * math.sqrt(aux)
126 |
127 | # combine the range with the x_k projection:
128 | return b0, b1, p_range, y_k + p_range, y_k - p_range, t
129 |
--------------------------------------------------------------------------------
/psp2py/static/css/calendar.css:
--------------------------------------------------------------------------------
1 | .calendar{z-index:99;position:relative;display:none;border-top:2px solid #fff;border-right:2px solid #000;border-bottom:2px solid #000;border-left:2px solid #fff;font-size:11px;color:#000;cursor:default;background:#d4d0c8;font-family:tahoma,verdana,sans-serif;}.calendar table{border-top:1px solid #000;border-right:1px solid #fff;border-bottom:1px solid #fff;border-left:1px solid #000;font-size:11px;color:#000;cursor:default;background:#d4d0c8;font-family:tahoma,verdana,sans-serif;}.calendar .button{text-align:center;padding:1px;border-top:1px solid #fff;border-right:1px solid #000;border-bottom:1px solid #000;border-left:1px solid #fff;}.calendar .nav{background:transparent}.calendar thead .title{font-weight:bold;padding:1px;border:1px solid #000;background:#848078;color:#fff;text-align:center;}.calendar thead .name{border-bottom:1px solid #000;padding:2px;text-align:center;background:#f4f0e8;}.calendar thead .weekend{color:#f00;}.calendar thead .hilite{border-top:2px solid #fff;border-right:2px solid #000;border-bottom:2px solid #000;border-left:2px solid #fff;padding:0;background-color:#e4e0d8;}.calendar thead .active{padding:2px 0 0 2px;border-top:1px solid #000;border-right:1px solid #fff;border-bottom:1px solid #fff;border-left:1px solid #000;background-color:#c4c0b8;}.calendar tbody .day{width:2em;text-align:right;padding:2px 4px 2px 2px;}.calendar tbody .day.othermonth{font-size:80%;color:#aaa;}.calendar tbody .day.othermonth.oweekend{color:#faa;}.calendar table .wn{padding:2px 3px 2px 2px;border-right:1px solid #000;background:#f4f0e8;}.calendar tbody .rowhilite td{background:#e4e0d8;}.calendar tbody .rowhilite td.wn{background:#d4d0c8;}.calendar tbody td.hilite{padding:1px 3px 1px 1px;border-top:1px solid #fff;border-right:1px solid #000;border-bottom:1px solid #000;border-left:1px solid #fff;}.calendar tbody td.active{padding:2px 2px 0 2px;border-top:1px solid #000;border-right:1px solid #fff;border-bottom:1px solid #fff;border-left:1px solid #000;}.calendar tbody td.selected{font-weight:bold;border-top:1px solid #000;border-right:1px solid #fff;border-bottom:1px solid #fff;border-left:1px solid #000;padding:2px 2px 0 2px;background:#e4e0d8;}.calendar tbody td.weekend{color:#f00;}.calendar tbody td.today{font-weight:bold;color:#00f;}.calendar tbody .disabled{color:#999;}.calendar tbody .emptycell{visibility:hidden;}.calendar tbody .emptyrow{display:none;}.calendar tfoot .ttip{background:#f4f0e8;padding:1px;border:1px solid #000;background:#848078;color:#fff;text-align:center;}.calendar tfoot .hilite{border-top:1px solid #fff;border-right:1px solid #000;border-bottom:1px solid #000;border-left:1px solid #fff;padding:1px;background:#e4e0d8;}.calendar tfoot .active{padding:2px 0 0 2px;border-top:1px solid #000;border-right:1px solid #fff;border-bottom:1px solid #fff;border-left:1px solid #000;}.calendar .combo{position:absolute;display:none;width:4em;top:0;left:0;cursor:default;border-top:1px solid #fff;border-right:1px solid #000;border-bottom:1px solid #000;border-left:1px solid #fff;background:#e4e0d8;font-size:90%;padding:1px;z-index:100;}.calendar .combo .label,.calendar .combo .label-IEfix{text-align:center;padding:1px;}.calendar .combo .label-IEfix{width:4em;}.calendar .combo .active{background:#c4c0b8;padding:0;border-top:1px solid #000;border-right:1px solid #fff;border-bottom:1px solid #fff;border-left:1px solid #000;}.calendar .combo .hilite{background:#048;color:#fea;}.calendar td.time{border-top:1px solid #000;padding:1px 0;text-align:center;background-color:#f4f0e8;}.calendar td.time .hour,.calendar td.time .minute,.calendar td.time .ampm{padding:0 3px 0 4px;border:1px solid #889;font-weight:bold;background-color:#fff;}.calendar td.time .ampm{text-align:center;}.calendar td.time .colon{padding:0 2px 0 3px;font-weight:bold;}.calendar td.time span.hilite{border-color:#000;background-color:#766;color:#fff;}.calendar td.time span.active{border-color:#f00;background-color:#000;color:#0f0;}#CP_hourcont{z-index:99;padding:0;position:absolute;border:1px dashed #666;background-color:#eee;display:none;}#CP_minutecont{z-index:99;background-color:#ddd;padding:1px;position:absolute;width:45px;display:none;}.floatleft{float:left;}.CP_hour{z-index:99;padding:1px;font-family:Arial,Helvetica,sans-serif;font-size:9px;white-space:nowrap;cursor:pointer;width:35px;}.CP_minute{z-index:99;padding:1px;font-family:Arial,Helvetica,sans-serif;font-size:9px;white-space:nowrap;cursor:pointer;width:auto;}.CP_over{background-color:#fff;z-index:99}
--------------------------------------------------------------------------------
/psp2py/static/css/handheld.css:
--------------------------------------------------------------------------------
1 |
2 | * {
3 | float: none; /* Screens are not big enough to account for floats */
4 | font-size: 80%; /* Slightly reducing font size to reduce need to scroll */
5 | background: #fff; /* As much contrast as possible */
6 | color: #000;
7 | }
--------------------------------------------------------------------------------
/psp2py/static/css/superfish-navbar.css:
--------------------------------------------------------------------------------
1 |
2 | /*** adding the class sf-navbar in addition to sf-menu creates an all-horizontal nav-bar menu ***/
3 | .sf-navbar {
4 | background: #BDD2FF;
5 | height: 2.5em;
6 | padding-bottom: 2.5em;
7 | position: relative;
8 | }
9 | .sf-navbar li {
10 | background: #AABDE6;
11 | position: static;
12 | }
13 | .sf-navbar a {
14 | border-top: none;
15 | }
16 | .sf-navbar li ul {
17 | width: 44em; /*IE6 soils itself without this*/
18 | }
19 | .sf-navbar li li {
20 | background: #BDD2FF;
21 | position: relative;
22 | }
23 | .sf-navbar li li ul {
24 | width: 13em;
25 | }
26 | .sf-navbar li li li {
27 | width: 100%;
28 | }
29 | .sf-navbar ul li {
30 | width: auto;
31 | float: left;
32 | }
33 | .sf-navbar a, .sf-navbar a:visited {
34 | border: none;
35 | }
36 | .sf-navbar li.current {
37 | background: #BDD2FF;
38 | }
39 | .sf-navbar li:hover,
40 | .sf-navbar li.sfHover,
41 | .sf-navbar li li.current,
42 | .sf-navbar a:focus, .sf-navbar a:hover, .sf-navbar a:active {
43 | background: #BDD2FF;
44 | }
45 | .sf-navbar ul li:hover,
46 | .sf-navbar ul li.sfHover,
47 | ul.sf-navbar ul li:hover li,
48 | ul.sf-navbar ul li.sfHover li,
49 | .sf-navbar ul a:focus, .sf-navbar ul a:hover, .sf-navbar ul a:active {
50 | background: #D1DFFF;
51 | }
52 | ul.sf-navbar li li li:hover,
53 | ul.sf-navbar li li li.sfHover,
54 | .sf-navbar li li.current li.current,
55 | .sf-navbar ul li li a:focus, .sf-navbar ul li li a:hover, .sf-navbar ul li li a:active {
56 | background: #E6EEFF;
57 | }
58 | ul.sf-navbar .current ul,
59 | ul.sf-navbar ul li:hover ul,
60 | ul.sf-navbar ul li.sfHover ul {
61 | left: 0;
62 | top: 2.5em; /* match top ul list item height */
63 | }
64 | ul.sf-navbar .current ul ul {
65 | top: -999em;
66 | }
67 |
68 | .sf-navbar li li.current > a {
69 | font-weight: bold;
70 | }
71 |
72 | /*** point all arrows down ***/
73 | /* point right for anchors in subs */
74 | .sf-navbar ul .sf-sub-indicator { background-position: -10px -100px; }
75 | .sf-navbar ul a > .sf-sub-indicator { background-position: 0 -100px; }
76 | /* apply hovers to modern browsers */
77 | .sf-navbar ul a:focus > .sf-sub-indicator,
78 | .sf-navbar ul a:hover > .sf-sub-indicator,
79 | .sf-navbar ul a:active > .sf-sub-indicator,
80 | .sf-navbar ul li:hover > a > .sf-sub-indicator,
81 | .sf-navbar ul li.sfHover > a > .sf-sub-indicator {
82 | background-position: -10px -100px; /* arrow hovers for modern browsers*/
83 | }
84 |
85 | /*** remove shadow on first submenu ***/
86 | .sf-navbar > li > ul {
87 | background: transparent;
88 | padding: 0;
89 | -moz-border-radius-bottomleft: 0;
90 | -moz-border-radius-topright: 0;
91 | -webkit-border-top-right-radius: 0;
92 | -webkit-border-bottom-left-radius: 0;
93 | }
--------------------------------------------------------------------------------
/psp2py/static/css/superfish-vertical.css:
--------------------------------------------------------------------------------
1 | /*** adding sf-vertical in addition to sf-menu creates a vertical menu ***/
2 | .sf-vertical, .sf-vertical li {
3 | width: 10em;
4 | }
5 | /* this lacks ul at the start of the selector, so the styles from the main CSS file override it where needed */
6 | .sf-vertical li:hover ul,
7 | .sf-vertical li.sfHover ul {
8 | left: 10em; /* match ul width */
9 | top: 0;
10 | }
11 |
12 | /*** alter arrow directions ***/
13 | .sf-vertical .sf-sub-indicator { background-position: -10px 0; } /* IE6 gets solid image only */
14 | .sf-vertical a > .sf-sub-indicator { background-position: 0 0; } /* use translucent arrow for modern browsers*/
15 |
16 | /* hover arrow direction for modern browsers*/
17 | .sf-vertical a:focus > .sf-sub-indicator,
18 | .sf-vertical a:hover > .sf-sub-indicator,
19 | .sf-vertical a:active > .sf-sub-indicator,
20 | .sf-vertical li:hover > a > .sf-sub-indicator,
21 | .sf-vertical li.sfHover > a > .sf-sub-indicator {
22 | background-position: -10px 0; /* arrow hovers for modern browsers*/
23 | }
--------------------------------------------------------------------------------
/psp2py/static/css/superfish.css:
--------------------------------------------------------------------------------
1 |
2 | /*** ESSENTIAL STYLES ***/
3 | .sf-menu, .sf-menu * {
4 | margin: 0;
5 | padding: 0;
6 | list-style: none;
7 | }
8 | .sf-menu {
9 | line-height: 1.0;
10 | }
11 | .sf-menu ul {
12 | position: absolute;
13 | top: -999em;
14 | width: 10em; /* left offset of submenus need to match (see below) */
15 | }
16 | .sf-menu ul li {
17 | width: 100%;
18 | }
19 | .sf-menu li:hover {
20 | visibility: inherit; /* fixes IE7 'sticky bug' */
21 | }
22 | .sf-menu li {
23 | float: left;
24 | position: relative;
25 | }
26 | .sf-menu a {
27 | display: block;
28 | position: relative;
29 | }
30 | .sf-menu li:hover ul,
31 | .sf-menu li.sfHover ul {
32 | left: 0;
33 | top: 2.5em; /* match top ul list item height */
34 | z-index: 99;
35 | }
36 | ul.sf-menu li:hover li ul,
37 | ul.sf-menu li.sfHover li ul {
38 | top: -999em;
39 | }
40 | ul.sf-menu li li:hover ul,
41 | ul.sf-menu li li.sfHover ul {
42 | left: 10em; /* match ul width */
43 | top: 0;
44 | }
45 | ul.sf-menu li li:hover li ul,
46 | ul.sf-menu li li.sfHover li ul {
47 | top: -999em;
48 | }
49 | ul.sf-menu li li li:hover ul,
50 | ul.sf-menu li li li.sfHover ul {
51 | left: 10em; /* match ul width */
52 | top: 0;
53 | }
54 |
55 | /*** DEMO SKIN ***/
56 | .sf-menu {
57 | float: left;
58 | /*margin-bottom: 1em;*/
59 | }
60 | .sf-menu a {
61 | border-left: 1px solid #fff;
62 | /*border-top: 1px solid #CFDEFF;*/
63 | padding: .75em 1em;
64 | text-decoration:none;
65 | }
66 | .sf-menu a, .sf-menu a:visited { /* visited pseudo selector so IE6 applies text colour*/
67 | color: #275b90;/*#13a;*/
68 | }
69 | .sf-menu li {
70 | background: #dadada;/*#BDD2FF;*/
71 | }
72 | .sf-menu li li {
73 | background: #AABDE6;
74 | }
75 | .sf-menu li li a {
76 | /*color: #13a;*/
77 | }
78 | .sf-menu li li li {
79 | background: #9AAEDB;
80 | }
81 | .sf-menu li:hover, .sf-menu li.sfHover,
82 | .sf-menu a:focus, .sf-menu a:hover, .sf-menu a:active {
83 | background: #CFDEFF;
84 | outline: 0;
85 | }
86 |
87 | /*** arrows **/
88 | .sf-menu a.sf-with-ul {
89 | padding-right: 2.25em;
90 | min-width: 1px; /* trigger IE7 hasLayout so spans position accurately */
91 | }
92 | .sf-sub-indicator {
93 | position: absolute;
94 | display: block;
95 | right: .75em;
96 | top: 1.05em; /* IE6 only */
97 | width: 10px;
98 | height: 10px;
99 | text-indent: -999em;
100 | overflow: hidden;
101 | background: url('../images/arrows-ffffff.png') no-repeat -10px -100px; /* 8-bit indexed alpha png. IE6 gets solid image only */
102 | }
103 | a > .sf-sub-indicator { /* give all except IE6 the correct values */
104 | top: .8em;
105 | background-position: 0 -100px; /* use translucent arrow for modern browsers*/
106 | }
107 | /* apply hovers to modern browsers */
108 | a:focus > .sf-sub-indicator,
109 | a:hover > .sf-sub-indicator,
110 | a:active > .sf-sub-indicator,
111 | li:hover > a > .sf-sub-indicator,
112 | li.sfHover > a > .sf-sub-indicator {
113 | background-position: -10px -100px; /* arrow hovers for modern browsers*/
114 | }
115 |
116 | /* point right for anchors in subs */
117 | .sf-menu ul .sf-sub-indicator { background-position: -10px 0; }
118 | .sf-menu ul a > .sf-sub-indicator { background-position: 0 0; }
119 | /* apply hovers to modern browsers */
120 | .sf-menu ul a:focus > .sf-sub-indicator,
121 | .sf-menu ul a:hover > .sf-sub-indicator,
122 | .sf-menu ul a:active > .sf-sub-indicator,
123 | .sf-menu ul li:hover > a > .sf-sub-indicator,
124 | .sf-menu ul li.sfHover > a > .sf-sub-indicator {
125 | background-position: -10px 0; /* arrow hovers for modern browsers*/
126 | }
127 |
128 | /*** shadows for all but IE6 ***/
129 | .sf-shadow ul {
130 | background: url('../images/shadow.png') no-repeat bottom right;
131 | padding: 0 8px 9px 0;
132 | -moz-border-radius-bottomleft: 17px;
133 | -moz-border-radius-topright: 17px;
134 | -webkit-border-top-right-radius: 17px;
135 | -webkit-border-bottom-left-radius: 17px;
136 | }
137 | .sf-shadow ul.sf-shadow-off {
138 | background: transparent;
139 | }
140 |
--------------------------------------------------------------------------------
/psp2py/static/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/reingart/rad2py/e4802ade132d569225e8be7eca830d2f888aa5f9/psp2py/static/favicon.ico
--------------------------------------------------------------------------------
/psp2py/static/images/arrows-ffffff.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/reingart/rad2py/e4802ade132d569225e8be7eca830d2f888aa5f9/psp2py/static/images/arrows-ffffff.png
--------------------------------------------------------------------------------
/psp2py/static/images/css3buttons_backgrounds.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/reingart/rad2py/e4802ade132d569225e8be7eca830d2f888aa5f9/psp2py/static/images/css3buttons_backgrounds.png
--------------------------------------------------------------------------------
/psp2py/static/images/css3buttons_icons.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/reingart/rad2py/e4802ade132d569225e8be7eca830d2f888aa5f9/psp2py/static/images/css3buttons_icons.png
--------------------------------------------------------------------------------
/psp2py/static/images/error.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/reingart/rad2py/e4802ade132d569225e8be7eca830d2f888aa5f9/psp2py/static/images/error.png
--------------------------------------------------------------------------------
/psp2py/static/images/ok.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/reingart/rad2py/e4802ade132d569225e8be7eca830d2f888aa5f9/psp2py/static/images/ok.png
--------------------------------------------------------------------------------
/psp2py/static/images/poweredby.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/reingart/rad2py/e4802ade132d569225e8be7eca830d2f888aa5f9/psp2py/static/images/poweredby.png
--------------------------------------------------------------------------------
/psp2py/static/images/shadow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/reingart/rad2py/e4802ade132d569225e8be7eca830d2f888aa5f9/psp2py/static/images/shadow.png
--------------------------------------------------------------------------------
/psp2py/static/images/warn.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/reingart/rad2py/e4802ade132d569225e8be7eca830d2f888aa5f9/psp2py/static/images/warn.png
--------------------------------------------------------------------------------
/psp2py/static/images/warning.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/reingart/rad2py/e4802ade132d569225e8be7eca830d2f888aa5f9/psp2py/static/images/warning.png
--------------------------------------------------------------------------------
/psp2py/static/js/superfish.js:
--------------------------------------------------------------------------------
1 |
2 | /*
3 | * Superfish v1.4.8 - jQuery menu widget
4 | * Copyright (c) 2008 Joel Birch
5 | *
6 | * Dual licensed under the MIT and GPL licenses:
7 | * http://www.opensource.org/licenses/mit-license.php
8 | * http://www.gnu.org/licenses/gpl.html
9 | *
10 | * CHANGELOG: http://users.tpg.com.au/j_birch/plugins/superfish/changelog.txt
11 | */
12 |
13 | ;(function($){
14 | $.fn.superfish = function(op){
15 |
16 | var sf = $.fn.superfish,
17 | c = sf.c,
18 | $arrow = $([' »'].join('')),
19 | over = function(){
20 | var $$ = $(this), menu = getMenu($$);
21 | clearTimeout(menu.sfTimer);
22 | $$.showSuperfishUl().siblings().hideSuperfishUl();
23 | },
24 | out = function(){
25 | var $$ = $(this), menu = getMenu($$), o = sf.op;
26 | clearTimeout(menu.sfTimer);
27 | menu.sfTimer=setTimeout(function(){
28 | o.retainPath=($.inArray($$[0],o.$path)>-1);
29 | $$.hideSuperfishUl();
30 | if (o.$path.length && $$.parents(['li.',o.hoverClass].join('')).length<1){over.call(o.$path);}
31 | },o.delay);
32 | },
33 | getMenu = function($menu){
34 | var menu = $menu.parents(['ul.',c.menuClass,':first'].join(''))[0];
35 | sf.op = sf.o[menu.serial];
36 | return menu;
37 | },
38 | addArrow = function($a){ $a.addClass(c.anchorClass).append($arrow.clone()); };
39 |
40 | return this.each(function() {
41 | var s = this.serial = sf.o.length;
42 | var o = $.extend({},sf.defaults,op);
43 | o.$path = $('li.'+o.pathClass,this).slice(0,o.pathLevels).each(function(){
44 | $(this).addClass([o.hoverClass,c.bcClass].join(' '))
45 | .filter('li:has(ul)').removeClass(o.pathClass);
46 | });
47 | sf.o[s] = sf.op = o;
48 |
49 | $('li:has(ul)',this)[($.fn.hoverIntent && !o.disableHI) ? 'hoverIntent' : 'hover'](over,out).each(function() {
50 | if (o.autoArrows) addArrow( $('>a:first-child',this) );
51 | })
52 | .not('.'+c.bcClass)
53 | .hideSuperfishUl();
54 |
55 | var $a = $('a',this);
56 | $a.each(function(i){
57 | var $li = $a.eq(i).parents('li');
58 | $a.eq(i).focus(function(){over.call($li);}).blur(function(){out.call($li);});
59 | });
60 | o.onInit.call(this);
61 |
62 | }).each(function() {
63 | var menuClasses = [c.menuClass];
64 | if (sf.op.dropShadows && !($.browser.msie && $.browser.version < 7)) menuClasses.push(c.shadowClass);
65 | $(this).addClass(menuClasses.join(' '));
66 | });
67 | };
68 |
69 | var sf = $.fn.superfish;
70 | sf.o = [];
71 | sf.op = {};
72 | sf.IE7fix = function(){
73 | var o = sf.op;
74 | if ($.browser.msie && $.browser.version > 6 && o.dropShadows && o.animation.opacity!=undefined)
75 | this.toggleClass(sf.c.shadowClass+'-off');
76 | };
77 | sf.c = {
78 | bcClass : 'sf-breadcrumb',
79 | menuClass : 'sf-js-enabled',
80 | anchorClass : 'sf-with-ul',
81 | arrowClass : 'sf-sub-indicator',
82 | shadowClass : 'sf-shadow'
83 | };
84 | sf.defaults = {
85 | hoverClass : 'sfHover',
86 | pathClass : 'overideThisToUse',
87 | pathLevels : 1,
88 | delay : 800,
89 | animation : {opacity:'show'},
90 | speed : 'normal',
91 | autoArrows : true,
92 | dropShadows : true,
93 | disableHI : false, // true disables hoverIntent detection
94 | onInit : function(){}, // callback functions
95 | onBeforeShow: function(){},
96 | onShow : function(){},
97 | onHide : function(){}
98 | };
99 | $.fn.extend({
100 | hideSuperfishUl : function(){
101 | var o = sf.op,
102 | not = (o.retainPath===true) ? o.$path : '';
103 | o.retainPath = false;
104 | var $ul = $(['li.',o.hoverClass].join(''),this).add(this).not(not).removeClass(o.hoverClass)
105 | .find('>ul').hide().css('visibility','hidden');
106 | o.onHide.call($ul);
107 | return this;
108 | },
109 | showSuperfishUl : function(){
110 | var o = sf.op,
111 | sh = sf.c.shadowClass+'-off',
112 | $ul = this.addClass(o.hoverClass)
113 | .find('>ul:hidden').css('visibility','visible');
114 | sf.IE7fix.call($ul);
115 | o.onBeforeShow.call($ul);
116 | $ul.animate(o.animation,o.speed,function(){ sf.IE7fix.call($ul); o.onShow.call($ul); });
117 | return this;
118 | }
119 | });
120 |
121 | })(jQuery);
122 |
--------------------------------------------------------------------------------
/psp2py/static/js/web2py_ajax.js:
--------------------------------------------------------------------------------
1 | function popup(url) {
2 | newwindow=window.open(url,'name','height=400,width=600');
3 | if (window.focus) newwindow.focus();
4 | return false;
5 | }
6 | function collapse(id) { jQuery('#'+id).slideToggle(); }
7 | function fade(id,value) { if(value>0) jQuery('#'+id).hide().fadeIn('slow'); else jQuery('#'+id).show().fadeOut('slow'); }
8 | function ajax(u,s,t) {
9 | query = '';
10 | if (typeof s == "string") {
11 | d = jQuery(s).serialize();
12 | if(d){ query = d; }
13 | } else {
14 | pcs = [];
15 | for(i=0; i0){query = pcs.join("&");}
20 | }
21 | jQuery.ajax({type: "POST", url: u, data: query, success: function(msg) { if(t) { if(t==':eval') eval(msg); else jQuery("#" + t).html(msg); } } });
22 | }
23 |
24 | String.prototype.reverse = function () { return this.split('').reverse().join('');};
25 | function web2py_ajax_init() {
26 | jQuery('.hidden').hide();
27 | jQuery('.error').hide().slideDown('slow');
28 | jQuery('.flash').click(function() { jQuery(this).fadeOut('slow'); return false; });
29 | // jQuery('input[type=submit]').click(function(){var t=jQuery(this);t.hide();t.after('')});
30 | jQuery('input.integer').live('keyup', function(){this.value=this.value.reverse().replace(/[^0-9\-]|\-(?=.)/g,'').reverse();});
31 | jQuery('input.double,input.decimal').live('keyup', function(){this.value=this.value.reverse().replace(/[^0-9\-\.,]|[\-](?=.)|[\.,](?=[0-9]*[\.,])/g,'').reverse();});
32 | var confirm_message = (typeof w2p_ajax_confirm_message != 'undefined') ? w2p_ajax_confirm_message : "Are you sure you want to delete this object?";
33 | jQuery("input[type='checkbox'].delete").live('click', function(){ if(this.checked) if(!confirm(confirm_message)) this.checked=false; });
34 | var date_format = (typeof w2p_ajax_date_format != 'undefined') ? w2p_ajax_date_format : "%Y-%m-%d";
35 | try {jQuery("input.date").live('focus',function() {Calendar.setup({
36 | inputField:this, ifFormat:date_format, showsTime:false
37 | }); }); } catch(e) {};
38 | var datetime_format = (typeof w2p_ajax_datetime_format != 'undefined') ? w2p_ajax_datetime_format : "%Y-%m-%d %H:%M:%S";
39 | try { jQuery("input.datetime").live('focus', function() {Calendar.setup({
40 | inputField:this, ifFormat:datetime_format, showsTime: true,timeFormat: "24"
41 | }); }); } catch(e) {};
42 |
43 | jQuery("input.time").live('focus', function() { var el = jQuery(this);
44 | if (!el.hasClass('hasTimeEntry')) try { el.timeEntry(); } catch(e) {};
45 | });
46 | };
47 |
48 | jQuery(function() {
49 | var flash = jQuery('.flash');
50 | flash.hide();
51 | if(flash.html()) flash.slideDown();
52 | web2py_ajax_init();
53 | });
54 | function web2py_trap_form(action,target) {
55 | jQuery('#'+target+' form').each(function(i){
56 | var form=jQuery(this);
57 | if(!form.hasClass('no_trap'))
58 | form.submit(function(obj){
59 | jQuery('.flash').hide().html('');
60 | web2py_ajax_page('post',action,form.serialize(),target);
61 | return false;
62 | });
63 | });
64 | }
65 | function web2py_ajax_page(method,action,data,target) {
66 | jQuery.ajax({'type':method,'url':action,'data':data,
67 | 'beforeSend':function(xhr) {
68 | xhr.setRequestHeader('web2py-component-location',document.location);
69 | xhr.setRequestHeader('web2py-component-element',target);},
70 | 'complete':function(xhr,text){
71 | var html=xhr.responseText;
72 | var content=xhr.getResponseHeader('web2py-component-content');
73 | var command=xhr.getResponseHeader('web2py-component-command');
74 | var flash=xhr.getResponseHeader('web2py-component-flash');
75 | var t = jQuery('#'+target);
76 | if(content=='prepend') t.prepend(html);
77 | else if(content=='append') t.append(html);
78 | else if(content!='hide') t.html(html);
79 | web2py_trap_form(action,target);
80 | web2py_ajax_init();
81 | if(command) eval(command);
82 | if(flash) jQuery('.flash').html(flash).slideDown();
83 | }
84 | });
85 | }
86 | function web2py_component(action,target) {
87 | jQuery(function(){ web2py_ajax_page('get',action,null,target); });
88 | }
89 | function web2py_comet(url,onmessage,onopen,onclose) {
90 | if ("WebSocket" in window) {
91 | var ws = new WebSocket(url);
92 | ws.onopen = onopen?onopen:(function(){});
93 | ws.onmessage = onmessage;
94 | ws.onclose = onclose?onclose:(function(){});
95 | return true; // supported
96 | } else return false; // not supported
97 | }
98 |
--------------------------------------------------------------------------------
/psp2py/static/robots.txt:
--------------------------------------------------------------------------------
1 | User-agent: *
2 | Disallow: /welcome/default/user
3 |
--------------------------------------------------------------------------------
/psp2py/views/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/reingart/rad2py/e4802ade132d569225e8be7eca830d2f888aa5f9/psp2py/views/__init__.py
--------------------------------------------------------------------------------
/psp2py/views/default/index.html:
--------------------------------------------------------------------------------
1 | {{left_sidebar_enabled=right_sidebar_enabled=False}}
2 | {{extend 'layout.html'}}
3 |
4 |
5 | {{=T("Welcome to PSP support tool")}}
6 | In this application you can:
7 |
8 | - {{=A(T("List projects"), _href=URL('projects','index'))}} or {{=A(T("Create"), _href=URL('projects','create'))}} one
9 | - {{=A(T("Estimate project size (PROBE)"), _href=URL('probe','index'))}} using the {{=A(T("reuse library"), _href=URL('probe','library'))}} {{=A(T("categorization"), _href=URL('probe','categorize'))}} ({{=A(T("log-normbal distribution"), _href=URL('probe','normal_distribution.png'))}} )
10 | - {{=A(T("Estimate project time"), _href=URL('estimate','index'))}}, calculate the {{=A(T("correlation"), _href=URL('estimate','correlation'))}} and {{=A(T("significance"), _href=URL('estimate','significance'))}} of your historical data ({{=A(T("Linear Regression"), _href=URL('estimate','linear_regression'))}}
11 | - {{=A(T("Generate Reports"), _href=URL('reports','index'))}} of performance and quality ({{=A(T("projects"), _href=URL('reports','projects'))}}, {{=A(T("defects"), _href=URL('reports','defects'))}} including their {{=A(T("pareto distribution"), _href=URL('reports','pareto_distribution.png'))}} and {{=A(T("average fix time"), _href=URL('reports','average_fix_time.png'))}} )
12 |
13 |
14 |
15 |
16 |
17 |
18 | For more information see http://code.google.com/p/rad2py
19 |
20 |
--------------------------------------------------------------------------------
/psp2py/views/default/user.html:
--------------------------------------------------------------------------------
1 | {{extend 'layout.html'}}
2 | {{=T( request.args(0).replace('_',' ').capitalize() )}}
3 |
4 | {{=form}}
5 | {{if request.args(0)=='login':}}
6 | {{if not 'register' in auth.settings.actions_disabled:}}
7 |
register
8 | {{pass}}
9 | {{if not 'request_reset_password' in auth.settings.actions_disabled:}}
10 |
lost password
11 | {{pass}}
12 | {{pass}}
13 |
14 |
15 |
20 |
--------------------------------------------------------------------------------
/psp2py/views/estimate/correlation.html:
--------------------------------------------------------------------------------
1 | {{extend 'layout.html'}}
2 | Correlation Test
3 |
4 |
5 | Time (hours)
6 | Size (SLOC)
7 |
8 | {{for h, l in zip(hours, loc):}}
9 |
10 | {{="%0.2f" % h}}
11 | {{=l}}
12 |
13 | {{pass}}
14 |
15 |
16 | Correlation:
17 |
18 | - r2 = {{=r2}} (correlation coefficient)
19 | - Correlation Degree: {{=correlation}}
20 |
21 |
--------------------------------------------------------------------------------
/psp2py/views/estimate/index.html:
--------------------------------------------------------------------------------
1 | {{extend 'layout.html'}}
2 | Resource Estimate
3 | {{=form}}
4 |
--------------------------------------------------------------------------------
/psp2py/views/estimate/significance.html:
--------------------------------------------------------------------------------
1 | {{extend 'layout.html'}}
2 | Significance Test
3 |
4 |
5 | Time (hours)
6 | Size (SLOC)
7 |
8 | {{for h, l in zip(hours, loc):}}
9 |
10 | {{="%0.2f" % h}}
11 | {{=l}}
12 |
13 | {{pass}}
14 |
15 |
16 | Significance:
17 |
18 | - r2 = {{=r2}} (correlation coefficient)
19 | - t = {{=t}} (student-t value)
20 | - p = {{=p}} (student-t probability)
21 | - s = {{=s}} (1-p)
22 | - Significance: {{=significance}}
23 |
24 |
--------------------------------------------------------------------------------
/psp2py/views/estimate/time_in_phase.html:
--------------------------------------------------------------------------------
1 | {{extend 'layout.html'}}
2 | Time to date summary
3 |
4 |
5 |
6 |
7 |
8 | Phase
9 | Time To Date
10 | %
11 |
12 |
13 |
14 | {{for t in times:}}
15 |
16 | {{=t[0]}}
17 | {{=pretty_time(t[1])}}
18 | {{="%d %%" % t[2]}}
19 |
20 | {{pass}}
21 |
22 |
23 |
--------------------------------------------------------------------------------
/psp2py/views/generic.html:
--------------------------------------------------------------------------------
1 | {{extend 'layout.html'}}
2 | {{"""
3 |
4 | You should not modify this file.
5 | It is used as default when a view is not provided for your controllers
6 |
7 | """}}
8 | {{=' '.join(x.capitalize() for x in request.function.split('_'))}}
9 | {{if len(response._vars)==1:}}
10 | {{=response._vars.values()[0]}}
11 | {{elif len(response._vars)>1:}}
12 | {{=BEAUTIFY(response._vars)}}
13 | {{pass}}
14 | {{if request.is_local:}}
15 | {{=response.toolbar()}}
16 | {{pass}}
17 |
--------------------------------------------------------------------------------
/psp2py/views/generic.json:
--------------------------------------------------------------------------------
1 | {{from gluon.serializers import json}}{{=XML(json(response._vars))}}
2 |
--------------------------------------------------------------------------------
/psp2py/views/generic.load:
--------------------------------------------------------------------------------
1 | {{'''
2 | # License: Public Domain
3 | # Author: Iceberg at 21cn dot com
4 |
5 | With this generic.load file, you can use same function to serve two purposes.
6 |
7 | = regular action
8 | - ajax callback (when called with .load)
9 |
10 | Example modified from http://www.web2py.com/AlterEgo/default/show/252:
11 |
12 | def index():
13 | return dict(
14 | part1='hello world',
15 | part2=LOAD(url=URL(r=request,f='auxiliary.load'),ajax=True))
16 |
17 | def auxiliary():
18 | form=SQLFORM.factory(Field('name'))
19 | if form.accepts(request.vars):
20 | response.flash = 'ok'
21 | return dict(message="Hello %s" % form.vars.name)
22 | return dict(form=form)
23 |
24 | Notice:
25 |
26 | - no need to set response.headers['web2py-response-flash']
27 | - no need to return a string
28 | even if the function is called via ajax.
29 |
30 | '''}}{{if len(response._vars)==1:}}{{=response._vars.values()[0]}}{{else:}}{{=BEAUTIFY(response._vars)}}{{pass}}
--------------------------------------------------------------------------------
/psp2py/views/generic.pdf:
--------------------------------------------------------------------------------
1 | {{
2 | import os
3 | from gluon.contrib.generics import pdf_from_html
4 | filename = '%s/%s.html' % (request.controller,request.function)
5 | if os.path.exists(os.path.join(request.folder,'views',filename)):
6 | html=response.render(filename)
7 | else:
8 | html=BODY(BEAUTIFY(response._vars)).xml()
9 | pass
10 | =pdf_from_html(html)
11 | }}
12 |
--------------------------------------------------------------------------------
/psp2py/views/generic.rss:
--------------------------------------------------------------------------------
1 | {{
2 | ###
3 | # response._vars contains the dictionary returned by the controller action
4 | # for this to work the action must return something like
5 | #
6 | # dict(title=...,link=...,description=...,created_on='...',items=...)
7 | #
8 | # items is a list of dictionaries each with title, link, description, pub_date.
9 | ###
10 | from gluon.serializers import rss}}{{=XML(rss(response._vars))}}
11 |
--------------------------------------------------------------------------------
/psp2py/views/generic.xml:
--------------------------------------------------------------------------------
1 | {{from gluon.serializers import xml}}{{=XML(xml(response._vars))}}
2 |
--------------------------------------------------------------------------------
/psp2py/views/probe/categorize.html:
--------------------------------------------------------------------------------
1 | {{extend 'layout.html'}}
2 | Object size categorization
3 |
4 | Normal (logarithmic) parameters
5 |
6 | - Std_Dev: {{=std_dev}}
7 | - Average: {{=avg_ln}}
8 |
9 |
10 | Objects and size ranges
11 |
12 |
13 |
14 | Object Name
15 | Size Range
16 | Object LOC
17 | Object ln(LOC)
18 |
19 | {{for name, loc in locs.items():}}
20 |
21 | {{=name}}
22 | {{=categorization.get(name)}}
23 | {{=objs[name]['loc']}}
24 | {{=loc}}
25 |
26 | {{pass}}
27 |
28 |
29 | Distribution
30 |
31 |
32 |
33 | Size Range
34 | Range Midpoint LOC
35 | Range Midpoint ln(LOC)
36 | Quantity
37 | Percentage
38 |
39 | {{for size in PSP_SIZES:}}
40 |
41 | {{=size}}
42 | {{=midpoints.get(size, "")}}
43 | {{=midpoints_ln.get(size, "")}}
44 | {{=midpoints_q.get(size)}}
45 | {{=categorization and ("%0.2f" % (midpoints_q.get(size, 0)/float(len(categorization))*100.)) or ''}} %
46 |
47 | {{pass}}
48 |
49 |
--------------------------------------------------------------------------------
/psp2py/views/probe/index.html:
--------------------------------------------------------------------------------
1 | {{extend 'layout.html'}}
2 | PROxy Based Estimation
3 |
4 | {{=T("Identify objects")}}
5 | {{=form}}
6 |
7 |
8 |
9 |
10 | {{=T("Objects")}}
11 |
12 |
13 |
14 | Name
15 | Category
16 | based on
17 | Relative size
18 | Planned LOC
19 |
20 |
21 |
22 | {{for obj in sorted(objects.values(), key=lambda x: x['name']):}}
23 |
24 | {{=obj['name']}}
25 | {{=obj['category']}}
26 | {{=obj['function_name']}}
27 | {{=obj['relative_size']}}
28 | {{=obj['loc']}}
29 |
30 | {{pass}}
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/psp2py/views/probe/library.html:
--------------------------------------------------------------------------------
1 | {{extend 'layout.html'}}
2 | PROBE reuse library
3 | Query form
4 | {{=form}}
5 | Objects
6 | {{=table}}
7 |
--------------------------------------------------------------------------------
/psp2py/views/projects/create.html:
--------------------------------------------------------------------------------
1 | {{extend 'layout.html'}}
2 | Create PSP Project
3 | {{=form}}
4 |
--------------------------------------------------------------------------------
/psp2py/views/projects/edit.html:
--------------------------------------------------------------------------------
1 | {{extend 'layout.html'}}
2 | Edit Project
3 | {{=form}}
4 |
--------------------------------------------------------------------------------
/psp2py/views/projects/index.html:
--------------------------------------------------------------------------------
1 | {{extend 'layout.html'}}
2 | PSP Projects List
3 | {{=form}}
4 |
--------------------------------------------------------------------------------
/psp2py/views/projects/show.html:
--------------------------------------------------------------------------------
1 | {{extend 'layout.html'}}
2 | Project: {{=project.name}}
3 | {{=form}}
4 | {{=FORM(
5 | INPUT(_type="submit", _value=T("Edit")),
6 | _action=URL('projects', 'edit', args=('psp_project', project.project_id)), )}}
7 | Time Summary
8 | {{=SQLTABLE(times, headers="fieldname:capitalize")}}
9 | Defects
10 | {{=SQLTABLE(defects, headers="fieldname:capitalize")}}
11 |
--------------------------------------------------------------------------------
/psp2py/views/reports/defects.html:
--------------------------------------------------------------------------------
1 | {{extend 'layout.html'}}
2 | Defect Type Standard Report
3 |
4 |
5 |
6 | No.
7 | Name
8 | Description
9 | Quantity
10 | Freq. %
11 | Fix Time
12 | Time %
13 | Average
14 |
15 |
16 | {{for defect_type, defect_name in sorted(PSP_DEFECT_TYPES.items()):}}
17 |
18 | {{=defect_type}}
19 | {{=defect_name}}
20 | {{=PSP_DEFECT_DESC[defect_type]}}
21 | {{='%d' % (defect_count_per_type.get(defect_type, 0))}}
22 | {{=('%.2f' % (defect_count_per_type.get(defect_type, 0)/float(defect_count)*100.0)) if defect_count else ""}} %
23 | {{=pretty_time(defect_fix_time_per_type.get(defect_type, 0))}}
24 | {{=('%.2f' % (defect_fix_time_per_type.get(defect_type, 0) / float(total_fix_time) * 100.)) if total_fix_time else ""}} %
25 | {{=defect_count_per_type.get(defect_type, 0) and pretty_time(defect_fix_time_per_type.get(defect_type, 0) / float(defect_count_per_type.get(defect_type, 0))) or ''}}
26 |
27 | {{pass}}
28 |
29 |
--------------------------------------------------------------------------------
/psp2py/views/reports/index.html:
--------------------------------------------------------------------------------
1 | {{extend 'layout.html'}}
2 | General Report
3 |
4 |
5 |
6 |
7 | Productivity
8 |
9 | - LOC per hour: {{="%0.2f" % loc_per_hour}}
10 | - Total LOC: {{=total_loc}}
11 | - Total Time: {{="%0.2f" % (total_time / 60. /60.) }} hours
12 | - Interruption Time: {{="%0.2f" % (interruption_time / 60. /60.) }} hours
13 | - Planned Time: {{="%0.2f" % (planned_time / 60. /60.) }} hours
14 | - CPI: {{="%0.2f" % (cost_performance_index) }} (plan/actual time)
15 |
16 |
17 |
18 | Defect Removal Efficiency
19 |
20 | - Process Yield: {{=process_yield}} % (removal before compile)
21 | - Defects per hour: {{="%0.2f" % total_defects_injected_per_hour}} (injected/removed)
22 | - Test Defects: {{="%0.2f" % test_defects_per_kloc}} removed per KLOC
23 | - Total Defects: {{="%0.2f" % total_defects_per_kloc}} removed per KLOC
24 | - Defect count: {{=total_defect_count}}
25 | - Fix Time: {{=pretty_time(total_fix_time)}}
26 | - Average Fix Time: {{=pretty_time(average_fix_time)}}
27 |
28 |
29 |
30 | Cost of Quality
31 |
37 |
38 |
39 |
40 |
41 | Report per phase
42 |
43 |
44 | Phase
45 | Planned Time
To Date
46 | Planned Time
To Date %
47 | Actual Time
To Date
48 | Actual Time
To Date %
49 | Defects
injected
50 | Defects
removed
51 | Yield
52 | Defects
per hour
53 | Defect Removal
Leverage (DRL)
54 |
55 |
56 | {{for phase in PSP_PHASES:}}
57 |
58 | {{=phase}}
59 | {{=pretty_time(planned_time_per_phase.get(phase, 0))}}
60 | {{='%.2f' % (planned_time_per_phase.get(phase, 0) / planned_time * 100.)}} %
61 | {{=pretty_time(times_per_phase.get(phase))}}
62 | {{='%.2f' % (times_per_phase.get(phase, 0) / total_time * 100.)}} %
63 | {{='%d' % (defects_injected_per_phase.get(phase) or 0)}}
64 | {{='%d' % (defects_removed_per_phase.get(phase) or 0)}}
65 | {{=yields_per_phase.get(phase) or ''}} %
66 | {{='%.2f' % (defects_per_hour_per_phase.get(phase) or 0)}}
67 | {{='%.2f' % (defect_removal_leverage.get(phase) or 0)}}
68 |
69 | {{pass}}
70 |
71 |
--------------------------------------------------------------------------------
/psp2py/views/reports/projects.html:
--------------------------------------------------------------------------------
1 | {{extend 'layout.html'}}
2 | Projects Summary Report
3 |
4 |
5 |
6 | Project
7 | Description
8 |
9 | Plan.
Time
10 | LPI
Time
11 | UPI
Time
12 | Actual
Time
13 | Int.
Time
14 | CPI
15 | Plan.
LOC
16 | Actual
LOC
17 | Defects
18 | Fix Time
19 |
20 |
21 | {{for project in projects:}}
22 |
23 | {{=project.psp_project.name}}
24 | {{=project.psp_project.description}}
25 |
26 | {{=pretty_time(project.sum_plan)}}
27 |
28 | {{="%.2f" % (project.psp_project.time_lpi or 0)}} h
29 | {{="%.2f" % (project.psp_project.time_upi or 0)}} h
30 | {{=pretty_time(project.sum_actual)}}
31 |
32 | {{=pretty_time(project.sum_interruption)}}
33 | {{= ('%.2f' % (project.sum_plan / float(project.sum_actual) if (project.sum_plan and project.sum_actual) else 0 )) or '' }}
34 |
35 | {{=project.psp_project.planned_loc or ''}}
36 | {{=project.psp_project.actual_loc or ''}}
37 | {{=defects_per_project.get(project.psp_project.project_id, '')}}
38 | {{=pretty_time(fix_time_per_project.get(project.psp_project.project_id, 0))}}
39 |
40 | {{pass}}
41 |
42 |
--------------------------------------------------------------------------------
/psp2py/views/web2py_ajax.html:
--------------------------------------------------------------------------------
1 | {{
2 | response.files.insert(0,URL('static','js/jquery.js'))
3 | response.files.insert(1,URL('static','css/calendar.css'))
4 | response.files.insert(2,URL('static','js/calendar.js'))
5 | for _item in response.meta or []:}}
6 | {{
7 | pass
8 | for _k,_file in enumerate(response.files or []):
9 | if _file in response.files[:_k]:
10 | continue
11 | _file0=_file.lower().split('?')[0]
12 | if _file0.endswith('.css'):}}
13 | {{
14 | elif _file0.endswith('.js'):}}
15 | {{
16 | pass
17 | pass
18 | }}
19 |
25 |
26 |
--------------------------------------------------------------------------------
/psp2py/views/wiki/edit.html:
--------------------------------------------------------------------------------
1 | {{extend 'layout.html'}}
2 | Edit Wiki
3 | {{=form}}
4 |
--------------------------------------------------------------------------------
/psp2py/views/wiki/index.html:
--------------------------------------------------------------------------------
1 | {{extend 'layout.html'}}
2 | Wiki Page Index
3 |
4 | {{for row in rows:}}
5 | - {{=A(row.title, _href=URL("view", args=row.page.split("/")))}}
6 | {{pass}}
7 |
8 |
9 | {{=FORM(
10 | INPUT(_type="submit", _value=T("New Page")),
11 | _action=URL('wiki', 'edit'))}}
12 |
--------------------------------------------------------------------------------
/psp2py/views/wiki/load.html:
--------------------------------------------------------------------------------
1 | {{=title}}
2 | {{=text}}
3 |
--------------------------------------------------------------------------------
/psp2py/views/wiki/view.html:
--------------------------------------------------------------------------------
1 | {{extend 'layout.html'}}
2 | {{=title}}
3 |
4 | {{=text}}
5 |
6 | {{=FORM(
7 | INPUT(_type="submit", _value=T("Edit")),
8 | _action=URL('wiki', 'edit', args=request.args))}}
9 |
--------------------------------------------------------------------------------
/screenshots/ide2py-0.05-ubuntu.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/reingart/rad2py/e4802ade132d569225e8be7eca830d2f888aa5f9/screenshots/ide2py-0.05-ubuntu.png
--------------------------------------------------------------------------------
/screenshots/ide2py-v0.03-ubuntu.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/reingart/rad2py/e4802ade132d569225e8be7eca830d2f888aa5f9/screenshots/ide2py-v0.03-ubuntu.png
--------------------------------------------------------------------------------
/screenshots/proof-of-concept.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/reingart/rad2py/e4802ade132d569225e8be7eca830d2f888aa5f9/screenshots/proof-of-concept.png
--------------------------------------------------------------------------------
/screenshots/prototipe-alpha-win7.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/reingart/rad2py/e4802ade132d569225e8be7eca830d2f888aa5f9/screenshots/prototipe-alpha-win7.png
--------------------------------------------------------------------------------
/screenshots/psp_average_fix_times.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/reingart/rad2py/e4802ade132d569225e8be7eca830d2f888aa5f9/screenshots/psp_average_fix_times.png
--------------------------------------------------------------------------------
/screenshots/psp_defect.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/reingart/rad2py/e4802ade132d569225e8be7eca830d2f888aa5f9/screenshots/psp_defect.png
--------------------------------------------------------------------------------
/screenshots/psp_defect_report.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/reingart/rad2py/e4802ade132d569225e8be7eca830d2f888aa5f9/screenshots/psp_defect_report.png
--------------------------------------------------------------------------------
/screenshots/psp_defects.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/reingart/rad2py/e4802ade132d569225e8be7eca830d2f888aa5f9/screenshots/psp_defects.png
--------------------------------------------------------------------------------
/screenshots/psp_estimate.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/reingart/rad2py/e4802ade132d569225e8be7eca830d2f888aa5f9/screenshots/psp_estimate.png
--------------------------------------------------------------------------------
/screenshots/psp_linear_regression.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/reingart/rad2py/e4802ade132d569225e8be7eca830d2f888aa5f9/screenshots/psp_linear_regression.png
--------------------------------------------------------------------------------
/screenshots/psp_metadata.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/reingart/rad2py/e4802ade132d569225e8be7eca830d2f888aa5f9/screenshots/psp_metadata.png
--------------------------------------------------------------------------------
/screenshots/psp_normal_distribution.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/reingart/rad2py/e4802ade132d569225e8be7eca830d2f888aa5f9/screenshots/psp_normal_distribution.png
--------------------------------------------------------------------------------
/screenshots/psp_pareto_distribution.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/reingart/rad2py/e4802ade132d569225e8be7eca830d2f888aa5f9/screenshots/psp_pareto_distribution.png
--------------------------------------------------------------------------------
/screenshots/psp_plan_summary_times.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/reingart/rad2py/e4802ade132d569225e8be7eca830d2f888aa5f9/screenshots/psp_plan_summary_times.png
--------------------------------------------------------------------------------
/screenshots/psp_probe.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/reingart/rad2py/e4802ade132d569225e8be7eca830d2f888aa5f9/screenshots/psp_probe.png
--------------------------------------------------------------------------------
/screenshots/psp_project.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/reingart/rad2py/e4802ade132d569225e8be7eca830d2f888aa5f9/screenshots/psp_project.png
--------------------------------------------------------------------------------
/screenshots/psp_report_projects.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/reingart/rad2py/e4802ade132d569225e8be7eca830d2f888aa5f9/screenshots/psp_report_projects.png
--------------------------------------------------------------------------------
/screenshots/psp_reports.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/reingart/rad2py/e4802ade132d569225e8be7eca830d2f888aa5f9/screenshots/psp_reports.png
--------------------------------------------------------------------------------
/screenshots/psp_reuse_library.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/reingart/rad2py/e4802ade132d569225e8be7eca830d2f888aa5f9/screenshots/psp_reuse_library.png
--------------------------------------------------------------------------------
/screenshots/psp_toolbar.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/reingart/rad2py/e4802ade132d569225e8be7eca830d2f888aa5f9/screenshots/psp_toolbar.png
--------------------------------------------------------------------------------
/screenshots/psp_wiki.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/reingart/rad2py/e4802ade132d569225e8be7eca830d2f888aa5f9/screenshots/psp_wiki.png
--------------------------------------------------------------------------------
/screenshots/pytong.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/reingart/rad2py/e4802ade132d569225e8be7eca830d2f888aa5f9/screenshots/pytong.png
--------------------------------------------------------------------------------
/screenshots/wxPyDiff.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/reingart/rad2py/e4802ade132d569225e8be7eca830d2f888aa5f9/screenshots/wxPyDiff.png
--------------------------------------------------------------------------------
/setup_qdb.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | from distutils.core import setup
4 | try:
5 | import py2exe
6 | from nsis import build_installer
7 | except:
8 | build_installer = None
9 |
10 | import qdb
11 |
12 | setup(name='qdb',
13 | version=qdb.__version__,
14 | description='PDB-like Client/Server Debugger for Python',
15 | author='Mariano Reingart',
16 | author_email='reingart@gmail.com',
17 | url='http://code.google.com/p/rad2py/wiki/QdbRemotePythonDebugger',
18 | packages=['qdb'],
19 | console=['qdb/qdb.py'],
20 | cmdclass = {"py2exe": build_installer},
21 | )
22 |
23 |
--------------------------------------------------------------------------------