The repocribro’s documentation¶
Welcome in the repocribro documentation. Continue by choosing the desired topic from the list of contents. You can also visit the repository repocribro@GitHub.
Contents¶
Introduction¶
repocribro is Python powered web application allowing users to register their GitHub repositories so they can be managed, searched, browsed, tested, etc. (depends on used extensions) within the app. Main idea is to provide simple but powerful modular tool for building groups of GitHub repositories which are developed by different users and organizations with some common goal.
Cribro means sieve in Italian language (origins in Latin word cribrum). This project provides tool for intelligent sifting repositories, information about them and its contents.
This project has been created as final semester work for subject MI-PYT, CTU in Prague (more in Credits).
Project is open-source (under MIT license) published @GitHub. Basically you just need to always include the copyright and permission notice with name of author. But it would be great if you let us know that you are using repocribro in any way!!!
Installation¶
Installation options¶
This application can be installed via standard setuptools
, for
more information read Python docs - Installing Python Module. Check
the Requirements before installation.
Check installation¶
After the successful installation you should be able to run:
$ repocribro --version
repocribro v0.1
Become an admin¶
After first start you should login into web app via GitHub and
then you can use assign-role
command to become an admin
.
$ repocribro assign-role --login MarekSuchanek --role admin
Loaded extensions: core
Role admin not in DB... adding
Role admin added to MarekSuchanek
Database¶
In order to create and maintain the database, you can use migrations by Flask-Migrate:
$ repocribro db --help
Or you can use standard SQLAlchemy procedure db.create_all()
via:
$ repocribro create-db
Both will try to create tables into database specified in the Configuration.
Configuration¶
You can see example configuration files at:
config/app.example.cfg
config/auth.example.cfg
config/db.example.cfg
!!! If you are going to publish your configuration somewhere make sure, that it does not contain any secret information like passwords or API tokens!
Syntax of configuration files is standard INI, parsed by ConfigParser. Names of variables are case insensitive. Configuration can be in separate configuration files but if there are same variables within same sections there will overriding depending on the order of files.
Default config file can be also specified with environment variable:
$ export REPOCRIBRO_CONFIG_FILE='/path/to/config.cfg'
$ python
Python 3.5.2 (default, Oct 14 2016, 12:54:53)
[GCC 6.2.1 20160916 (Red Hat 6.2.1-2)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from repocribro.app import app
>>> app.run()
Application¶
You can specify any of the Flask (or extensions) configuration variables
that is supposed to be placed to app.config
. Just use same name (it
can be also lowercase). These configurations must be done in [flask]
section. Mandatory attribute is SECRET_KEY
used for the session signing,
this key is of course private.
For example:
[flask]
# something is wrong, I want to debug
DEBUG = true
# random secret key (use os.urandom())
SECRET_KEY = VeryPseudoRandomSuchSecret
Database¶
Next you need to specify configuration of your database. Flask extension
Flask-SQLAlchemy is used so again configuration needs to be done within
section [flask]
.
http://flask-sqlalchemy.pocoo.org/2.1/config/#configuration-keys
!!! If file contains DB password and username keep it private!
For example:
[flask]
# SQLite is enough, just testing
SQLALCHEMY_DATABASE_URI = sqlite:////tmp/test.db
GitHub¶
For communication with GitHub OAuth you are going to need Client ID and
Client secret. Also for working with webhooks secret key must be set-up
so every incoming message can be verified. Specify those in [github]
section of config.
https://developer.github.com/webhooks/securing/
!!! Always keep file with this configuration private!
For example:
[github]
# Client ID & secret is obtained by creating OAuth app
CLIENT_ID = myAppClientIdFromGitHub
CLIENT_SECRET = myAppClientSecretFromGitHub
# Webhook secret for signing should be randomly generated
WEBHOOKS_SECRET = someRandomSecretKeyForWebhooks
Requirements¶
- Python 3.5+
- Installed dependencies (automatic with
setup.py
) - Configuration prepared
- DB supported by SQLAlchemy
Usage¶
Usage basics¶
First you need to have prepared config file(s) with at least minimal mandatory configuration and repocribro successfully installed(see Installation and Configuration).
$ repocribro --config <config_file> [command] [command options]
$ repocribro -c <config_file> [command] [command options]
$ repocribro -c <config_file_1> -c <config_file_2> [command] [command options]
For all commands you can specify configuration file(s) of repocribro app, order of arguments matters only if you are overriding same configuration variable in those files. If no config files are specified those from default path will be used.
Commands¶
After supplying configuration files you can use various commands. Full list of commands with details are described within CLI commands.
For starting the web application (server) use:
$ repocribro runserver
Common options¶
You can also use standard -?
, --help
and --version
:
$ repocribro --help
usage: repocribro [-c CFG_FILES] [-v] [-?] {runserver,db,shell,repocheck} ...
positional arguments:
{runserver,db,shell,repocheck}
runserver Runs the Flask development server i.e. app.run()
db Perform database migrations
shell Runs a Python shell inside Flask application context.
repocheck Perform check procedure of repository events
optional arguments:
-c CFG_FILES, --config CFG_FILES
-v, --version show program's version number and exit
-?, --help show this help message and exit
$ repocribro --version
repocribro v0.0
CLI commands¶
There are various command for the app management some are
provided by Flask extensions, some by repocribro. You can
use option --help
to get more information.
assign-role¶
Main purpose for this command is to set the initial admin of the app without touching DB directly. Others can be then set within administration zone of web interface.
$ repocribro assign-role --login MarekSuchanek --role admin
Loaded extensions: core
Role admin not in DB... adding
Role admin added to MarekSuchanek
$ repocribro assign-role --login MarekSuchanek --role admin
Loaded extensions: core
User MarekSuchanek already has role admin
For more information:
$ repocribro assign-role --help
db (database)¶
Command supplied by Flask-Migrate extension provides tool to work with database migrations (init, migrate, downgrade, upgrade, etc.).
For more information:
$ repocribro db --help
repocheck¶
Not implemented yet!
This command will provide simple checking of one or all repositories if there are some uncaught events within specified time. Main idea is to get the missed events (from webhooks) due to app outage.
runserver¶
Runs the web application (app.run()
), but also some settings
can be overriden like hostname, port, debugging, ...
For more information:
$ repocribro runserver --help
shell¶
Runs the Python shell inside the Flask app context. That can be useful for some debugging by hand.
For more information:
$ repocribro shell --help
Web application¶
Public usage¶
Anonymous (unauthenticated) used can browse public content of the web application which includes:
- landing with basic info
- search
- user/organization profiles
- public repositories with their releases and updates
Authentication¶
User can authenticate via GitHub OAuth with scope:
repo
= read and manage user repositories (with private)user
= read user information (with private)admin:webhook
= add/remove webhooks
User management¶
Every activate (not banned) user can manage which of his/her repositories should be listed within application as:
- public = everyone can see them
- hidden = only people with secret URL can see them
- private = only owner or administrator can see them
Information about user account can be synchronized as well as the repository information. When activating the repository webhook is added. Because webhook can be deleted at GitHub by hand, user can recreate the webhook again (he can’t do it by hand because doesn’t know the webhooks secret).
Administration¶
Managing user accounts, roles and repositories (not owned) can be done in administration zone. Same principles as in user management zone.
REST API¶
There is also REST API (only GET) for all GitHub entities, but it will be reworked soon (because the repo privacy & compatibility issues).
The actual is done by Flask-Restless with collections:
user
org
repo
push
commit
release
Credits¶
This project was created as final semester work for the awesome subject MI-PYT (Advanced Python) taught at the Faculty of Information Technology, Czech Technical University in Prague (FIT CTU) by @hroncok and @encukou.
Thanks goes to the Python community, to developers, contributors and other people around projects that are used within repocribro:
Also many thanks to GitHub, Travis CI, coveralls.io, readthedocs.org, requires.io and PyPi for being here for all of us.
Testing¶
This project uses the most fabulous testing tools for Python:
Run tests¶
Run tests simply by:
python setup.py test
or (if you have installed dependencies):
python -m pytest [options]
pytest [options]
You can also see the tests logs at Travis CI.
Betamax cassettes¶
Betamax cassettes are stored in tests/fixtures/cassettes
directory. If
you are not connected to theInternet, GitHub API is not working and/or
you don’t want to create own GitHub token you will use (replay) them in order
to test API client.
If you want to run your own cassettes, you need to setup system
variable GITHUB_TOKEN
which will contain the GitHub personal token
(must have privileges to create/delete webhooks). You also must change variables
within tests/test_github.py
specifying some of your existing repository and
also non-existing repository. Token can be created at:
Your test command then might look like:
$ GITHUB_TOKEN=<YOUR_TOKEN> python setup.py test
or use export
and unset
:
$ export GITHUB_TOKEN=<YOUR_TOKEN>
$ python setup.py test
...
$ unset GITHUB_TOKEN
For more information, enjoy reading Betamax documentation.
Writing extensions¶
Hooks for extension¶
Name | Description | Return type |
---|---|---|
get_gh_event_processors |
Get GitHub events processors | dict of str : list of function |
get_gh_webhook_processors |
Get GitHub webhook processors | dict of str : list of function |
init_business |
Init business layer of the extension | None |
init_blueprints |
Init Flask blueprints (register them) | None |
init_container |
Put whatever you need into DI container of the app | None |
init_filters |
Init Jinja2 filters for views (register them) | None |
init_models |
Init models (data) layer of the extension | array |
introduce |
Introduce yourself (just name) for the list of extensions | str |
view_admin_extensions |
Return view object of extension for the admin list | ExtensionView |
view_admin_index_tabs |
Add/edit tabs for admin index page | dict of str :ViewTab |
view_core_search_tabs |
Add/edit tabs for search results page | dict of str :ViewTab |
view_core_user_detail_tabs |
Add/edit tabs for public user page | dict of str :ViewTab |
view_core_org_detail_tabs |
Add/edit tabs for public organization page | dict of str :ViewTab |
view_core_repo_detail_tabs |
Add/edit tabs for repository detail page | dict of str :ViewTab |
view_manage_dashboard_tabs |
Add/edit tabs for user management zone dashboard | dict of str : `ViewTab |
You can write your own repocribro extension. It’s very simple,
all you need is extend the Extension
class from repocribro.extending
,
make function returning instance of this class and direct entrypoint
in the group [repocribro.ext]
on that function. Extending is done
via implementing actions on Hooks for extension which can return something.
While writing new plugin use please the same model, so even your extension
is also easily extensible. Big part of core repocribro is extension itself
see the module repocribro.ext_core
.
my_ext.py¶
1 2 3 4 5 6 7 8 9 10 | from repocribro.extending import Extension
class MyNewExtension(Extension):
...
def make_my_new_extension():
...
return MyNewExtension()
|
setup.py¶
1 2 3 4 5 6 7 8 9 10 11 12 13 | from setuptools import setup
...
setup(
...
entry_points={
'repocribro.ext': [
'repocribro-my_ext = my_ext:make_my_new_extension'
]
},
...
)
...
|
API¶
repocribro consists of following package(s) and it’s modules:
repocribro.api¶
-
repocribro.api.
create_api
(app, db)¶ Create REST API (with GET) for resources in DB
Parameters: - app (
flask.Flask
) – Actual web application - db – Actual database with stored resources
Returns: API manager extension
Return type: flask_restless.APIManager
Todo: Implement own or go into bigger detail (privacy, usernames, etc.)
- app (
repocribro.commands¶
AssignRoleCommand¶
-
class
repocribro.commands.
AssignRoleCommand
(func=None)¶ Bases:
flask_script.commands.Command
Assign desired role to desired user
-
option_list
= (<flask_script.commands.Option object at 0x7fc37790ff28>, <flask_script.commands.Option object at 0x7fc37790ff60>)¶ CLI command options for assign-role
-
run
(login, role_name)¶ Run the assign-role command with given options in order to assign role to user
Parameters: - login (str) – Login name of desired user
- role_name (str) – Name of desired role
Raises: SystemExit – If user does not exists or already had the role
-
DbCreateCommand¶
RepocheckCommand¶
-
class
repocribro.commands.
RepocheckCommand
(func=None)¶ Bases:
flask_script.commands.Command
Perform check procedure of repository events
-
_do_check
(repo)¶ Perform single repository check for new events
Parameters: repo ( repocribro.models.Repository
) – Repository to be checkedTodo: Handle pagination of GitHub events Raises: SystemExit – if GitHub API request fails
-
_process_event
(repo, event)¶ Process potentially new event for repository
Parameters: - repo (
repocribro.models.Repository
) – Repository related to event - event (dict) – GitHub event data
Returns: If the event was new or already registered before
Return type: bool
- repo (
-
event2webhook
= {'ReleaseEvent': 'release', 'PushEvent': 'push', 'RepositoryEvent': 'repository'}¶
-
option_list
= (<flask_script.commands.Option object at 0x7fc3779122b0>,)¶ CLI command options for repocheck
-
run
(full_name=None)¶ Run the repocheck command to check repo(s) new events
Obviously this procedure can check events only on public repositories. If name of repository is not specified, then procedure will be called on all registered public repositories in DB.
Parameters: full_name (str) – Name of repository to be checked (if None -> all) Raises: SystemExit – If repository with given full_name does not exist
-
repocribro.controllers¶
repocribro.controllers.admin¶
-
repocribro.controllers.admin.
account_ban
(login)¶ Ban (make inactive) account (POST handler)
-
repocribro.controllers.admin.
account_delete
(login)¶ Delete account (POST handler)
-
repocribro.controllers.admin.
account_detail
(login)¶ Account administration (GET handler)
-
repocribro.controllers.admin.
admin
= <flask.blueprints.Blueprint object>¶ Admin controller blueprint
-
repocribro.controllers.admin.
index
()¶ Administration zone dashboard (GET handler)
-
repocribro.controllers.admin.
repo_delete
(login, reponame)¶ Delete repository (POST handler)
-
repocribro.controllers.admin.
repo_detail
(login, reponame)¶ Repository administration (GET handler)
-
repocribro.controllers.admin.
repo_visibility
(login, reponame)¶ Change repository visibility (POST handler)
-
repocribro.controllers.admin.
role_assignment_add
(name)¶ Assign role to user (POST handler)
-
repocribro.controllers.admin.
role_assignment_remove
(name)¶ Remove assignment of role to user (POST handler)
-
repocribro.controllers.admin.
role_create
()¶ Create new role (POST handler)
-
repocribro.controllers.admin.
role_delete
(name)¶ Delete role (POST handler)
-
repocribro.controllers.admin.
role_detail
(name)¶ Role administration (GET handler)
-
repocribro.controllers.admin.
role_edit
(name)¶ Edit role (POST handler)
repocribro.controllers.auth¶
-
repocribro.controllers.auth.
auth
= <flask.blueprints.Blueprint object>¶ Auth controller blueprint
-
repocribro.controllers.auth.
github
()¶ Redirect to GitHub OAuth gate (GET handler)
-
repocribro.controllers.auth.
github_callback
()¶ Callback gate for GitHub OAUTH (GET handler)
-
repocribro.controllers.auth.
github_callback_get_account
(db, gh_api)¶ Processing GitHub callback action
Parameters: - db (
flask_sqlalchemy.SQLAlchemy
) – Database for storing GitHub user info - gh_api (
repocribro.github.GitHubAPI
) – GitHub API client ready for the communication
Returns: User account and flag if it’s new one
Return type: tuple of
repocribro.models.UserAccount
, bool- db (
-
repocribro.controllers.auth.
logout
()¶ Logout currently logged user (GET handler)
repocribro.controllers.core¶
-
repocribro.controllers.core.
core
= <flask.blueprints.Blueprint object>¶ Core controller blueprint
-
repocribro.controllers.core.
index
()¶ Landing page (GET handler)
-
repocribro.controllers.core.
org_detail
(login)¶ Organization detail (GET handler)
Todo: implement 410 (org deleted/archived/renamed)
-
repocribro.controllers.core.
repo_detail
(login, reponame)¶ Repo detail (GET handler)
-
repocribro.controllers.core.
repo_detail_common
(db, ext_master, repo, has_secret=False)¶ Repo detail (for GET handlers)
Todo: implement 410 (repo deleted/archived/renamed)
Hidden repo detail (GET handler)
-
repocribro.controllers.core.
repo_redir
(login)¶
-
repocribro.controllers.core.
search
(query='')¶ Search page (GET handler)
Todo: more attrs, limits & pages
-
repocribro.controllers.core.
user_detail
(login)¶ User detail (GET handler)
Todo: implement 410 (user deleted/archived/renamed)
repocribro.controllers.errors¶
-
repocribro.controllers.errors.
err_forbidden
(error)¶ Error handler for HTTP 403 - Unauthorized
-
repocribro.controllers.errors.
err_gone
(error)¶ Error handler for HTTP 410 - Gone
-
repocribro.controllers.errors.
err_internal
(error)¶ Error handler for HTTP 501 - Not Implemented
-
repocribro.controllers.errors.
err_not_found
(error)¶ Error handler for HTTP 403 - Not Found
-
repocribro.controllers.errors.
errors
= <flask.blueprints.Blueprint object>¶ Errors controller blueprint
repocribro.controllers.manage¶
-
repocribro.controllers.manage.
dashboard
()¶ Management zone dashboard (GET handler)
-
repocribro.controllers.manage.
has_good_webhook
(gh_api, repo)¶ Check webhook at GitHub for repo
Parameters: - gh_api (
repocribro.github.GitHubAPI
) – GitHub API client for communication - repo (
repocribro.models.Repository
) – Repository which webhook should be checked
Returns: If webhook is already in good shape
Return type: bool
Todo: move somewhere else, check registered events
- gh_api (
-
repocribro.controllers.manage.
manage
= <flask.blueprints.Blueprint object>¶ Manage controller blueprint
-
repocribro.controllers.manage.
organizations
()¶ List user organizations from GitHub (GET handler)
-
repocribro.controllers.manage.
repo_activate
(reponame)¶ Activate repo in app from GitHub (POST handler)
Todo: protect from activating too often
-
repocribro.controllers.manage.
repo_deactivate
(reponame)¶ Deactivate repo in app from GitHub (POST handler)
-
repocribro.controllers.manage.
repo_delete
()¶ Delete repo (in app) from GitHub (POST handler)
-
repocribro.controllers.manage.
repo_detail
(reponame)¶ Repository detail (GET handler)
-
repocribro.controllers.manage.
repo_update
(reponame)¶ Update repo info from GitHub (GET handler)
Todo: protect from updating too often
-
repocribro.controllers.manage.
repositories
()¶ List user repositories from GitHub (GET handler)
-
repocribro.controllers.manage.
update_profile
()¶ Update user info from GitHub (GET handler)
Todo: protect from updating too often
-
repocribro.controllers.manage.
update_webhook
(gh_api, repo)¶ Update webhook at GitHub for repo if needed
Parameters: - gh_api (
repocribro.github.GitHubAPI
) – GitHub API client for communication - repo (
repocribro.models.Repository
) – Repository which webhook should be updated
Returns: If webhook is now in good shape
Return type: bool
Todo: move somewhere else
- gh_api (
repocribro.ext_core¶
CoreExtension¶
-
class
repocribro.ext_core.
CoreExtension
(master, app, db)¶ Bases:
repocribro.extending.extension.Extension
-
ADMIN_URL
= None¶
-
AUTHOR
= 'Marek Suchánek'¶ Author of core extension
-
CATEGORY
= 'basic'¶ Category of core extension
-
GH_URL
= 'https://github.com/MarekSuchanek/repocribro'¶ GitHub URL of core extension
-
HOME_URL
= None¶
-
NAME
= 'core'¶ Name of core extension
-
__init__
(master, app, db)¶
-
call
(hook_name, default, *args, **kwargs)¶ Call the operation via hook name
Parameters: - hook_name (str) – Name of hook to be called
- default – Default return value if hook operation not found
- args – Positional args to be passed to the hook operation
- kwargs – Keywords args to be passed to the hook operation
Returns: Result of the operation on the requested hook
-
static
get_gh_event_processors
()¶ Get all GitHub events processors
-
static
get_gh_webhook_processors
()¶ Get all GitHub webhooks processory
-
init_blueprints
()¶ Hook operation for initiating the blueprints and registering them within repocribro Flask app
-
init_business
()¶ Init business layer (other extensions, what is needed)
-
init_container
()¶ Init service DI container of the app
-
init_filters
()¶ Hook operation for initiating the Jinja filters and registering them within Jinja env of repocribro Flask app
-
init_models
()¶ Hook operation for initiating the models and registering them within db
-
introduce
()¶ Hook operation for getting short introduction of extension (mostly for debug/log purpose)
Returns: Name of the extension Return type: str
-
static
provide_blueprints
()¶
-
static
provide_filters
()¶
-
static
provide_models
()¶
-
register_blueprints_from_list
(blueprints)¶ Registering Flask blueprints to the app
Parameters: blueprints ( list
offlask.blueprint
) – List of Flask blueprints to be registered
-
register_filters_from_dict
(filters)¶ Registering functions as Jinja filters
Parameters: filters (dict of str: function) – Dictionary where key is name of filter and value is the function serving as filter
-
view_admin_extensions
()¶ Hook operation for getting view model of the extension in order to show it in the administration of app
Returns: Extensions view for this extension Return type: repocribro.extending.helpers.ExtensionView
-
view_admin_index_tabs
(tabs_dict)¶ Prepare tabs for index view of admin controller
Parameters: tabs_dict (dict of str: repocribro.extending.helpers.ViewTab
) – Target dictionary for tabs
-
view_core_org_detail_tabs
(org, tabs_dict)¶ Prepare tabs for org detail view of core controller
Parameters: - org (
repocribro.models.Organization
) – Organization which details should be shown - tabs_dict (dict of str:
repocribro.extending.helpers.ViewTab
) – Target dictionary for tabs
- org (
-
view_core_repo_detail_tabs
(repo, tabs_dict)¶ Prepare tabs for repo detail view of core controller
Parameters: - repo (
repocribro.models.Repository
) – Repository which details should be shown - tabs_dict (dict of str:
repocribro.extending.helpers.ViewTab
) – Target dictionary for tabs
- repo (
-
view_core_search_tabs
(query, tabs_dict)¶ Prepare tabs for search view of core controller
Parameters: - query (str) – Fulltext query for the search
- tabs_dict (dict of str:
repocribro.extending.helpers.ViewTab
) – Target dictionary for tabs
-
view_core_user_detail_tabs
(user, tabs_dict)¶ Prepare tabs for user detail view of core controller
Parameters: - user (
repocribro.models.User
) – User which details should be shown - tabs_dict (dict of str:
repocribro.extending.helpers.ViewTab
) – Target dictionary for tabs
- user (
-
view_manage_dashboard_tabs
(tabs_dict)¶ Prepare tabs for dashboard view of manage controller
Parameters: tabs_dict (dict of str: repocribro.extending.helpers.ViewTab
) – Target dictionary for tabs
-
repocribro.extending¶
Extension¶
-
class
repocribro.extending.
Extension
(master, app, db)¶ Bases:
object
Generic repocribro extension class
It serves as base extension which does nothing but has prepared all the attributes and methods needed. Particular real extensions can override those attributes and methods to make so behavior and extend repocribro. It also provides some useful methods to those subclasses.
-
ADMIN_URL
= None¶ Administration URL within site (best via url_for)
-
AUTHOR
= ''¶ Author(s) of extension
-
CATEGORY
= ''¶ Category of extension (basic, security, data, ...)
-
GH_URL
= None¶ GitHub url of extension project
-
HOME_URL
= None¶ Homepage url of extension (rtd, pocoo, ...)
-
NAME
= 'unknown'¶ Name of extension
-
__init__
(master, app, db)¶ Inits the basic two parts of repocribro - flask app and DB
Parameters: - master (
ExtensionsMaster
) – Master for this extension - app (
flask.Flask
) – Flask application of repocribro - db (
flask_sqlalchemy.SQLAlchemy
) – SQLAlchemy database of repocribro - args – not used
- kwargs – not used
- master (
-
call
(hook_name, default, *args, **kwargs)¶ Call the operation via hook name
Parameters: - hook_name (str) – Name of hook to be called
- default – Default return value if hook operation not found
- args – Positional args to be passed to the hook operation
- kwargs – Keywords args to be passed to the hook operation
Returns: Result of the operation on the requested hook
-
init_blueprints
()¶ Hook operation for initiating the blueprints and registering them within repocribro Flask app
-
init_filters
()¶ Hook operation for initiating the Jinja filters and registering them within Jinja env of repocribro Flask app
-
init_models
()¶ Hook operation for initiating the models and registering them within db
-
introduce
()¶ Hook operation for getting short introduction of extension (mostly for debug/log purpose)
Returns: Name of the extension Return type: str
-
static
provide_blueprints
()¶ Extension can provide Flask blueprints to the app by this method
Returns: List of Flask blueprints provided by extension Return type: list of flask.blueprint
-
static
provide_filters
()¶ Extension can provide Jinja filters to the app by this method
Returns: Dictionary with name + function/filter pairs Return type: dict of str: function
-
static
provide_models
()¶ Extension can provide (DB) models to the app by this method
Returns: List of models provided by extension Return type: list of db.Model
-
register_blueprints_from_list
(blueprints)¶ Registering Flask blueprints to the app
Parameters: blueprints ( list
offlask.blueprint
) – List of Flask blueprints to be registered
-
register_filters_from_dict
(filters)¶ Registering functions as Jinja filters
Parameters: filters (dict of str: function) – Dictionary where key is name of filter and value is the function serving as filter
-
view_admin_extensions
()¶ Hook operation for getting view model of the extension in order to show it in the administration of app
Returns: Extensions view for this extension Return type: repocribro.extending.helpers.ExtensionView
-
ExtensionsMaster¶
-
class
repocribro.extending.
ExtensionsMaster
(*args, **kwargs)¶ Bases:
object
Collector & master of Extensions
Extension master finds and holds all the repocribro extensions and is used for calling operations on them and collecting the results.
-
ENTRYPOINT_GROUP
= 'repocribro.ext'¶ String used for looking up the extensions
-
LOAD_ERROR_MSG
= 'Extension "{}" ({}) is not making an Extension (sub)class instance. It will be ignored!'¶ Error message mask for extension load error
-
__init__
(*args, **kwargs)¶ Collects all the extensions to be mantained by this object
Parameters: - args – positional args to be passed to extensions
- kwargs – keywords args to be passed to extensions
Todo: there might be some problem with ordering of extensions
-
classmethod
_collect_extensions
(name=None)¶ Method for selecting extensions within
ENTRYPOINT_GROUP
Parameters: name (str) – Can be used to select single entrypoint/extension Returns: Generator of selected entry points Return type: pkg_resources.WorkingSet.iter_entry_points
-
call
(hook_name, default=None, *args, **kwargs)¶ Call the hook on all extensions registered
Parameters: - hook_name (str) – Name of hook to be called
- default – Default return value if hook operation not found
- args – Positional args to be passed to the hook operation
- kwargs – Keywords args to be passed to the hook operation
Returns: Result of the operation on the requested hook
-
repocribro.manage¶
-
repocribro.manage.
run
()¶ Run the CLI manager for the web application
Todo: allow extension add options & commands, separate create and run part of function
repocribro.models¶
Mixins¶
Anonymous¶
-
class
repocribro.models.
Anonymous
¶ Bases:
flask_login.mixins.AnonymousUserMixin
Anonymous (not logged) user representation
-
has_role
(role)¶ Check whether has the role
Parameters: role ( repocribro.models.RoleMixin
) – Role to be checkedReturns: False, anonymous has no roles Return type: bool
-
is_active
¶ Check whether is user active
Returns: False, anonymous is not active Return type: bool
-
owns_repo
(repo)¶ Check if user owns the repository
Parameters: repo ( repocribro.models.Repository
) – Repository which shoudl be testedReturns: False, anonymous can not own repository Return type: bool
-
rolenames
¶ Get names of all roles of that user
Returns: Empty list, anonymous has no roles Return type: list of str
-
sees_repo
(repo, has_secret=False)¶ Check if user is allowed to see the repo
Anonymous can see only public repos
Parameters: - repo (
repocribro.models.Repository
) – Repository which user want to see - has_secret (bool) – If current user knows the secret URL
Returns: If user can see repo
Return type: bool
- repo (
-
RoleMixin¶
-
class
repocribro.models.
RoleMixin
¶ Bases:
object
Mixin for models representing roles
-
__eq__
(other)¶ Equality of roles is based on names
Parameters: other ( repocribro.models.RoleMixin
or str) – Role or its name to be compared withReturns: If names are equal Return type: bool
-
__hash__
()¶ Standard hashing via name
Returns: Hash of role Return type: int
-
__ne__
(other)¶ Inequality of roles is based on names
Parameters: other ( repocribro.models.RoleMixin
or str) – Role or its name to be compared withReturns: If names are not equal Return type: bool
-
SearchableMixin¶
-
class
repocribro.models.
SearchableMixin
¶ Bases:
object
Mixin for models that support fulltext query
-
classmethod
fulltext_query
(query_str, db_query)¶ Add fulltext filter to the DB query
Parameters: - query_str (str) – String to be queried
- db_query (
sqlalchemy.orm.query.Query
) – Database query object
Returns: Query with fulltext filter added
Return type: sqlalchemy.orm.query.Query
-
classmethod
UserMixin¶
-
class
repocribro.models.
UserMixin
¶ Bases:
flask_login.mixins.UserMixin
-
has_role
(role)¶ Check whether has the role
Parameters: role (str) – Role to be checked Returns: If user has a role Return type: bool
-
is_active
¶ Check whether is user active
Returns: If user is active (can login) Return type: bool
-
owns_repo
(repo)¶ Check if user owns the repository
Parameters: repo ( repocribro.models.Repository
) – Repository which shoudl be testedReturns: If user owns repo Return type: bool
-
rolenames
¶ Get names of all roles of that user
Returns: List of names of roles of user Return type: list of str
-
sees_repo
(repo, has_secret=False)¶ Check if user is allowed to see the repo
Must be admin or owner to see not public repo
Parameters: - repo (
repocribro.models.Repository
) – Repository which user want to see - has_secret (bool) – If current user knows the secret URL
Returns: If user can see repo
Return type: bool
- repo (
-
Models¶
Commit¶
-
class
repocribro.models.
Commit
(sha, message, author_name, author_email, distinct, push)¶ Bases:
flask_sqlalchemy.Model
,repocribro.models.SearchableMixin
Commit from GitHub
-
__init__
(sha, message, author_name, author_email, distinct, push)¶
-
__repr__
()¶ Standard string representation of DB object
Returns: Unique string representation Return type: str
-
_sa_class_manager
= <ClassManager of <class 'repocribro.models.Commit'> at 7fc37756f188>¶
The git author’s email address.
The git author’s name.
-
static
create_from_dict
(commit_dict, push)¶ Create new commit from GitHub and additional data
Parameters: - commit_dict (dict) – GitHub data containing commit
- push (
repocribro.models.Push
) – Push where this commit belongs
Returns: Created new commit
Return type: repocribro.models.Commit
Todo: verify, there are some conflict in GitHub docs
-
distinct
¶ Whether this commit is distinct from any that have been pushed before.
-
id
¶ Unique identifier of the commit
-
message
¶ The commit message.
-
push
¶ Push where the commit belongs to
-
push_id
¶ ID of push where the commit belongs to
-
sha
¶ The SHA of the commit.
-
Organization¶
-
class
repocribro.models.
Organization
(github_id, login, email, name, company, location, description, blog_url, avatar_url)¶ Bases:
repocribro.models.RepositoryOwner
,repocribro.models.SearchableMixin
Organization from GitHub
-
__init__
(github_id, login, email, name, company, location, description, blog_url, avatar_url)¶
-
__repr__
()¶ Standard string representation of DB object
Returns: Unique string representation Return type: str
-
_sa_class_manager
= <ClassManager of <class 'repocribro.models.Organization'> at 7fc377613138>¶
-
avatar_url
¶
-
blog_url
¶
-
company
¶
-
static
create_from_dict
(org_dict)¶ Create new organization from GitHub data
Parameters: org_dict (dict) – GitHub data containing organization Returns: Created new organization Return type: repocribro.models.Organization
-
description
¶
-
email
¶
-
github_id
¶
-
id
¶
-
location
¶
-
login
¶
-
name
¶
-
repositories
¶
-
type
¶
-
Push¶
-
class
repocribro.models.
Push
(github_id, ref, after, before, size, distinct_size, timestamp, sender_login, sender_id, repository)¶ Bases:
flask_sqlalchemy.Model
,repocribro.models.SearchableMixin
Push from GitHub
-
__init__
(github_id, ref, after, before, size, distinct_size, timestamp, sender_login, sender_id, repository)¶
-
__repr__
()¶ Standard string representation of DB object
Returns: Unique string representation Return type: str
-
_sa_class_manager
= <ClassManager of <class 'repocribro.models.Push'> at 7fc377613bd8>¶
-
after
¶ The SHA of the most recent commit on ref after the push. (HEAD)
-
before
¶ The SHA of the most recent commit on ref before the push.
-
commits
¶ Commits within this push
-
static
create_from_dict
(push_dict, sender_dict, repo, timestamp=None)¶ Create new push from GitHub and additional data
This also creates commits of this push
Parameters: - push_dict (dict) – GitHub data containing push
- sender_dict (dict) – GitHub data containing sender
- repo (
repocribro.models.Repository
) – Repository where this push belongs
Returns: Created new push
Return type: repocribro.models.Push
-
distinct_size
¶ The number of distinct commits in the push.
-
github_id
¶ GitHub Push ID
-
id
¶ Unique identifier of the push
-
ref
¶ The full Git ref that was pushed.
-
repository
¶ Repository where push belongs to
-
repository_id
¶ ID of the repository where push belongs to
-
sender_id
¶ ID of the sender
-
sender_login
¶ Login of the sender
-
size
¶ The number of commits in the push.
-
timestamp
¶ Timestamp of push (when it was registered)
-
Role¶
-
class
repocribro.models.
Role
(name, description)¶ Bases:
flask_sqlalchemy.Model
,repocribro.models.RoleMixin
User account role in the application
-
__init__
(name, description)¶
-
__repr__
()¶ Standard string representation of DB object
Returns: Unique string representation Return type: str
-
_sa_class_manager
= <ClassManager of <class 'repocribro.models.Role'> at 7fc3775fd228>¶
-
description
¶ Description (purpose, notes, ...) of the role
-
id
¶ Unique identifier of the role
-
name
¶ Unique name of the role
-
user_accounts
¶ User accounts assigned to the role
-
Release¶
-
class
repocribro.models.
Release
(github_id, tag_name, created_at, published_at, url, prerelease, draft, name, body, author_id, author_login, sender_login, sender_id, repository)¶ Bases:
flask_sqlalchemy.Model
,repocribro.models.SearchableMixin
Release from GitHub
-
__init__
(github_id, tag_name, created_at, published_at, url, prerelease, draft, name, body, author_id, author_login, sender_login, sender_id, repository)¶
-
__repr__
()¶ Standard string representation of DB object
Returns: Unique string representation Return type: str
-
_sa_class_manager
= <ClassManager of <class 'repocribro.models.Release'> at 7fc37756f6d8>¶
ID of author
Login of author
-
body
¶ Body with some description
-
static
create_from_dict
(release_dict, sender_dict, repo)¶ Create new release from GitHub and additional data
Parameters: - release_dict (dict) – GitHub data containing release
- sender_dict (dict) – GitHub data containing sender
- repo (
repocribro.models.Repository
) – Repository where this release belongs
Returns: Created new release
Return type: repocribro.models.Release
-
created_at
¶ Timestamp when the release was created
-
draft
¶ Flag if it’s just a draft
-
github_id
¶ GitHub unique identifier
-
id
¶ Unique identifier of the release
-
name
¶ Name
-
prerelease
¶ Flag if it’s just a prerelease
-
published_at
¶ Timestamp when the release was published
-
repository
¶ Repository where release belongs to
-
repository_id
¶ ID of the repository where release belongs to
-
sender_id
¶ ID of sender
-
sender_login
¶ Login of sender
-
tag_name
¶ Tag of the release
-
url
¶ URL to release page
-
Repository¶
-
class
repocribro.models.
Repository
(github_id, fork_of, full_name, name, languages, url, description, private, webhook_id, owner, visibility_type, secret=None)¶ Bases:
flask_sqlalchemy.Model
,repocribro.models.SearchableMixin
Repository from GitHub
-
VISIBILITY_HIDDEN
= 2¶ Constant representing hidden visibility within app
-
VISIBILITY_PRIVATE
= 1¶ Constant representing private visibility within app
-
VISIBILITY_PUBLIC
= 0¶ Constant representing public visibility within app
-
__init__
(github_id, fork_of, full_name, name, languages, url, description, private, webhook_id, owner, visibility_type, secret=None)¶
-
__repr__
()¶ Standard string representation of DB object
Returns: Unique string representation Return type: str
-
_sa_class_manager
= <ClassManager of <class 'repocribro.models.Repository'> at 7fc377613818>¶
-
static
create_from_dict
(repo_dict, owner, webhook_id=None, visibility_type=0, secret=None)¶ Create new repository from GitHub and additional data
Parameters: - repo_dict (dict) – GitHub data containing repository
- owner (
repocribro.model.RepositoryOwner
) – Owner of this repository - webhook_id (int) – ID of registered webhook (if available)
- visibility_type (int) – Visibility type within app (default: public)
- secret (str) – Secret for hidden URL (if available)
Returns: Created new repository
Return type: repocribro.models.Repository
Todo: work with fork_of somehow
-
description
¶
-
events_updated
()¶ Set that now was performed last events update of repo
Todo: How about some past events before adding to app?
-
fork_of
¶ GitHub id of repository which this is fork of
-
full_name
¶ Full name (owner login + repository name)
-
generate_secret
()¶ Generate new unique secret code for repository
-
github_id
¶ GitHub unique identifier
-
id
¶ Unique identifier of the repository
Check if repository is hidden within app
-
is_private
¶ Check if repository is private within app
-
is_public
¶ Check if repository is public within app
-
languages
¶
-
last_event
¶
-
static
make_full_name
(login, reponame)¶ Create full name from owner login name and repository name
Parameters: - login (str) – Owner login
- reponame (str) – Name of repository (without owner login)
Returns: Full name of repository
Return type: str
-
name
¶
-
owner
¶ Owner of repository
-
owner_id
¶
-
owner_login
¶ Get owner login from full name of repository
Returns: Owner login Return type: str
-
private
¶
-
pushes
¶ Registered pushes to repository
-
releases
¶ Registered releases for repository
-
secret
¶
-
update_from_dict
(repo_dict)¶ Update repository attributes from GitHub data dict
Parameters: repo_dict (dict) – GitHub data containing repository
-
url
¶
-
visibility_type
¶
-
webhook_id
¶
-
User¶
-
class
repocribro.models.
User
(github_id, login, email, name, company, location, bio, blog_url, avatar_url, hireable, user_account)¶ Bases:
repocribro.models.RepositoryOwner
,repocribro.models.SearchableMixin
User from GitHub
-
__init__
(github_id, login, email, name, company, location, bio, blog_url, avatar_url, hireable, user_account)¶
-
__repr__
()¶ Standard string representation of DB object
Returns: Unique string representation Return type: str
-
_sa_class_manager
= <ClassManager of <class 'repocribro.models.User'> at 7fc3775fdb88>¶
-
avatar_url
¶
-
blog_url
¶
-
company
¶
-
static
create_from_dict
(user_dict, user_account)¶ Create new user from GitHub data and related user account
Parameters: - user_dict (dict) – GitHub data containing user
- user_account (
repocribro.models.UserAccount
) – User account in app for GH user
Returns: Created new user
Return type: repocribro.models.User
-
description
¶
-
email
¶
-
github_id
¶
-
hireable
¶ Flag whether is user hireable
-
id
¶
-
location
¶
-
login
¶
-
name
¶
-
repositories
¶
-
type
¶
-
update_from_dict
(user_dict)¶ Update user from GitHub data
Parameters: user_dict (dict) – GitHub data containing user
-
user_account
¶ User’s account within app
-
user_account_id
¶ ID of user’s account within app
-
UserAccount¶
-
class
repocribro.models.
UserAccount
(**kwargs)¶ Bases:
flask_sqlalchemy.Model
,repocribro.models.UserMixin
,repocribro.models.SearchableMixin
UserAccount in the repocribro app
-
__init__
(**kwargs)¶ A simple constructor that allows initialization from kwargs.
Sets attributes on the constructed instance using the names and values in
kwargs
.Only keys that are present as attributes of the instance’s class are allowed. These could be, for example, any mapped columns or relationships.
-
__repr__
()¶ Standard string representation of DB object
Returns: Unique string representation Return type: str
-
_sa_class_manager
= <ClassManager of <class 'repocribro.models.UserAccount'> at 7fc37765cdb8>¶
-
active
¶ Flag if the account is active or banned
-
created_at
¶ Timestamp where account was created
-
github_user
¶ Relation to the GitHub user connected to account
-
id
¶ Unique identifier of the user account
-
login
¶ Get login name for user account from related GH user
Returns: Login name Return type: str
-
roles
¶ Roles assigned to the user account
-
repocribro.repocribro¶
-
repocribro.repocribro.
AUTHOR
= 'Marek Suchánek'¶ Author of the application
-
repocribro.repocribro.
DEFAULT_CONFIG_FILES
= ['config/app.cfg', 'config/auth.cfg', 'config/db.cfg']¶ Paths to default configuration files
-
class
repocribro.repocribro.
DI_Container
¶ Simple container of services for web app
Variables: - factories – Factories of services
- singletons – Singletons (shared objects) of services
-
__init__
()¶ Prepare dict for storing services and factories
-
get
(what, *args, **kwargs)¶ Retrieve service from the container
Parameters: - what (str) – Name of the service to get
- args – Positional arguments passed to factory
- kwargs – Keyword arguments passed to factory
Returns: The service or None
-
set_factory
(name, factory)¶ Set service factory (callable for creating instances)
Parameters: - name (str) – Name of the service
- factory (callable) – Function or callable object creating service instance
-
set_singleton
(name, singleton)¶ Set service as singleton (shared object)
Parameters: - name (str) – Name of the service
- singleton (object) – The object to be shared as singleton
-
repocribro.repocribro.
PROG_NAME
= 'repocribro'¶ Name of the application
-
repocribro.repocribro.
RELEASE
= '0.1'¶ Actual release tag
-
class
repocribro.repocribro.
Repocribro
¶ Repocribro is Flask web application
Variables: container – Service container for the app -
__init__
()¶ Setup Flask app and prepare service container
-
-
repocribro.repocribro.
VERSION
= '0.1'¶ Actual version
-
repocribro.repocribro.
create_app
(cfg_files='DEFAULT')¶ Factory for making the web Flask application
Parameters: cfg_files – Single or more config file(s) Returns: Constructed web application Return type: repocribro.repocribro.Repocribro
repocribro.security¶
-
class
repocribro.security.
Permissions
¶ Class for prividing various permissions
Todo: allow extensions provide permissions to others -
__dict__
= mappingproxy({'__module__': 'repocribro.security', 'admin_role': <Permission needs={Need(method='role', value='admin')} excludes=set()>, '__weakref__': <attribute '__weakref__' of 'Permissions' objects>, '__doc__': ' Class for prividing various permissions\n\n :todo: allow extensions provide permissions to others\n ', '__dict__': <attribute '__dict__' of 'Permissions' objects>})¶
-
__module__
= 'repocribro.security'¶
-
__weakref__
¶ list of weak references to the object (if defined)
-
admin_role
= <Permission needs={Need(method='role', value='admin')} excludes=set()>¶ Administrator role permission
-
-
repocribro.security.
clear_session
(*args)¶ Simple helper for clearing variables from session
Parameters: args – names of session variables to remove
-
repocribro.security.
init_login_manager
(db)¶ Init security extensions (login manager and principal)
Parameters: db ( flask_sqlalchemy.SQLAlchemy
) – Database which stores user accounts and rolesReturns: Login manager and principal extensions Return type: ( flask_login.LoginManager
,flask_principal.Principal
-
repocribro.security.
login
(user_account)¶ Login desired user into the app
Parameters: user_account ( repocribro.models.UserAccount
) – User account to be logged in
-
repocribro.security.
logout
()¶ Logout the current user from the app
-
repocribro.security.
on_identity_loaded
(sender, identity)¶ Principal helper for loading the identity of logged user
Parameters: - sender – Sender of the signal
- identity (
flask_principal.Identity
) – Identity container
-
repocribro.security.
permissions
= <repocribro.security.Permissions object>¶ All permissions in the app