scaffold, prototype scripts
This commit is contained in:
commit
ecf989da73
|
@ -0,0 +1,56 @@
|
|||
# Byte-compiled / optimized / DLL files
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
*$py.class
|
||||
|
||||
# C extensions
|
||||
*.so
|
||||
|
||||
# Distribution / packaging
|
||||
.Python
|
||||
env/
|
||||
build/
|
||||
develop-eggs/
|
||||
dist/
|
||||
downloads/
|
||||
eggs/
|
||||
.eggs/
|
||||
lib/
|
||||
lib64/
|
||||
parts/
|
||||
sdist/
|
||||
var/
|
||||
*.egg-info/
|
||||
.installed.cfg
|
||||
*.egg
|
||||
|
||||
|
||||
# dotenv
|
||||
.env
|
||||
|
||||
# Rope project settings
|
||||
.ropeproject
|
||||
|
||||
# Vim
|
||||
Session.vim
|
||||
|
||||
# Pycharm
|
||||
.idea
|
||||
|
||||
# junk
|
||||
blocks.json
|
||||
|
||||
# sqlite db for testing
|
||||
local.db
|
||||
/tests/fastest-test.sh
|
||||
/tests/sbds-install.sh
|
||||
/tests/test.sh
|
||||
/tests/fast-test.sh
|
||||
/tests/sync.sh
|
||||
/tests/failed_blocks/
|
||||
/envd
|
||||
!/sbds.egg-info/
|
||||
/tests/envdir-to-envfile.sh
|
||||
*.db
|
||||
envfile
|
||||
/deploy
|
|
@ -0,0 +1,112 @@
|
|||
# Byte-compiled / optimized / DLL files
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
*$py.class
|
||||
|
||||
# C extensions
|
||||
*.so
|
||||
|
||||
# Distribution / packaging
|
||||
.Python
|
||||
env/
|
||||
build/
|
||||
develop-eggs/
|
||||
dist/
|
||||
downloads/
|
||||
eggs/
|
||||
.eggs/
|
||||
lib/
|
||||
lib64/
|
||||
parts/
|
||||
sdist/
|
||||
var/
|
||||
*.egg-info/
|
||||
.installed.cfg
|
||||
*.egg
|
||||
|
||||
# PyInstaller
|
||||
# Usually these files are written by a python script from a template
|
||||
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
||||
*.manifest
|
||||
*.spec
|
||||
|
||||
# Installer logs
|
||||
pip-log.txt
|
||||
pip-delete-this-directory.txt
|
||||
|
||||
# Unit tests / coverage reports
|
||||
htmlcov/
|
||||
.tox/
|
||||
.coverage
|
||||
.coverage.*
|
||||
.cache
|
||||
nosetests.xml
|
||||
coverage.xml
|
||||
*,cover
|
||||
.hypothesis/
|
||||
|
||||
# Translations
|
||||
*.mo
|
||||
*.pot
|
||||
|
||||
# Django stuff:
|
||||
*.log
|
||||
local_settings.py
|
||||
|
||||
# Flask stuff:
|
||||
instance/
|
||||
.webassets-cache
|
||||
|
||||
# Scrapy stuff:
|
||||
.scrapy
|
||||
|
||||
# Sphinx documentation
|
||||
docs/_build/
|
||||
|
||||
# PyBuilder
|
||||
target/
|
||||
|
||||
# IPython Notebook
|
||||
.ipynb_checkpoints
|
||||
|
||||
# pyenv
|
||||
.python-version
|
||||
|
||||
# celery beat schedule file
|
||||
celerybeat-schedule
|
||||
|
||||
# dotenv
|
||||
.env
|
||||
envfile
|
||||
|
||||
# virtualenv
|
||||
venv/
|
||||
ENV/
|
||||
|
||||
# Spyder project settings
|
||||
.spyderproject
|
||||
|
||||
# Rope project settings
|
||||
.ropeproject
|
||||
|
||||
# Vim
|
||||
Session.vim
|
||||
|
||||
# Pycharm
|
||||
.idea
|
||||
|
||||
# sqlite db for testing
|
||||
*.db
|
||||
/tests/fast-test.sh
|
||||
/tests/fastest-test.sh
|
||||
/tests/sbds-install.sh
|
||||
/tests/test.sh
|
||||
/tests/sync.sh
|
||||
/tests/failed_blocks/
|
||||
tests/failed_blocks/
|
||||
/envdir/
|
||||
/sbds.egg-info/
|
||||
/envd/
|
||||
/tests/envdir-to-envfile.sh
|
||||
/deploy/
|
||||
/scripts/hive.sqlite
|
|
@ -0,0 +1,12 @@
|
|||
FROM python:3.5.3
|
||||
MAINTAINER furion <furion@steemit.com>
|
||||
|
||||
COPY . /src
|
||||
WORKDIR /src
|
||||
|
||||
RUN pip install ipython
|
||||
RUN pip install -r requirements.txt
|
||||
|
||||
EXPOSE 5000
|
||||
|
||||
#CMD ["python", "app.py"]
|
|
@ -0,0 +1,21 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2017 Steemit Inc.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
|
@ -0,0 +1,47 @@
|
|||
SHELL := /bin/bash
|
||||
ROOT_DIR := $(shell pwd)
|
||||
|
||||
PROJECT_NAME := hive
|
||||
PROJECT_DOCKER_TAG := steemit/$(PROJECT_NAME)
|
||||
PROJECT_DOCKER_RUN_ARGS := -p8080:8080
|
||||
|
||||
default: build
|
||||
|
||||
.PHONY: test run test-without-lint test-pylint fmt test-without-build build
|
||||
|
||||
build:
|
||||
docker build -t $(PROJECT_DOCKER_TAG) .
|
||||
|
||||
run:
|
||||
docker run $(PROJECT_DOCKER_RUN_ARGS) $(PROJECT_DOCKER_TAG)
|
||||
|
||||
test: test-without-build build
|
||||
|
||||
test-without-build: test-without-lint test-pylint
|
||||
|
||||
|
||||
test-without-lint:
|
||||
py.test tests
|
||||
|
||||
test-pylint:
|
||||
py.test --pylint -m pylint $(PROJECT_NAME)
|
||||
|
||||
fmt:
|
||||
yapf --recursive --in-place --style pep8 .
|
||||
autopep8 --recursive --in-place .
|
||||
|
||||
requirements.txt: serve.py
|
||||
pip freeze > $@
|
||||
|
||||
clean: clean-build clean-pyc
|
||||
|
||||
clean-build:
|
||||
rm -fr build/ dist/ *.egg-info .eggs/ .tox/ __pycache__/ .cache/ .coverage htmlcov src
|
||||
|
||||
clean-pyc:
|
||||
find . -name '*.pyc' -exec rm -f {} +
|
||||
find . -name '*.pyo' -exec rm -f {} +
|
||||
find . -name '*~' -exec rm -f {} +
|
||||
|
||||
install: clean
|
||||
pip install -e .
|
|
@ -0,0 +1,24 @@
|
|||
`hivemind` is an off-chain consensus layer for Steem communities and API server for social features like feeds and follows.
|
||||
|
||||
It is primarily concerned with indexing specific `custom_json` namespaces but also watches for posts, votes, and account creations.
|
||||
|
||||
[Community Spec Draft](https://github.com/steemit/condenser/wiki/Community-Spec-%5BDRAFT%5D)
|
||||
|
||||
|
||||
Upon reindexing/following the blockchain, the following tables are populated:
|
||||
|
||||
### Core
|
||||
|
||||
- `hive_blocks`: basic linked list of blocks to save current head block and ensure sequential processing
|
||||
- `hive_accounts`: basic account index. may be supplanted with cached data
|
||||
- `hive_posts`: main post index. contains core immutable metadata as well as community states
|
||||
- `hive_follows`: all follows and their creation date
|
||||
- `hive_reblogs`: all reblog actions (account, post, date)
|
||||
- `hive_posts_cache`: updated with latest state of posts as new blocks come in (removing need to query steemd)
|
||||
|
||||
### Community
|
||||
|
||||
- `hive_communities`: registered community data
|
||||
- `hive_members`: roles of accounts within each community, and metadata
|
||||
- `hive_flags`: track all community flag operations for mods to review
|
||||
- `hive_modlog`: tracks all `hivemind` related operations for auditability
|
|
@ -0,0 +1,12 @@
|
|||
pytest
|
||||
pytest-runner
|
||||
pytest-pylint
|
||||
pep8
|
||||
yapf
|
||||
sphinx
|
||||
recommonmark
|
||||
sphinxcontrib-restbuilder
|
||||
sphinxcontrib-programoutput
|
||||
pytest-console-scripts
|
||||
sphinxcontrib-napoleon
|
||||
sphinx_rtd_theme
|
|
@ -0,0 +1 @@
|
|||
# coding=utf-8
|
|
@ -0,0 +1,153 @@
|
|||
import json
|
||||
from typing import Union
|
||||
|
||||
from steem import Steem
|
||||
from steem.account import Account
|
||||
from steembase.operations import CustomJson
|
||||
|
||||
|
||||
class Community:
|
||||
""" Community is an extension of steem.commit.Commit class. It allows you to construct
|
||||
various community related `custom_json` operations, and commit them onto the blockchain.
|
||||
|
||||
Args:
|
||||
community_name (str): Community to operate in.
|
||||
account_name (str): Account to perform actions with.
|
||||
steem_instance (Steem): steem.Steem instance. If empty, a default Steem instance will be created on the fly.
|
||||
All arguments passed to Community will be inherited by this new Steem instance as well. (ie. `no_broadcast`).
|
||||
|
||||
Example:
|
||||
You can pass arguments to Steem instance trough Community initializer:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
community = Community('my_community_name', no_broadcast=True) # simulation mode
|
||||
|
||||
"""
|
||||
|
||||
_roles = ['admin', 'moderator', 'poster']
|
||||
_valid_settings = ['name', 'about', 'description', 'language', 'nsfw']
|
||||
|
||||
def __init__(self, community_name: str, account_name: str, steem_instance: Steem = None, **kwargs):
|
||||
self.steem = steem_instance or Steem(**kwargs)
|
||||
self.community = community_name
|
||||
self.account = account_name
|
||||
|
||||
def create(self, community_type: str = 'public', admins: Union[str, list] = None):
|
||||
""" Create a new community.
|
||||
|
||||
This method will upgrade an existing STEEM account into a new community.
|
||||
|
||||
Args:
|
||||
community_type: Can be **public** (default) or **restricted**.
|
||||
admins: A single username, or a list of users who will be community Admins.
|
||||
If left empty, the community owner will be assigned as a single admin. Can be modified later.
|
||||
"""
|
||||
# validate account and community name
|
||||
Account(self.account)
|
||||
assert self.community == self.account
|
||||
# todo: check if community already exists
|
||||
|
||||
if type(admins) == str:
|
||||
admins = [admins]
|
||||
if not admins:
|
||||
admins = [self.community]
|
||||
|
||||
op = self._op(action='create',
|
||||
type=community_type,
|
||||
admins=admins)
|
||||
return self._commit(op)
|
||||
|
||||
def update_settings(self, **settings):
|
||||
# sanitize the settings to valid keys
|
||||
settings = {k: v for k, v in settings.items() if k in self._valid_settings}
|
||||
op = self._op(action='update_settings', settings=settings)
|
||||
return self._commit(op)
|
||||
|
||||
def add_users(self, account_names: Union[str, list], role: str):
|
||||
""" Add user to the community in the specified role.
|
||||
|
||||
Args:
|
||||
account_names (str, list): Steem username(s) of the account we are adding to the community.
|
||||
role (str): Role we are adding this user as. Can be admin, moderator or poster.
|
||||
|
||||
"""
|
||||
return self._add_or_remove_users(account_names, role, 'add')
|
||||
|
||||
def remove_users(self, account_names: Union[str, list], role: str):
|
||||
""" Opposite of `add_user`. """
|
||||
return self._add_or_remove_users(account_names, role, 'remove')
|
||||
|
||||
def _add_or_remove_users(self, account_names: Union[str, list], role: str, action: str):
|
||||
""" Implementation for adding/removing users to communities under various roles. """
|
||||
if type(account_names) == str:
|
||||
account_names = [account_names]
|
||||
|
||||
if role not in self._roles:
|
||||
raise ValueError('Invalid role "%s", needs to be either: %s' % (role, ', '.join(self._roles)))
|
||||
|
||||
action_name = '{0}_{1}s'.format(action, role)
|
||||
op = self._op(action=action_name, accounts=account_names)
|
||||
return self._commit(op)
|
||||
|
||||
def set_user_title(self, account_name: str, title: str):
|
||||
""" Set a title for given user. """
|
||||
op = self._op(action='set_user_title', account=account_name, title=title)
|
||||
return self._commit(op)
|
||||
|
||||
def mute_user(self, account_name: str):
|
||||
op = self._op(action='mute_user', account=account_name)
|
||||
return self._commit(op)
|
||||
|
||||
def unmute_user(self, account_name: str):
|
||||
op = self._op(action='unmute_user', account=account_name)
|
||||
return self._commit(op)
|
||||
|
||||
def mute_post(self, author: str, permlink: str, notes: str):
|
||||
op = self._op(action='mute_post', author=author, permlink=permlink, notes=notes)
|
||||
return self._commit(op)
|
||||
|
||||
def unmute_post(self, author: str, permlink: str, notes: str):
|
||||
op = self._op(action='unmute_post', author=author, permlink=permlink, notes=notes)
|
||||
return self._commit(op)
|
||||
|
||||
def pin_post(self, author: str, permlink: str):
|
||||
op = self._op(action='pin_post', author=author, permlink=permlink)
|
||||
return self._commit(op)
|
||||
|
||||
def unpin_post(self, author: str, permlink: str):
|
||||
op = self._op(action='unpin_post', author=author, permlink=permlink)
|
||||
return self._commit(op)
|
||||
|
||||
def flag_post(self, author: str, permlink: str, comment: str):
|
||||
op = self._op(action='flag_post', author=author, permlink=permlink, comment=comment)
|
||||
return self._commit(op)
|
||||
|
||||
def _commit(self, community_op: Union[list, str]):
|
||||
""" Construct and commit a community *custom_json* operation to the blockchain. """
|
||||
if type(community_op) == str:
|
||||
community_op = json.loads(community_op)
|
||||
|
||||
op = CustomJson(
|
||||
**{'json': community_op,
|
||||
'required_auths': [],
|
||||
'required_posting_auths': [self.account],
|
||||
'id': 'com.steemit.community'})
|
||||
return self.steem.commit.finalizeOp(op, self.account, 'posting')
|
||||
|
||||
def _op(self, action: str, **params):
|
||||
""" Generate a standard data structure for community *custom_json* operations. """
|
||||
return [action, {
|
||||
'community': self.community,
|
||||
**params
|
||||
}]
|
||||
|
||||
def _check_permissions(self, action, account_name):
|
||||
""" Check if this account has the right to perform this action within the community.
|
||||
Should be called as helper in most methods.
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
pass
|
|
@ -0,0 +1,407 @@
|
|||
[MASTER]
|
||||
|
||||
# Specify a configuration file.
|
||||
#rcfile=
|
||||
|
||||
# Python code to execute, usually for sys.path manipulation such as
|
||||
# pygtk.require().
|
||||
#init-hook=
|
||||
|
||||
# Add files or directories to the blacklist. They should be base names, not
|
||||
# paths.
|
||||
ignore=CVS
|
||||
|
||||
# Add files or directories matching the regex patterns to the blacklist. The
|
||||
# regex matches against base names, not paths.
|
||||
ignore-patterns=
|
||||
|
||||
# Pickle collected data for later comparisons.
|
||||
persistent=yes
|
||||
|
||||
# List of plugins (as comma separated values of python modules names) to load,
|
||||
# usually to register additional checkers.
|
||||
load-plugins=
|
||||
|
||||
# Use multiple processes to speed up Pylint.
|
||||
jobs=1
|
||||
|
||||
# Allow loading of arbitrary C extensions. Extensions are imported into the
|
||||
# active Python interpreter and may run arbitrary code.
|
||||
unsafe-load-any-extension=no
|
||||
|
||||
# A comma-separated list of package or module names from where C extensions may
|
||||
# be loaded. Extensions are loading into the active Python interpreter and may
|
||||
# run arbitrary code
|
||||
extension-pkg-whitelist=
|
||||
|
||||
# Allow optimization of some AST trees. This will activate a peephole AST
|
||||
# optimizer, which will apply various small optimizations. For instance, it can
|
||||
# be used to obtain the result of joining multiple strings with the addition
|
||||
# operator. Joining a lot of strings can lead to a maximum recursion error in
|
||||
# Pylint and this flag can prevent that. It has one side effect, the resulting
|
||||
# AST will be different than the one from reality. This option is deprecated
|
||||
# and it will be removed in Pylint 2.0.
|
||||
optimize-ast=no
|
||||
|
||||
|
||||
[MESSAGES CONTROL]
|
||||
|
||||
# Only show warnings with the listed confidence levels. Leave empty to show
|
||||
# all. Valid levels: HIGH, INFERENCE, INFERENCE_FAILURE, UNDEFINED
|
||||
confidence=
|
||||
|
||||
# Enable the message, report, category or checker with the given id(s). You can
|
||||
# either give multiple identifier separated by comma (,) or put this option
|
||||
# multiple time (only on the command line, not in the configuration file where
|
||||
# it should appear only once). See also the "--disable" option for examples.
|
||||
#enable=
|
||||
|
||||
# Disable the message, report, category or checker with the given id(s). You
|
||||
# can either give multiple identifiers separated by comma (,) or put this
|
||||
# option multiple times (only on the command line, not in the configuration
|
||||
# file where it should appear only once).You can also use "--disable=all" to
|
||||
# disable everything first and then reenable specific checks. For example, if
|
||||
# you want to run only the similarities checker, you can use "--disable=all
|
||||
# --enable=similarities". If you want to run only the classes checker, but have
|
||||
# no Warning level messages displayed, use"--disable=all --enable=classes
|
||||
# --disable=W"
|
||||
disable=range-builtin-not-iterating,filter-builtin-not-iterating,raising-string,no-absolute-import,round-builtin,old-raise-syntax,nonzero-method,hex-method,import-star-module-level,zip-builtin-not-iterating,delslice-method,basestring-builtin,coerce-builtin,file-builtin,unicode-builtin,unpacking-in-except,apply-builtin,print-statement,parameter-unpacking,next-method-called,indexing-exception,reduce-builtin,reload-builtin,map-builtin-not-iterating,old-octal-literal,backtick,old-ne-operator,intern-builtin,suppressed-message,raw_input-builtin,execfile-builtin,old-division,buffer-builtin,dict-view-method,dict-iter-method,metaclass-assignment,useless-suppression,cmp-method,input-builtin,standarderror-builtin,unichr-builtin,cmp-builtin,long-suffix,getslice-method,long-builtin,xrange-builtin,using-cmp-argument,setslice-method,oct-method,coerce-method
|
||||
|
||||
|
||||
[REPORTS]
|
||||
|
||||
# Set the output format. Available formats are text, parseable, colorized, msvs
|
||||
# (visual studio) and html. You can also give a reporter class, eg
|
||||
# mypackage.mymodule.MyReporterClass.
|
||||
output-format=text
|
||||
|
||||
# Put messages in a separate file for each module / package specified on the
|
||||
# command line instead of printing them on stdout. Reports (if any) will be
|
||||
# written in a file name "pylint_global.[txt|html]". This option is deprecated
|
||||
# and it will be removed in Pylint 2.0.
|
||||
files-output=no
|
||||
|
||||
# Tells whether to display a full report or only the messages
|
||||
reports=yes
|
||||
|
||||
# Python expression which should return a note less than 10 (10 is the highest
|
||||
# note). You have access to the variables errors warning, statement which
|
||||
# respectively contain the number of errors / warnings messages and the total
|
||||
# number of statements analyzed. This is used by the global evaluation report
|
||||
# (RP0004).
|
||||
evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10)
|
||||
|
||||
# Template used to display messages. This is a python new-style format string
|
||||
# used to format the message information. See doc for all details
|
||||
#msg-template=
|
||||
|
||||
|
||||
[BASIC]
|
||||
|
||||
# Good variable names which should always be accepted, separated by a comma
|
||||
good-names=i,j,k,ex,Run,_
|
||||
|
||||
# Bad variable names which should always be refused, separated by a comma
|
||||
bad-names=foo,bar,baz,toto,tutu,tata
|
||||
|
||||
# Colon-delimited sets of names that determine each other's naming style when
|
||||
# the name regexes allow several styles.
|
||||
name-group=
|
||||
|
||||
# Include a hint for the correct naming format with invalid-name
|
||||
include-naming-hint=no
|
||||
|
||||
# List of decorators that produce properties, such as abc.abstractproperty. Add
|
||||
# to this list to register other decorators that produce valid properties.
|
||||
property-classes=abc.abstractproperty
|
||||
|
||||
# Regular expression matching correct module names
|
||||
module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$
|
||||
|
||||
# Naming hint for module names
|
||||
module-name-hint=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$
|
||||
|
||||
# Regular expression matching correct argument names
|
||||
argument-rgx=[a-z_][a-z0-9_]{2,30}$
|
||||
|
||||
# Naming hint for argument names
|
||||
argument-name-hint=[a-z_][a-z0-9_]{2,30}$
|
||||
|
||||
# Regular expression matching correct method names
|
||||
method-rgx=[a-z_][a-z0-9_]{2,30}$
|
||||
|
||||
# Naming hint for method names
|
||||
method-name-hint=[a-z_][a-z0-9_]{2,30}$
|
||||
|
||||
# Regular expression matching correct function names
|
||||
function-rgx=[a-z_][a-z0-9_]{2,30}$
|
||||
|
||||
# Naming hint for function names
|
||||
function-name-hint=[a-z_][a-z0-9_]{2,30}$
|
||||
|
||||
# Regular expression matching correct inline iteration names
|
||||
inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$
|
||||
|
||||
# Naming hint for inline iteration names
|
||||
inlinevar-name-hint=[A-Za-z_][A-Za-z0-9_]*$
|
||||
|
||||
# Regular expression matching correct attribute names
|
||||
attr-rgx=[a-z_][a-z0-9_]{2,30}$
|
||||
|
||||
# Naming hint for attribute names
|
||||
attr-name-hint=[a-z_][a-z0-9_]{2,30}$
|
||||
|
||||
# Regular expression matching correct variable names
|
||||
variable-rgx=[a-z_][a-z0-9_]{2,30}$
|
||||
|
||||
# Naming hint for variable names
|
||||
variable-name-hint=[a-z_][a-z0-9_]{2,30}$
|
||||
|
||||
# Regular expression matching correct class names
|
||||
class-rgx=[A-Z_][a-zA-Z0-9]+$
|
||||
|
||||
# Naming hint for class names
|
||||
class-name-hint=[A-Z_][a-zA-Z0-9]+$
|
||||
|
||||
# Regular expression matching correct constant names
|
||||
const-rgx=(([A-Z_][A-Z0-9_]*)|(__.*__))$
|
||||
|
||||
# Naming hint for constant names
|
||||
const-name-hint=(([A-Z_][A-Z0-9_]*)|(__.*__))$
|
||||
|
||||
# Regular expression matching correct class attribute names
|
||||
class-attribute-rgx=([A-Za-z_][A-Za-z0-9_]{2,30}|(__.*__))$
|
||||
|
||||
# Naming hint for class attribute names
|
||||
class-attribute-name-hint=([A-Za-z_][A-Za-z0-9_]{2,30}|(__.*__))$
|
||||
|
||||
# Regular expression which should only match function or class names that do
|
||||
# not require a docstring.
|
||||
no-docstring-rgx=^_
|
||||
|
||||
# Minimum line length for functions/classes that require docstrings, shorter
|
||||
# ones are exempt.
|
||||
docstring-min-length=-1
|
||||
|
||||
|
||||
[ELIF]
|
||||
|
||||
# Maximum number of nested blocks for function / method body
|
||||
max-nested-blocks=5
|
||||
|
||||
|
||||
[FORMAT]
|
||||
|
||||
# Maximum number of characters on a single line.
|
||||
max-line-length=100
|
||||
|
||||
# Regexp for a line that is allowed to be longer than the limit.
|
||||
ignore-long-lines=^\s*(# )?<?https?://\S+>?$
|
||||
|
||||
# Allow the body of an if to be on the same line as the test if there is no
|
||||
# else.
|
||||
single-line-if-stmt=no
|
||||
|
||||
# List of optional constructs for which whitespace checking is disabled. `dict-
|
||||
# separator` is used to allow tabulation in dicts, etc.: {1 : 1,\n222: 2}.
|
||||
# `trailing-comma` allows a space between comma and closing bracket: (a, ).
|
||||
# `empty-line` allows space-only lines.
|
||||
no-space-check=trailing-comma,dict-separator
|
||||
|
||||
# Maximum number of lines in a module
|
||||
max-module-lines=1000
|
||||
|
||||
# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1
|
||||
# tab).
|
||||
indent-string=' '
|
||||
|
||||
# Number of spaces of indent required inside a hanging or continued line.
|
||||
indent-after-paren=4
|
||||
|
||||
# Expected format of line ending, e.g. empty (any line ending), LF or CRLF.
|
||||
expected-line-ending-format=
|
||||
|
||||
|
||||
[LOGGING]
|
||||
|
||||
# Logging modules to check that the string format arguments are in logging
|
||||
# function parameter format
|
||||
logging-modules=logging
|
||||
|
||||
|
||||
[MISCELLANEOUS]
|
||||
|
||||
# List of note tags to take in consideration, separated by a comma.
|
||||
notes=FIXME,XXX,TODO
|
||||
|
||||
|
||||
[SIMILARITIES]
|
||||
|
||||
# Minimum lines number of a similarity.
|
||||
min-similarity-lines=4
|
||||
|
||||
# Ignore comments when computing similarities.
|
||||
ignore-comments=yes
|
||||
|
||||
# Ignore docstrings when computing similarities.
|
||||
ignore-docstrings=yes
|
||||
|
||||
# Ignore imports when computing similarities.
|
||||
ignore-imports=no
|
||||
|
||||
|
||||
[SPELLING]
|
||||
|
||||
# Spelling dictionary name. Available dictionaries: none. To make it working
|
||||
# install python-enchant package.
|
||||
spelling-dict=
|
||||
|
||||
# List of comma separated words that should not be checked.
|
||||
spelling-ignore-words=
|
||||
|
||||
# A path to a file that contains private dictionary; one word per line.
|
||||
spelling-private-dict-file=
|
||||
|
||||
# Tells whether to store unknown words to indicated private dictionary in
|
||||
# --spelling-private-dict-file option instead of raising a message.
|
||||
spelling-store-unknown-words=no
|
||||
|
||||
|
||||
[TYPECHECK]
|
||||
|
||||
# Tells whether missing members accessed in mixin class should be ignored. A
|
||||
# mixin class is detected if its name ends with "mixin" (case insensitive).
|
||||
ignore-mixin-members=yes
|
||||
|
||||
# List of module names for which member attributes should not be checked
|
||||
# (useful for modules/projects where namespaces are manipulated during runtime
|
||||
# and thus existing member attributes cannot be deduced by static analysis. It
|
||||
# supports qualified module names, as well as Unix pattern matching.
|
||||
ignored-modules=
|
||||
|
||||
# List of class names for which member attributes should not be checked (useful
|
||||
# for classes with dynamically set attributes). This supports the use of
|
||||
# qualified names.
|
||||
ignored-classes=optparse.Values,thread._local,_thread._local
|
||||
|
||||
# List of members which are set dynamically and missed by pylint inference
|
||||
# system, and so shouldn't trigger E1101 when accessed. Python regular
|
||||
# expressions are accepted.
|
||||
generated-members=
|
||||
|
||||
# List of decorators that produce context managers, such as
|
||||
# contextlib.contextmanager. Add to this list to register other decorators that
|
||||
# produce valid context managers.
|
||||
contextmanager-decorators=contextlib.contextmanager
|
||||
|
||||
|
||||
[VARIABLES]
|
||||
|
||||
# Tells whether we should check for unused import in __init__ files.
|
||||
init-import=no
|
||||
|
||||
# A regular expression matching the name of dummy variables (i.e. expectedly
|
||||
# not used).
|
||||
dummy-variables-rgx=(_+[a-zA-Z0-9]*?$)|dummy
|
||||
|
||||
# List of additional names supposed to be defined in builtins. Remember that
|
||||
# you should avoid to define new builtins when possible.
|
||||
additional-builtins=
|
||||
|
||||
# List of strings which can identify a callback function by name. A callback
|
||||
# name must start or end with one of those strings.
|
||||
callbacks=cb_,_cb
|
||||
|
||||
# List of qualified module names which can have objects that can redefine
|
||||
# builtins.
|
||||
redefining-builtins-modules=six.moves,future.builtins
|
||||
|
||||
|
||||
[CLASSES]
|
||||
|
||||
# List of method names used to declare (i.e. assign) instance attributes.
|
||||
defining-attr-methods=__init__,__new__,setUp
|
||||
|
||||
# List of valid names for the first argument in a class method.
|
||||
valid-classmethod-first-arg=cls
|
||||
|
||||
# List of valid names for the first argument in a metaclass class method.
|
||||
valid-metaclass-classmethod-first-arg=mcs
|
||||
|
||||
# List of member names, which should be excluded from the protected access
|
||||
# warning.
|
||||
exclude-protected=_asdict,_fields,_replace,_source,_make
|
||||
|
||||
|
||||
[DESIGN]
|
||||
|
||||
# Maximum number of arguments for function / method
|
||||
max-args=5
|
||||
|
||||
# Argument names that match this expression will be ignored. Default to name
|
||||
# with leading underscore
|
||||
ignored-argument-names=_.*
|
||||
|
||||
# Maximum number of locals for function / method body
|
||||
max-locals=15
|
||||
|
||||
# Maximum number of return / yield for function / method body
|
||||
max-returns=6
|
||||
|
||||
# Maximum number of branch for function / method body
|
||||
max-branches=12
|
||||
|
||||
# Maximum number of statements in function / method body
|
||||
max-statements=50
|
||||
|
||||
# Maximum number of parents for a class (see R0901).
|
||||
max-parents=7
|
||||
|
||||
# Maximum number of attributes for a class (see R0902).
|
||||
max-attributes=7
|
||||
|
||||
# Minimum number of public methods for a class (see R0903).
|
||||
min-public-methods=2
|
||||
|
||||
# Maximum number of public methods for a class (see R0904).
|
||||
max-public-methods=20
|
||||
|
||||
# Maximum number of boolean expressions in a if statement
|
||||
max-bool-expr=5
|
||||
|
||||
|
||||
[IMPORTS]
|
||||
|
||||
# Deprecated modules which should not be used, separated by a comma
|
||||
deprecated-modules=optparse
|
||||
|
||||
# Create a graph of every (i.e. internal and external) dependencies in the
|
||||
# given file (report RP0402 must not be disabled)
|
||||
import-graph=
|
||||
|
||||
# Create a graph of external dependencies in the given file (report RP0402 must
|
||||
# not be disabled)
|
||||
ext-import-graph=
|
||||
|
||||
# Create a graph of internal dependencies in the given file (report RP0402 must
|
||||
# not be disabled)
|
||||
int-import-graph=
|
||||
|
||||
# Force import order to recognize a module as part of the standard
|
||||
# compatibility libraries.
|
||||
known-standard-library=
|
||||
|
||||
# Force import order to recognize a module as part of a third party library.
|
||||
known-third-party=enchant
|
||||
|
||||
# Analyse import fallback blocks. This can be used to support both Python 2 and
|
||||
# 3 compatible code, which means that the block might have code that exists
|
||||
# only in one or another interpreter, leading to false positives when analysed.
|
||||
analyse-fallback-blocks=no
|
||||
|
||||
|
||||
[EXCEPTIONS]
|
||||
|
||||
# Exceptions that will emit a warning when being caught. Defaults to
|
||||
# "Exception"
|
||||
overgeneral-exceptions=
|
|
@ -0,0 +1,28 @@
|
|||
version: '2'
|
||||
services:
|
||||
mysql:
|
||||
image: mysql
|
||||
container_name: hive-mysql
|
||||
environment:
|
||||
MYSQL_ROOT_PASSWORD: root_password
|
||||
MYSQL_USERNAME: testuser
|
||||
MYSQL_PASSWORD: testuserpass
|
||||
MYSQL_DATABASE: testdb
|
||||
ports:
|
||||
- 3306:3306
|
||||
volumes:
|
||||
- /home/user/docker/hive:/var/lib/mysql
|
||||
phpmyadmin:
|
||||
image: phpmyadmin/phpmyadmin
|
||||
container_name: hive-phpmyadmin
|
||||
links:
|
||||
- mysql:db
|
||||
environment:
|
||||
MYSQL_USERNAME: root
|
||||
MYSQL_ROOT_PASSWORD: root_password
|
||||
MYSQL_DATABASE: testdb
|
||||
restart: always
|
||||
ports:
|
||||
- 8080:80
|
||||
volumes:
|
||||
- /sessions
|
|
@ -0,0 +1,34 @@
|
|||
import datetime as dt
|
||||
|
||||
from sqlalchemy import (
|
||||
Column,
|
||||
Integer,
|
||||
MetaData,
|
||||
Table,
|
||||
DateTime,
|
||||
Index,
|
||||
)
|
||||
from sqlalchemy import create_engine
|
||||
from sqlalchemy.dialects.mysql import SMALLINT
|
||||
|
||||
metadata = MetaData()
|
||||
|
||||
addresses = Table(
|
||||
'hive_blocks', metadata,
|
||||
Column('num', Integer, primary_key=True),
|
||||
Column('prev', Integer),
|
||||
Column('txs', SMALLINT(unsigned=True), default=0),
|
||||
Column('created_at', DateTime),
|
||||
Index('hive_blocks_ux1', 'prev', unique=True),
|
||||
# ForeignKeyConstraint(name='hive_blocks_fk1', columns='prev', refcolumns='hive_blocks.num'),
|
||||
mysql_engine='InnoDB',
|
||||
mysql_charset='utf8mb4',
|
||||
)
|
||||
|
||||
if __name__ == '__main__':
|
||||
engine = create_engine('sqlite:///hive.sqlite', echo=True)
|
||||
metadata.create_all(engine)
|
||||
engine.execute(
|
||||
addresses.insert([addresses.c.num, addresses.c.prev, addresses.c.created_at]).
|
||||
values(num=0, prev=None, created_at=dt.datetime.fromtimestamp(0)))
|
||||
# INSERT INTO hive_blocks (num, prev, created_at) VALUES (0, NULL, "1970-01-01T00:00:00");
|
|
@ -0,0 +1,126 @@
|
|||
-- base
|
||||
CREATE TABLE hive_blocks (
|
||||
num INT(8) PRIMARY KEY NOT NULL,
|
||||
prev INT(40),
|
||||
txs SMALLINT UNSIGNED NOT NULL DEFAULT 0,
|
||||
created_at DATETIME NOT NULL,
|
||||
CONSTRAINT hive_blocks_fk1 FOREIGN KEY (prev) REFERENCES hive_blocks (num)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
CREATE UNIQUE INDEX hive_blocks_ux1 ON hive_blocks (prev);
|
||||
INSERT INTO hive_blocks (num, prev, created_at) VALUES (0, NULL, "1970-01-01T00:00:00");
|
||||
|
||||
CREATE TABLE hive_accounts (
|
||||
id INT(8) PRIMARY KEY NOT NULL AUTO_INCREMENT,
|
||||
name CHAR(16) NOT NULL,
|
||||
created_at DATETIME NOT NULL
|
||||
-- json_metadata?
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
CREATE UNIQUE INDEX hive_accounts_ux1 ON hive_accounts (name);
|
||||
INSERT INTO hive_accounts (name, created_at) VALUES ("null", "1970-01-01T00:00:00");
|
||||
INSERT INTO hive_accounts (name, created_at) VALUES ("temp", "1970-01-01T00:00:00");
|
||||
|
||||
CREATE TABLE hive_posts (
|
||||
-- immutable:
|
||||
id INT(8) PRIMARY KEY NOT NULL AUTO_INCREMENT,
|
||||
parent_id INT(8),
|
||||
author CHAR(16) NOT NULL,
|
||||
permlink CHAR(255) NOT NULL,
|
||||
community CHAR(16),
|
||||
depth SMALLINT UNSIGNED NOT NULL,
|
||||
created_at DATETIME NOT NULL,
|
||||
-- mutable:
|
||||
is_deleted TINYINT(1) NOT NULL DEFAULT 0,
|
||||
is_pinned TINYINT(1) NOT NULL DEFAULT 0,
|
||||
is_muted TINYINT(1) NOT NULL DEFAULT 0,
|
||||
--
|
||||
CONSTRAINT hive_posts_fk1 FOREIGN KEY (author) REFERENCES hive_accounts (name),
|
||||
CONSTRAINT hive_posts_fk2 FOREIGN KEY (community) REFERENCES hive_accounts (name),
|
||||
CONSTRAINT hive_posts_fk3 FOREIGN KEY (parent_id) REFERENCES hive_posts (id)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
CREATE UNIQUE INDEX hive_posts_ux1 ON hive_posts (author, permlink);
|
||||
CREATE INDEX hive_posts_ix1 ON hive_posts (parent_id);
|
||||
|
||||
CREATE TABLE hive_follows (
|
||||
follower CHAR(16) NOT NULL,
|
||||
following CHAR(16) NOT NULL,
|
||||
created_at DATETIME NOT NULL,
|
||||
CONSTRAINT hive_follows_fk1 FOREIGN KEY (follower) REFERENCES hive_accounts (name),
|
||||
CONSTRAINT hive_follows_fk2 FOREIGN KEY (following) REFERENCES hive_accounts (name)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
CREATE UNIQUE INDEX hive_follows_ux1 ON hive_follows (follower, following);
|
||||
|
||||
CREATE TABLE hive_reblogs (
|
||||
account CHAR(16) NOT NULL,
|
||||
post_id INT(8) NOT NULL,
|
||||
created_at DATETIME NOT NULL,
|
||||
CONSTRAINT hive_reblogs_fk1 FOREIGN KEY (account) REFERENCES hive_accounts (name),
|
||||
CONSTRAINT hive_reblogs_fk2 FOREIGN KEY (post_id) REFERENCES hive_posts (id)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
CREATE UNIQUE INDEX hive_reblogs_ux1 ON hive_reblogs (account, post_id);
|
||||
CREATE INDEX hive_reblogs_ix1 ON hive_reblogs (post_id, account, created_at);
|
||||
|
||||
-- cache
|
||||
CREATE TABLE hive_posts_cache (
|
||||
post_id INT(8) PRIMARY KEY NOT NULL,
|
||||
title VARCHAR(255),
|
||||
preview VARCHAR(1024),
|
||||
thumb_url VARCHAR(1024),
|
||||
children INT(8) NOT NULL DEFAULT 0, -- future: do not count comments made by muted users, or low rep
|
||||
net_claims BIGINT UNSIGNED,
|
||||
-- total_payout_value,
|
||||
-- tags
|
||||
-- active_votes?
|
||||
-- json_metadata -- anything else in here?
|
||||
-- post_preview --> bother trying to parse/render posts?
|
||||
-- is_nsfw
|
||||
CONSTRAINT hive_posts_cache_fk1 FOREIGN KEY (post_id) REFERENCES hive_posts (id)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
|
||||
-- communities
|
||||
CREATE TABLE hive_communities (
|
||||
account_id INT(8) PRIMARY KEY NOT NULL,
|
||||
name VARCHAR(32) NOT NULL,
|
||||
about VARCHAR(255) NOT NULL DEFAULT '',
|
||||
description VARCHAR(5000) NOT NULL DEFAULT '',
|
||||
lang CHAR(2) NOT NULL DEFAULT 'en',
|
||||
is_nsfw TINYINT(1) NOT NULL DEFAULT 0,
|
||||
is_private TINYINT(1) NOT NULL DEFAULT 0,
|
||||
created_at DATETIME NOT NULL,
|
||||
CONSTRAINT hive_communities_fk1 FOREIGN KEY (account_id) REFERENCES hive_accounts (id)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
CREATE TABLE hive_members (
|
||||
community_id INT(8) NOT NULL,
|
||||
account_id INT(8) NOT NULL,
|
||||
is_admin TINYINT(1) NOT NULL,
|
||||
is_mod TINYINT(1) NOT NULL,
|
||||
is_approved TINYINT(1) NOT NULL,
|
||||
is_muted TINYINT(1) NOT NULL,
|
||||
title VARCHAR(255) NOT NULL DEFAULT '',
|
||||
CONSTRAINT hive_members_fk1 FOREIGN KEY (community_id) REFERENCES hive_communities (account_id),
|
||||
CONSTRAINT hive_members_fk2 FOREIGN KEY (account_id) REFERENCES hive_accounts (id)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
CREATE UNIQUE INDEX hive_members_ux1 ON hive_members (community_id, account_id);
|
||||
|
||||
CREATE TABLE hive_flags (
|
||||
account_id INT(8) NOT NULL,
|
||||
post_id INT(8) NOT NULL,
|
||||
notes VARCHAR(255) NOT NULL,
|
||||
created_at DATETIME NOT NULL,
|
||||
CONSTRAINT hive_flags_fk1 FOREIGN KEY (account_id) REFERENCES hive_accounts (id),
|
||||
CONSTRAINT hive_flags_fk2 FOREIGN KEY (post_id) REFERENCES hive_posts (id)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
CREATE UNIQUE INDEX hive_flags_ux1 ON hive_flags (account_id, post_id);
|
||||
|
||||
CREATE TABLE hive_modlog (
|
||||
id INT(8) PRIMARY KEY NOT NULL,
|
||||
community_id INT(8) NOT NULL,
|
||||
account_id INT(8) NOT NULL,
|
||||
action VARCHAR(32) NOT NULL,
|
||||
params VARCHAR(1000) NOT NULL,
|
||||
created_at DATETIME NOT NULL,
|
||||
CONSTRAINT hive_modlog_fk1 FOREIGN KEY (community_id) REFERENCES hive_communities (account_id),
|
||||
CONSTRAINT hive_modlog_fk2 FOREIGN KEY (account_id) REFERENCES hive_accounts (id)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
CREATE INDEX hive_modlog_ix1 ON hive_modlog (community_id, created_at);
|
|
@ -0,0 +1,33 @@
|
|||
from pprint import pprint
|
||||
from sqlalchemy import (
|
||||
Column,
|
||||
Integer,
|
||||
MetaData,
|
||||
String,
|
||||
Table,
|
||||
create_engine,
|
||||
)
|
||||
from sqlalchemy import select
|
||||
from steem.account import Account
|
||||
|
||||
engine = create_engine('sqlite:///hive.sqlite', echo=True)
|
||||
|
||||
metadata = MetaData()
|
||||
|
||||
authors = Table(
|
||||
'authors',
|
||||
metadata,
|
||||
Column('id', Integer, primary_key=True, autoincrement=True),
|
||||
Column('name', String(16)),
|
||||
Column('balances', String),
|
||||
)
|
||||
|
||||
metadata.create_all(engine)
|
||||
|
||||
if __name__ == '__main__':
|
||||
conn = engine.connect()
|
||||
acc = Account('furion')
|
||||
r = authors.insert().values(name=acc.name, balances='100')
|
||||
engine.execute(r)
|
||||
q = select([authors])
|
||||
pprint(conn.execute(q).fetchall())
|
|
@ -0,0 +1,34 @@
|
|||
[aliases]
|
||||
test=pytest
|
||||
|
||||
[build_sphinx]
|
||||
source-dir = docs/
|
||||
build-dir = docs/_build
|
||||
all_files = 1
|
||||
|
||||
|
||||
[pycodestyle]
|
||||
# formerly pep8
|
||||
ignore = E501
|
||||
|
||||
|
||||
[pep8]
|
||||
# backwards compat
|
||||
ignore = E501
|
||||
|
||||
|
||||
[style]
|
||||
# google yapf config
|
||||
|
||||
|
||||
[tool:pytest]
|
||||
norecursedirs=dist docs build .tox deploy
|
||||
addopts = --pylint
|
||||
|
||||
|
||||
[coverage:run]
|
||||
branch = True
|
||||
source = sbds
|
||||
|
||||
[coverage:xml]
|
||||
output = coverage.xml
|
|
@ -0,0 +1,36 @@
|
|||
# coding=utf-8
|
||||
import sys
|
||||
|
||||
from setuptools import find_packages
|
||||
from setuptools import setup
|
||||
|
||||
assert sys.version_info[0] == 3 and sys.version_info[1] >= 5, "hive requires Python 3.5 or newer"
|
||||
|
||||
# yapf: disable
|
||||
setup(
|
||||
name='hivemind',
|
||||
version='0.0.1',
|
||||
description='Community consensus layer for the Steem blockchain',
|
||||
long_description=open('README.md').read(),
|
||||
packages=find_packages(exclude=['scripts']),
|
||||
setup_requires=['pytest-runner'],
|
||||
tests_require=['pytest',
|
||||
'pep8',
|
||||
'pytest-pylint',
|
||||
'yapf',
|
||||
'sphinx',
|
||||
'recommonmark',
|
||||
'sphinxcontrib-restbuilder',
|
||||
'sphinxcontrib-programoutput',
|
||||
'pytest-console-scripts'],
|
||||
|
||||
install_requires=[
|
||||
'maya',
|
||||
'toolz',
|
||||
'funcy',
|
||||
],
|
||||
entry_points={
|
||||
'console_scripts': [
|
||||
'hive=hive.cli:cli',
|
||||
]
|
||||
})
|
Loading…
Reference in New Issue