<commit_before>"""For loading TLG .json files and searching, then pulling author ids.
"""

from cltk.corpus.greek.tlg.author_date import AUTHOR_DATE
from cltk.corpus.greek.tlg.author_epithet import AUTHOR_EPITHET
from cltk.corpus.greek.tlg.author_female import AUTHOR_FEMALE
from cltk.corpus.greek.tlg.author_geo import AUTHOR_GEO
from cltk.corpus.greek.tlg.id_author import ID_AUTHOR
from cltk.corpus.greek.tlg.index_lists import INDEX_LIST
import regex
import os
import json

__author__ = ['Kyle P. Johnson <kyle@kyle-p-johnson.com>',
              'Stephen Margheim <stephen.margheim@gmail.com>',
              'Martín Pozzi <marpozzi@gmail.com>']
__license__ = 'MIT License. See LICENSE.'

THIS_DIR = os.path.dirname(os.path.abspath(__file__))

# Gender
def get_female_authors():
    """Open female authors index and return ordered set of author ids."""
    return set(AUTHOR_FEMALE['Femina'])

# Epithet
def get_epithet_index():
    """Return dict of epithets (key) to a set of all author ids of that
    epithet (value).
    """
    _dict = {}
    for k, v in AUTHOR_EPITHET.items():
        _dict[k] = set(v)
    return _dict

def get_epithets():
    """Return a list of all the epithet labels."""
    return sorted(AUTHOR_EPITHET.keys())

def select_authors_by_epithet(query):
    """Pass exact name (case insensitive) of epithet name, return ordered set
    of author ids.
    """

    for epithet, ids in AUTHOR_EPITHET.items():
        if epithet.casefold() == query.casefold():
            return set(ids)

def get_epithet_of_author(_id):
    """Pass author id and return the name of its associated epithet."""
    for epithet, ids in AUTHOR_EPITHET.items():
        if _id in ids:
            return epithet

# Geography
def get_geo_index():
    """Get entire index of geographic name (key) and set of associated authors
    (value).
    """
    _dict = {}
    for k, v in AUTHOR_EPITHET.items():
        _dict[k] = set(v)

    return _dict

def get_geographies():
    """Return a list of all the epithet labels."""
    return sorted(AUTHOR_GEO.keys())

def select_authors_by_geo(query):
    """Pass exact name (case insensitive) of geography name, return ordered set
    of author ids.
    """
    for geo, ids in AUTHOR_GEO.items():
        if geo.casefold() == query.casefold():
            return set(ids)

def get_geo_of_author(_id):
    """Pass author id and return the name of its associated epithet."""
    for geo, ids in AUTHOR_GEO.items():
        if _id in ids:
            return geo

# List of TLG indices
def get_lists():
    """A list of the TLG's lists."""
    return INDEX_LIST

# Master author index (`id_author.json`)
def get_id_author():
    """Returns entirety of id-author TLG index."""
    return ID_AUTHOR

def select_id_by_name(query):
    """Do a case-insensitive regex match on author name, returns TLG id."""
    id_author = get_id_author()
    comp = regex.compile(r'{}'.format(query.casefold()), flags=regex.VERSION1)
    matches = []
    for _id, author in id_author.items():
        match = comp.findall(author.casefold())
        if match:
            matches.append((_id, author))
    return matches

def open_json(_file):
    """Loads the json file as a dictionary and returns it."""
    with open(_file) as f:
        return json.load(f)

# Dates
def get_date_author():
    """Returns entirety of date-author index."""
    _path = os.path.join(THIS_DIR, 'author_date.json')
    return open_json(_path)

def get_dates():
    """Return a list of all the epithet labels."""
    _dict = get_date_author()
    return sorted(_dict.keys())

def get_date_of_author(_id):
    """Pass author id and return the name of its associated date."""
    _dict = get_date_author()
    for date, ids in _dict.items():
        if _id in ids:
            return date
    return None

def _get_epoch(_str):
    """Take incoming string, return its epoch."""
    _return = None
    if _str.startswith('A.D. '):
        _return = 'ad'
    elif _str.startswith('a. A.D. '):
        _return = None #?
    elif _str.startswith('p. A.D. '):
        _return = 'ad'
    elif regex.match(r'^[0-9]+ B\.C\. *', _str):
        _return = 'bc'
    elif regex.match(r'^a\. *[0-9]+ B\.C\. *', _str):
        _return = 'bc'
    elif regex.match(r'^p\. *[0-9]+ B\.C\. *', _str):
        _return = None  #?
    elif _str == 'Incertum' or _str == 'Varia':
        _return = _str
    return _return

def _check_number(_str):
    """check if the string contains only a number followed by ?"""
    if regex.match(r'^[0-9]+\?*', _str):
        return True
    return False

def _handle_splits(_str):
    """Check if incoming date has a '-" or '/', if so do stuff."""
    _str = _str.replace('/', '-')
    _tmp_dict = {}

    if '-' in _str:
        start, stop = _str.split('-')
        if _check_number(start):
            start = regex.sub(r'[0-9]+\?*', start, stop)
        elif _check_number(stop):
            stop = regex.sub(r'[0-9]+\?*', stop, start)
    else:
        start = _str
        stop = _str
    _tmp_dict['start_raw'] = start
    _tmp_dict['stop_raw'] = stop

    _tmp_dict['start_epoch'] = _get_epoch(start)
    _tmp_dict['stop_epoch'] = _get_epoch(stop)

    return _tmp_dict

def normalize_dates():
    """Experiment to make sense of TLG dates.
    TODO: start here, parse everything with pass
    """
    _dict = get_date_author()
    for tlg_date in _dict:
        date = {}
        if tlg_date == 'Varia':
            #give a homer-to-byz date for 'varia'
            pass
        elif tlg_date == 'Incertum':
            #?
            pass
        else:
            tmp_date = _handle_splits(tlg_date)
            date.update(tmp_date)

        print(date)

if __name__ == "__main__":
    pass
<commit_msg>added function to access work numbers data<commit_after>"""For loading TLG .json files and searching, then pulling author ids.
"""

from cltk.corpus.greek.tlg.author_date import AUTHOR_DATE
from cltk.corpus.greek.tlg.author_epithet import AUTHOR_EPITHET
from cltk.corpus.greek.tlg.author_female import AUTHOR_FEMALE
from cltk.corpus.greek.tlg.author_geo import AUTHOR_GEO
from cltk.corpus.greek.tlg.id_author import ID_AUTHOR
from cltk.corpus.greek.tlg.index_lists import INDEX_LIST
from cltk.corpus.greek.tlg.work_numbers import WORK_NUMBERS
import regex
import os
import json

__author__ = ['Kyle P. Johnson <kyle@kyle-p-johnson.com>',
              'Stephen Margheim <stephen.margheim@gmail.com>',
              'Martín Pozzi <marpozzi@gmail.com>']
__license__ = 'MIT License. See LICENSE.'

THIS_DIR = os.path.dirname(os.path.abspath(__file__))

# Gender
def get_female_authors():
    """Open female authors index and return ordered set of author ids."""
    return set(AUTHOR_FEMALE['Femina'])

# Epithet
def get_epithet_index():
    """Return dict of epithets (key) to a set of all author ids of that
    epithet (value).
    """
    _dict = {}
    for k, v in AUTHOR_EPITHET.items():
        _dict[k] = set(v)
    return _dict

def get_epithets():
    """Return a list of all the epithet labels."""
    return sorted(AUTHOR_EPITHET.keys())

def select_authors_by_epithet(query):
    """Pass exact name (case insensitive) of epithet name, return ordered set
    of author ids.
    """

    for epithet, ids in AUTHOR_EPITHET.items():
        if epithet.casefold() == query.casefold():
            return set(ids)

def get_epithet_of_author(_id):
    """Pass author id and return the name of its associated epithet."""
    for epithet, ids in AUTHOR_EPITHET.items():
        if _id in ids:
            return epithet

# Geography
def get_geo_index():
    """Get entire index of geographic name (key) and set of associated authors
    (value).
    """
    _dict = {}
    for k, v in AUTHOR_EPITHET.items():
        _dict[k] = set(v)

    return _dict

def get_geographies():
    """Return a list of all the epithet labels."""
    return sorted(AUTHOR_GEO.keys())

def select_authors_by_geo(query):
    """Pass exact name (case insensitive) of geography name, return ordered set
    of author ids.
    """
    for geo, ids in AUTHOR_GEO.items():
        if geo.casefold() == query.casefold():
            return set(ids)

def get_geo_of_author(_id):
    """Pass author id and return the name of its associated epithet."""
    for geo, ids in AUTHOR_GEO.items():
        if _id in ids:
            return geo

# List of TLG indices
def get_lists():
    """A list of the TLG's lists."""
    return INDEX_LIST

# Master author index (`id_author.json`)
def get_id_author():
    """Returns entirety of id-author TLG index."""
    return ID_AUTHOR

def select_id_by_name(query):
    """Do a case-insensitive regex match on author name, returns TLG id."""
    id_author = get_id_author()
    comp = regex.compile(r'{}'.format(query.casefold()), flags=regex.VERSION1)
    matches = []
    for _id, author in id_author.items():
        match = comp.findall(author.casefold())
        if match:
            matches.append((_id, author))
    return matches

def open_json(_file):
    """Loads the json file as a dictionary and returns it."""
    with open(_file) as f:
        return json.load(f)

# Work numbers
def get_works_by_author(_id):
  """Pass author id and return a dictionary of its works."""
    return WORK_NUMBERS[_id]

# Dates
def get_date_author():
    """Returns entirety of date-author index."""
    _path = os.path.join(THIS_DIR, 'author_date.json')
    return open_json(_path)

def get_dates():
    """Return a list of all the epithet labels."""
    _dict = get_date_author()
    return sorted(_dict.keys())

def get_date_of_author(_id):
    """Pass author id and return the name of its associated date."""
    _dict = get_date_author()
    for date, ids in _dict.items():
        if _id in ids:
            return date
    return None

def _get_epoch(_str):
    """Take incoming string, return its epoch."""
    _return = None
    if _str.startswith('A.D. '):
        _return = 'ad'
    elif _str.startswith('a. A.D. '):
        _return = None #?
    elif _str.startswith('p. A.D. '):
        _return = 'ad'
    elif regex.match(r'^[0-9]+ B\.C\. *', _str):
        _return = 'bc'
    elif regex.match(r'^a\. *[0-9]+ B\.C\. *', _str):
        _return = 'bc'
    elif regex.match(r'^p\. *[0-9]+ B\.C\. *', _str):
        _return = None  #?
    elif _str == 'Incertum' or _str == 'Varia':
        _return = _str
    return _return

def _check_number(_str):
    """check if the string contains only a number followed by ?"""
    if regex.match(r'^[0-9]+\?*', _str):
        return True
    return False

def _handle_splits(_str):
    """Check if incoming date has a '-" or '/', if so do stuff."""
    _str = _str.replace('/', '-')
    _tmp_dict = {}

    if '-' in _str:
        start, stop = _str.split('-')
        if _check_number(start):
            start = regex.sub(r'[0-9]+\?*', start, stop)
        elif _check_number(stop):
            stop = regex.sub(r'[0-9]+\?*', stop, start)
    else:
        start = _str
        stop = _str
    _tmp_dict['start_raw'] = start
    _tmp_dict['stop_raw'] = stop

    _tmp_dict['start_epoch'] = _get_epoch(start)
    _tmp_dict['stop_epoch'] = _get_epoch(stop)

    return _tmp_dict

def normalize_dates():
    """Experiment to make sense of TLG dates.
    TODO: start here, parse everything with pass
    """
    _dict = get_date_author()
    for tlg_date in _dict:
        date = {}
        if tlg_date == 'Varia':
            #give a homer-to-byz date for 'varia'
            pass
        elif tlg_date == 'Incertum':
            #?
            pass
        else:
            tmp_date = _handle_splits(tlg_date)
            date.update(tmp_date)

        print(date)

if __name__ == "__main__":
    pass
<|endoftext|>


<commit_before># Copyright 2013-2020 Lawrence Livermore National Security, LLC and other
# Spack Project Developers. See the top-level COPYRIGHT file for details.
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)

from spack import *

class PyTraitlets(PythonPackage):
    """Traitlets Python config system"""

    homepage = "https://pypi.python.org/pypi/traitlets"
    url      = "https://github.com/ipython/traitlets/archive/4.3.1.tar.gz"

    version('4.3.3', sha256='b686c1aadf6ee5a9ee4c22df23bc5cd5bb7b5cfa18afe092e0a139cc2f05fe2e')
    version('4.3.2', sha256='370f938ad730d52272ef74f96f831cb21138f6168e46fe582fe256c35cc656ce')
    version('4.3.1', sha256='3d50b2968f2e1477bd0de4b9656df40fd5624fc85cd1fc15f6c885cd68a4f6a1')
    version('4.3.0', sha256='2f6cbc367fb56cbde91b2585202ef0a5bd41ae205a70aeecca1aeb4cb5b64e66')
    version('4.2.2', sha256='bc749e08dd89c6007eb70e98c958f16d41e9a1fa42fdc9e9ba24e67469efa0ef')
    version('4.2.1', sha256='a9ea45313f7130c555d8c1832529bf3f522ffc584093436783bc4b9611e8c4a9')
    version('4.2.0', sha256='923cbe84bef30c27d2083f014f23a5da0ebe7da2e67a683d97acb07002e2ce0d')
    version('4.1.0', sha256='93ead8dbf7e9617c88b79620072bfc499e7f25613f3df2234e5fdf08348c0a83')
    version('4.0.0', sha256='03f380cb2e47689ae55dbe9a5dccbdde5cad8c4637312d720f4c3a991fb15cd2')

    depends_on('python@2.7:2.8,3.3:', type=('build', 'run'))
    depends_on('py-six', type=('build', 'run'))
    depends_on('py-decorator', type=('build', 'run'))
    depends_on('py-ipython-genutils', type=('build', 'run'))
    depends_on('py-enum34', when='^python@:3.3', type=('build', 'run'))
<commit_msg>py-traitlets: added v5.0.4, moved url to PyPI (#18640)<commit_after># Copyright 2013-2020 Lawrence Livermore National Security, LLC and other
# Spack Project Developers. See the top-level COPYRIGHT file for details.
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)

from spack import *

class PyTraitlets(PythonPackage):
    """Traitlets Python config system"""

    homepage = "https://pypi.python.org/pypi/traitlets"
    url      = "https://pypi.io/packages/source/t/traitlets/traitlets-5.0.4.tar.gz"

    version('5.0.4', sha256='86c9351f94f95de9db8a04ad8e892da299a088a64fd283f9f6f18770ae5eae1b')
    version('4.3.3', sha256='d023ee369ddd2763310e4c3eae1ff649689440d4ae59d7485eb4cfbbe3e359f7')
    version('4.3.2', sha256='9c4bd2d267b7153df9152698efb1050a5d84982d3384a37b2c1f7723ba3e7835')
    version('4.3.1', sha256='ba8c94323ccbe8fd792e45d8efe8c95d3e0744cc8c085295b607552ab573724c')
    version('4.3.0', sha256='8a33cb7b1ef47f2d6dc16e9cf971217d5a4882a3541c070e78a0e8e8edcb3f82')
    version('4.2.2', sha256='7d7e3070484b2fe490fa55e0acf7023afc5ed9ddabec57405f25c355158e152a')
    version('4.2.1', sha256='76eba33c89723b8fc024f950cacaf5bf2ef37999642cc9a61f4e7c1ca5cf0ac0')
    version('4.2.0', sha256='e4c39210f2f2ff7361b86043b6512adbcf6f024b44b501f7b42fd9a23402dea9')
    version('4.1.0', sha256='440e38dfa5d2a26c086d4b427cfb7aed17d0a2dca78bce90c33354da2592af5b')
    version('4.0.0', sha256='0b140b4a94a4f1951887d9bce4650da211f79600fc9fdb422acc90c5bbe0233b')

    depends_on('python@3.7:', when='@5:', type=('build', 'run'))
    depends_on('python@2.7:2.8,3.3:', type=('build', 'run'))
    depends_on('py-ipython-genutils', type=('build', 'run'))
    depends_on('py-six', when='@:4', type=('build', 'run'))
    depends_on('py-decorator', when='@:4', type=('build', 'run'))
    depends_on('py-enum34', when='^python@:3.3', type=('build', 'run'))
    depends_on('py-pytest', type='test')
<|endoftext|>


<commit_before>"""
Django settings for webapp project.

For more information on this file, see
https://docs.djangoproject.com/en/1.7/topics/settings/

For the full list of settings and their values, see
https://docs.djangoproject.com/en/1.7/ref/settings/
"""
# Honor the 'X-Forwarded-Proto' header for request.is_secure()
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')

import os

SECRET_KEY = os.environ.get('SECRET_KEY', 'secret key')
SITE_ID = os.environ.get('SITE_ID', 1)

# Allow all host headers
ALLOWED_HOSTS = ['*']

SITE_ID = 1

# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
import dj_database_url
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/1.7/howto/deployment/checklist/

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True if os.environ.get('DEV_DEBUG') == 'True' else False

TEMPLATE_DEBUG = DEBUG

TEMPLATE_DIRS = (
    (BASE_DIR + '/templates/'),
)

from django.conf import global_settings

WEBAPP_VERSION = "1.2.0"

TEMPLATE_CONTEXT_PROCESSORS = global_settings.TEMPLATE_CONTEXT_PROCESSORS + (
    'webapp.apps.pages.views.settings_context_processor',
    'webapp.context_processors.google_analytics',
)

# Application definition

INSTALLED_APPS = (
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.humanize',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'django.contrib.sites',

    # Apps
    'webapp.apps.taxbrain',
    'webapp.apps.dynamic',
    'webapp.apps.pages',
    'webapp.apps.register',
    'webapp.apps.btax',

    # Third party apps
    'flatblocks',
    'account',
    'gunicorn',
    'hermes',
    'import_export',
    'storages'
)

MIDDLEWARE_CLASSES = (
    'django.middleware.gzip.GZipMiddleware',
    'htmlmin.middleware.HtmlMinifyMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
)

ROOT_URLCONF = 'webapp.urls'

WSGI_APPLICATION = 'webapp.wsgi.application'

CELERY_RESULT_BACKEND = os.environ.get('REDISGREEN_URL')

BROKER_URL = os.environ.get('REDISGREEN_URL')

# Database
# https://docs.djangoproject.com/en/1.7/ref/settings/#databases

if os.environ.get('DATABASE_URL', None):
    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.postgresql_psycopg2',
            'NAME': 'taxcalc',
            'USER': 'postgres',
            'PASSWORD': '',
            'HOST': 'localhost',
            'PORT': '5432',
        }
    }
    # Parse database configuration from $DATABASE_URL
    import dj_database_url
    DATABASES['default'] = dj_database_url.config()
else:
    DATABASES = {
        'default': {
          'ENGINE': 'django.db.backends.sqlite3',
          'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
        }
    }

# Internationalization
# https://docs.djangoproject.com/en/1.7/topics/i18n/

LANGUAGE_CODE = 'en-us'

TIME_ZONE = 'UTC'

USE_I18N = True

USE_L10N = True

USE_TZ = True

# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/1.7/howto/static-files/

STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')

STATICFILES_DIRS = (
    os.path.join(BASE_DIR, "static"),
)

# AWS S3 static file storage

# Use Amazon S3 for storage for uploaded media files.
DEFAULT_FILE_STORAGE = "storages.backends.s3boto.S3BotoStorage"

# Amazon S3 settings.
AWS_ACCESS_KEY_ID = os.environ.get("AWS_KEY_ID", "")
AWS_SECRET_ACCESS_KEY = os.environ.get("AWS_SECRET_ID", "")
AWS_STORAGE_BUCKET_NAME = os.environ.get("AWS_STORAGE_BUCKET_NAME", "")
AWS_S3_HOST = os.environ.get("AWS_S3_HOST", None)

# Tell django-storages that when coming up with the URL for an item in S3 storage, keep
# it simple - just use this domain plus the path. (If this isn't set, things get complicated).
# This controls how the `static` template tag from `staticfiles` gets expanded, if you're using it.
# We also use it in the next setting.
AWS_S3_CUSTOM_DOMAIN = '%s.s3.amazonaws.com' % AWS_STORAGE_BUCKET_NAME

# This is used by the `static` template tag from `static`, if you're using that. Or if anything else
# refers directly to STATIC_URL. So it's safest to always set it.

# STATIC_URL is used by StaticFilesStorage to create the path to static assets when
# using the 'static' template tag. In production, we use storages, so just leave this as
# '/static/' for development purposes
#STATIC_URL = "https://%s/" % AWS_S3_CUSTOM_DOMAIN
STATIC_URL = '/static/'

# Tell the staticfiles app to use S3Boto storage when writing the collected static files (when
# you run `collectstatic`).
if True:
    STATICFILES_STORAGE = 'django.contrib.staticfiles.storage.StaticFilesStorage'
else:
    STATICFILES_STORAGE = 'storages.backends.s3boto.S3BotoStorage'

SENDGRID_API_KEY=os.environ.get("SENDGRID_API_KEY", "")
EMAIL_BACKEND = "sgbackend.SendGridBackend"
BLOG_URL = os.environ.get('BLOG_URL', 'http://news.ospc.org/')

GOOGLE_ANALYTICS_PROPERTY_ID = os.environ.get("GOOGLE_ANALYTICS_PROPERTY_ID", "")
GOOGLE_ANALYTICS_EMBEDDED_ID = os.environ.get("GOOGLE_ANALYTICS_EMBEDDED_ID", "")
GOOGLE_ANALYTICS_DOMAIN = os.environ.get("GOOGLE_ANALYTICS_DOMAIN", "")
<commit_msg>Update hardcoded version to 1.2.1<commit_after>"""
Django settings for webapp project.

For more information on this file, see
https://docs.djangoproject.com/en/1.7/topics/settings/

For the full list of settings and their values, see
https://docs.djangoproject.com/en/1.7/ref/settings/
"""
# Honor the 'X-Forwarded-Proto' header for request.is_secure()
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')

import os

SECRET_KEY = os.environ.get('SECRET_KEY', 'secret key')
SITE_ID = os.environ.get('SITE_ID', 1)

# Allow all host headers
ALLOWED_HOSTS = ['*']

SITE_ID = 1

# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
import dj_database_url
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/1.7/howto/deployment/checklist/

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True if os.environ.get('DEV_DEBUG') == 'True' else False

TEMPLATE_DEBUG = DEBUG

TEMPLATE_DIRS = (
    (BASE_DIR + '/templates/'),
)

from django.conf import global_settings

WEBAPP_VERSION = "1.2.1"

TEMPLATE_CONTEXT_PROCESSORS = global_settings.TEMPLATE_CONTEXT_PROCESSORS + (
    'webapp.apps.pages.views.settings_context_processor',
    'webapp.context_processors.google_analytics',
)

# Application definition

INSTALLED_APPS = (
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.humanize',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'django.contrib.sites',

    # Apps
    'webapp.apps.taxbrain',
    'webapp.apps.dynamic',
    'webapp.apps.pages',
    'webapp.apps.register',
    'webapp.apps.btax',

    # Third party apps
    'flatblocks',
    'account',
    'gunicorn',
    'hermes',
    'import_export',
    'storages'
)

MIDDLEWARE_CLASSES = (
    'django.middleware.gzip.GZipMiddleware',
    'htmlmin.middleware.HtmlMinifyMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
)

ROOT_URLCONF = 'webapp.urls'

WSGI_APPLICATION = 'webapp.wsgi.application'

CELERY_RESULT_BACKEND = os.environ.get('REDISGREEN_URL')

BROKER_URL = os.environ.get('REDISGREEN_URL')

# Database
# https://docs.djangoproject.com/en/1.7/ref/settings/#databases

if os.environ.get('DATABASE_URL', None):
    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.postgresql_psycopg2',
            'NAME': 'taxcalc',
            'USER': 'postgres',
            'PASSWORD': '',
            'HOST': 'localhost',
            'PORT': '5432',
        }
    }
    # Parse database configuration from $DATABASE_URL
    import dj_database_url
    DATABASES['default'] = dj_database_url.config()
else:
    DATABASES = {
        'default': {
          'ENGINE': 'django.db.backends.sqlite3',
          'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
        }
    }

# Internationalization
# https://docs.djangoproject.com/en/1.7/topics/i18n/

LANGUAGE_CODE = 'en-us'

TIME_ZONE = 'UTC'

USE_I18N = True

USE_L10N = True

USE_TZ = True

# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/1.7/howto/static-files/

STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')

STATICFILES_DIRS = (
    os.path.join(BASE_DIR, "static"),
)

# AWS S3 static file storage

# Use Amazon S3 for storage for uploaded media files.
DEFAULT_FILE_STORAGE = "storages.backends.s3boto.S3BotoStorage"

# Amazon S3 settings.
AWS_ACCESS_KEY_ID = os.environ.get("AWS_KEY_ID", "")
AWS_SECRET_ACCESS_KEY = os.environ.get("AWS_SECRET_ID", "")
AWS_STORAGE_BUCKET_NAME = os.environ.get("AWS_STORAGE_BUCKET_NAME", "")
AWS_S3_HOST = os.environ.get("AWS_S3_HOST", None)

# Tell django-storages that when coming up with the URL for an item in S3 storage, keep
# it simple - just use this domain plus the path. (If this isn't set, things get complicated).
# This controls how the `static` template tag from `staticfiles` gets expanded, if you're using it.
# We also use it in the next setting.
AWS_S3_CUSTOM_DOMAIN = '%s.s3.amazonaws.com' % AWS_STORAGE_BUCKET_NAME

# This is used by the `static` template tag from `static`, if you're using that. Or if anything else
# refers directly to STATIC_URL. So it's safest to always set it.

# STATIC_URL is used by StaticFilesStorage to create the path to static assets when
# using the 'static' template tag. In production, we use storages, so just leave this as
# '/static/' for development purposes
#STATIC_URL = "https://%s/" % AWS_S3_CUSTOM_DOMAIN
STATIC_URL = '/static/'

# Tell the staticfiles app to use S3Boto storage when writing the collected static files (when
# you run `collectstatic`).
if True:
    STATICFILES_STORAGE = 'django.contrib.staticfiles.storage.StaticFilesStorage'
else:
    STATICFILES_STORAGE = 'storages.backends.s3boto.S3BotoStorage'

SENDGRID_API_KEY=os.environ.get("SENDGRID_API_KEY", "")
EMAIL_BACKEND = "sgbackend.SendGridBackend"
BLOG_URL = os.environ.get('BLOG_URL', 'http://news.ospc.org/')

GOOGLE_ANALYTICS_PROPERTY_ID = os.environ.get("GOOGLE_ANALYTICS_PROPERTY_ID", "")
GOOGLE_ANALYTICS_EMBEDDED_ID = os.environ.get("GOOGLE_ANALYTICS_EMBEDDED_ID", "")
GOOGLE_ANALYTICS_DOMAIN = os.environ.get("GOOGLE_ANALYTICS_DOMAIN", "")
<|endoftext|>


<commit_before>"""
Django settings for webapp project.

For more information on this file, see
https://docs.djangoproject.com/en/1.7/topics/settings/

For the full list of settings and their values, see
https://docs.djangoproject.com/en/1.7/ref/settings/
"""
# Honor the 'X-Forwarded-Proto' header for request.is_secure()
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')

import os

SECRET_KEY = os.environ.get('SECRET_KEY', 'secret key')
SITE_ID = os.environ.get('SITE_ID', 1)

# Allow all host headers
ALLOWED_HOSTS = ['*']

SITE_ID = 1

# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
import dj_database_url
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/1.7/howto/deployment/checklist/

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True if os.environ.get('DEV_DEBUG') == 'True' else False

TEMPLATE_DEBUG = DEBUG

TEMPLATE_DIRS = (
    (BASE_DIR + '/templates/'),
)

from django.conf import global_settings

WEBAPP_VERSION = "1.3.0"

TEMPLATE_CONTEXT_PROCESSORS = global_settings.TEMPLATE_CONTEXT_PROCESSORS + (
    'webapp.apps.pages.views.settings_context_processor',
    'webapp.context_processors.google_analytics',
)

# Application definition

INSTALLED_APPS = (
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.humanize',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'django.contrib.sites',

    # Apps
    'webapp.apps.taxbrain',
    'webapp.apps.dynamic',
    'webapp.apps.pages',
    'webapp.apps.register',
    'webapp.apps.btax',

    # Third party apps
    'flatblocks',
    'account',
    'gunicorn',
    'hermes',
    'import_export',
    'storages'
)

MIDDLEWARE_CLASSES = (
    'django.middleware.gzip.GZipMiddleware',
    'htmlmin.middleware.HtmlMinifyMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
)

ROOT_URLCONF = 'webapp.urls'

WSGI_APPLICATION = 'webapp.wsgi.application'

CELERY_RESULT_BACKEND = os.environ.get('REDISGREEN_URL')

BROKER_URL = os.environ.get('REDISGREEN_URL')

# Database
# https://docs.djangoproject.com/en/1.7/ref/settings/#databases

if os.environ.get('DATABASE_URL', None):
    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.postgresql_psycopg2',
            'NAME': 'taxcalc',
            'USER': 'postgres',
            'PASSWORD': '',
            'HOST': 'localhost',
            'PORT': '5432',
        }
    }
    # Parse database configuration from $DATABASE_URL
    import dj_database_url
    DATABASES['default'] = dj_database_url.config()
else:
    DATABASES = {
        'default': {
          'ENGINE': 'django.db.backends.sqlite3',
          'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
        }
    }

# Internationalization
# https://docs.djangoproject.com/en/1.7/topics/i18n/

LANGUAGE_CODE = 'en-us'

TIME_ZONE = 'UTC'

USE_I18N = True

USE_L10N = True

USE_TZ = True

# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/1.7/howto/static-files/

STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')

STATICFILES_DIRS = (
    os.path.join(BASE_DIR, "static"),
)

# AWS S3 static file storage

# Use Amazon S3 for storage for uploaded media files.
DEFAULT_FILE_STORAGE = "storages.backends.s3boto.S3BotoStorage"

# Amazon S3 settings.
AWS_ACCESS_KEY_ID = os.environ.get("AWS_KEY_ID", "")
AWS_SECRET_ACCESS_KEY = os.environ.get("AWS_SECRET_ID", "")
AWS_STORAGE_BUCKET_NAME = os.environ.get("AWS_STORAGE_BUCKET_NAME", "")
AWS_S3_HOST = os.environ.get("AWS_S3_HOST", None)

# Tell django-storages that when coming up with the URL for an item in S3 storage, keep
# it simple - just use this domain plus the path. (If this isn't set, things get complicated).
# This controls how the `static` template tag from `staticfiles` gets expanded, if you're using it.
# We also use it in the next setting.
AWS_S3_CUSTOM_DOMAIN = '%s.s3.amazonaws.com' % AWS_STORAGE_BUCKET_NAME

# This is used by the `static` template tag from `static`, if you're using that. Or if anything else
# refers directly to STATIC_URL. So it's safest to always set it.

# STATIC_URL is used by StaticFilesStorage to create the path to static assets when
# using the 'static' template tag. In production, we use storages, so just leave this as
# '/static/' for development purposes
#STATIC_URL = "https://%s/" % AWS_S3_CUSTOM_DOMAIN
STATIC_URL = '/static/'

# Tell the staticfiles app to use S3Boto storage when writing the collected static files (when
# you run `collectstatic`).
if True:
    STATICFILES_STORAGE = 'django.contrib.staticfiles.storage.StaticFilesStorage'
else:
    STATICFILES_STORAGE = 'storages.backends.s3boto.S3BotoStorage'

SENDGRID_API_KEY=os.environ.get("SENDGRID_API_KEY", "")
EMAIL_BACKEND = "sgbackend.SendGridBackend"
BLOG_URL = os.environ.get('BLOG_URL', 'http://news.ospc.org/')

GOOGLE_ANALYTICS_PROPERTY_ID = os.environ.get("GOOGLE_ANALYTICS_PROPERTY_ID", "")
GOOGLE_ANALYTICS_EMBEDDED_ID = os.environ.get("GOOGLE_ANALYTICS_EMBEDDED_ID", "")
GOOGLE_ANALYTICS_DOMAIN = os.environ.get("GOOGLE_ANALYTICS_DOMAIN", "")
<commit_msg>Update settings.py<commit_after>"""
Django settings for webapp project.

For more information on this file, see
https://docs.djangoproject.com/en/1.7/topics/settings/

For the full list of settings and their values, see
https://docs.djangoproject.com/en/1.7/ref/settings/
"""
# Honor the 'X-Forwarded-Proto' header for request.is_secure()
SECURE_PROXY_SSL_HEADER = ['HTTP_X_FORWARDED_PROTO', 'https']

import os

SECRET_KEY = os.environ.get('SECRET_KEY', 'secret key')
SITE_ID = os.environ.get('SITE_ID', 1)

# Allow all host headers
ALLOWED_HOSTS = ['*']

SITE_ID = 1

# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
import dj_database_url
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/1.7/howto/deployment/checklist/

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True if os.environ.get('DEV_DEBUG') == 'True' else False

TEMPLATE_DEBUG = DEBUG

TEMPLATE_DIRS = [
    (BASE_DIR + '/templates/'),
]

from django.conf import global_settings

WEBAPP_VERSION = "1.3.0"

TEMPLATE_CONTEXT_PROCESSORS = global_settings.TEMPLATE_CONTEXT_PROCESSORS + [
    'webapp.apps.pages.views.settings_context_processor',
    'webapp.context_processors.google_analytics',
]

# Application definition

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.humanize',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'django.contrib.sites',

    # Apps
    'webapp.apps.taxbrain',
    'webapp.apps.dynamic',
    'webapp.apps.pages',
    'webapp.apps.register',
    'webapp.apps.btax',

    # Third party apps
    'flatblocks',
    'account',
    'gunicorn',
    'hermes',
    'import_export',
    'storages'
]

MIDDLEWARE_CLASSES = [
    'django.middleware.gzip.GZipMiddleware',
    'htmlmin.middleware.HtmlMinifyMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

ROOT_URLCONF = 'webapp.urls'

WSGI_APPLICATION = 'webapp.wsgi.application'

CELERY_RESULT_BACKEND = os.environ.get('REDISGREEN_URL')

BROKER_URL = os.environ.get('REDISGREEN_URL')

# Database
# https://docs.djangoproject.com/en/1.7/ref/settings/#databases

if os.environ.get('DATABASE_URL', None):
    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.postgresql_psycopg2',
            'NAME': 'taxcalc',
            'USER': 'postgres',
            'PASSWORD': '',
            'HOST': 'localhost',
            'PORT': '5432',
        }
    }
    # Parse database configuration from $DATABASE_URL
    import dj_database_url
    DATABASES['default'] = dj_database_url.config()
else:
    DATABASES = {
        'default': {
          'ENGINE': 'django.db.backends.sqlite3',
          'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
        }
    }

# Internationalization
# https://docs.djangoproject.com/en/1.7/topics/i18n/

LANGUAGE_CODE = 'en-us'

TIME_ZONE = 'UTC'

USE_I18N = True

USE_L10N = True

USE_TZ = True

# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/1.7/howto/static-files/

STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')

STATICFILES_DIRS = [
    os.path.join(BASE_DIR, "static"),
]

# AWS S3 static file storage

# Use Amazon S3 for storage for uploaded media files.
DEFAULT_FILE_STORAGE = "storages.backends.s3boto.S3BotoStorage"

# Amazon S3 settings.
AWS_ACCESS_KEY_ID = os.environ.get("AWS_KEY_ID", "")
AWS_SECRET_ACCESS_KEY = os.environ.get("AWS_SECRET_ID", "")
AWS_STORAGE_BUCKET_NAME = os.environ.get("AWS_STORAGE_BUCKET_NAME", "")
AWS_S3_HOST = os.environ.get("AWS_S3_HOST", None)

# Tell django-storages that when coming up with the URL for an item in S3 storage, keep
# it simple - just use this domain plus the path. (If this isn't set, things get complicated).
# This controls how the `static` template tag from `staticfiles` gets expanded, if you're using it.
# We also use it in the next setting.
AWS_S3_CUSTOM_DOMAIN = '%s.s3.amazonaws.com' % AWS_STORAGE_BUCKET_NAME

# This is used by the `static` template tag from `static`, if you're using that. Or if anything else
# refers directly to STATIC_URL. So it's safest to always set it.

# STATIC_URL is used by StaticFilesStorage to create the path to static assets when
# using the 'static' template tag. In production, we use storages, so just leave this as
# '/static/' for development purposes
#STATIC_URL = "https://%s/" % AWS_S3_CUSTOM_DOMAIN
STATIC_URL = '/static/'

# Tell the staticfiles app to use S3Boto storage when writing the collected static files (when
# you run `collectstatic`).
if True:
    STATICFILES_STORAGE = 'django.contrib.staticfiles.storage.StaticFilesStorage'
else:
    STATICFILES_STORAGE = 'storages.backends.s3boto.S3BotoStorage'

SENDGRID_API_KEY=os.environ.get("SENDGRID_API_KEY", "")
EMAIL_BACKEND = "sgbackend.SendGridBackend"
BLOG_URL = os.environ.get('BLOG_URL', 'http://news.ospc.org/')

GOOGLE_ANALYTICS_PROPERTY_ID = os.environ.get("GOOGLE_ANALYTICS_PROPERTY_ID", "")
GOOGLE_ANALYTICS_EMBEDDED_ID = os.environ.get("GOOGLE_ANALYTICS_EMBEDDED_ID", "")
GOOGLE_ANALYTICS_DOMAIN = os.environ.get("GOOGLE_ANALYTICS_DOMAIN", "")
<|endoftext|>


<commit_before>##########################################################################
#
#  Copyright (c) 2016, Image Engine Design Inc. All rights reserved.
#
#  Redistribution and use in source and binary forms, with or without
#  modification, are permitted provided that the following conditions are
#  met:
#
#      * Redistributions of source code must retain the above
#        copyright notice, this list of conditions and the following
#        disclaimer.
#
#      * Redistributions in binary form must reproduce the above
#        copyright notice, this list of conditions and the following
#        disclaimer in the documentation and/or other materials provided with
#        the distribution.
#
#      * Neither the name of John Haddon nor the names of
#        any other contributors to this software may be used to endorse or
#        promote products derived from this software without specific prior
#        written permission.
#
#  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
#  IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
#  THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
#  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
#  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
#  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
#  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
#  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
#  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
#  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
#  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
##########################################################################

import os
import gc
import sys
import time
import resource
import collections

import IECore

import Gaffer

class stats( Gaffer.Application ) :

	def __init__( self ) :

		Gaffer.Application.__init__( self )

		self.parameters().addParameters(

			[
				IECore.FileNameParameter(
					name = "script",
					description = "The script to examine.",
					defaultValue = "",
					allowEmptyString = False,
					extensions = "gfr",
					check = IECore.FileNameParameter.CheckType.MustExist,
				),

				IECore.FloatParameter(
					name = "frame",
					description = "The frame to evaluate statistics at.",
					defaultValue = 1,
				),

				IECore.StringParameter(
					name = "scene",
					description = "The name of a SceneNode or ScenePlug to examine.",
					defaultValue = "",
				),

				IECore.BoolParameter(
					name = "performanceMonitor",
					description = "Turns on a performance monitor to provide additional"
						"statistics about the operation of the node graph.",
					defaultValue = False,
				),

				IECore.IntParameter(
					name = "mostFrequentlyHashed",
					description = "The number of most-frequently hashed plugs to print. "
						"Only used when the performance monitor is on.",
					defaultValue = 50,
				),

				IECore.IntParameter(
					name = "mostFrequentlyComputed",
					description = "The number of most-frequently hashed plugs to print. "
						"Only used when the performance monitor is on.",
					defaultValue = 50,
				)

			]

		)

		self.parameters().userData()["parser"] = IECore.CompoundObject(
			{
				"flagless" : IECore.StringVectorData( [ "script" ] )
			}
		)

	def _run( self, args ) :

		if args["performanceMonitor"].value :
			self.__performanceMonitor = Gaffer.PerformanceMonitor()
		else :
			self.__performanceMonitor = None

		self.__timers = collections.OrderedDict()
		self.__memory = collections.OrderedDict()

		self.__memory["Application"] = _Memory.maxRSS()

		script = Gaffer.ScriptNode()
		script["fileName"].setValue( os.path.abspath( args["script"].value ) )

		with _Timer() as loadingTimer :
			script.load( continueOnError = True )
		self.__timers["Loading"] = loadingTimer

		self.__memory["Script"] = _Memory.maxRSS() - self.__memory["Application"]

		with Gaffer.Context( script.context() ) as context :

			context.setFrame( args["frame"].value )

			self.__printVersion( script )

			print ""

			self.__printSettings( script )

			print ""

			self.__printVariables( script )

			print ""

			self.__printNodes( script )

			if args["scene"].value :

				self.__printScene( script, args )

		print ""

		self.__printMemory()

		print ""

		self.__printPerformance( script, args )

		print

	def __printVersion( self, script ) :

		numbers = [ Gaffer.Metadata.nodeValue( script, "serialiser:" + x + "Version" ) for x in ( "milestone", "major", "minor", "patch" ) ]
		if None not in numbers :
			version = ".".join( str( x ) for x in numbers )
		else :
			version = "unknown"

		print "Gaffer Version : {version}".format( version = version )

	def __printItems( self, items ) :

		if not len( items ) :
			return

		width = max( [ len( x[0] ) for x in items ] ) + 4
		for name, value in items :
			print "  {name:<{width}}{value}".format( name = name, width = width, value = value )

	def __printSettings( self, script ) :

		plugsToIgnore = {
			script["fileName"],
			script["unsavedChanges"],
			script["variables"],
		}

		items = []
		def itemsWalk( p ) :

			if p in plugsToIgnore :
				return

			if hasattr( p, "getValue" ) :
				items.append( ( p.relativeName( script ), p.getValue() ) )
			else :
				for c in p.children( Gaffer.Plug ) :
					itemsWalk( c )

		itemsWalk( script )

		print "Settings :\n"
		self.__printItems( items )

	def __printVariables( self, script ) :

		items = []
		for p in script["variables"] :
			data, name = script["variables"].memberDataAndName( p )
			if data is not None :
				items.append( ( name, data ) )

		print "Variables :\n"
		self.__printItems( items )

	def __printNodes( self, script ) :

		def countWalk( node, counter ) :

			if not isinstance( node, Gaffer.ScriptNode ) :
				counter[node.typeName()] += 1

			for c in node.children( Gaffer.Node ) :
				countWalk( c, counter )

		counter = collections.Counter()
		countWalk( script, counter )

		items = [ ( nodeType.rpartition( ":" )[2], count ) for nodeType, count in counter.most_common() ]
		items.extend( [
			( "", "" ),
			( "Total", sum( counter.values() ) ),
		] )

		print "Nodes :\n"
		self.__printItems( items )

	def __printScene( self, script, args ) :

		import GafferScene
		import GafferSceneTest

		scene = script.descendant( args["scene"].value )
		if isinstance( scene, Gaffer.Node ) :
			scene = next( ( x for x in scene.children( GafferScene.ScenePlug ) ), None )

		if scene is None :
			IECore.msg( IECore.Msg.Level.Error, "stats", "Scene \"%s\" does not exist" % args["scene"].value )
			return

		memory = _Memory.maxRSS()
		with _Timer() as sceneTimer :
			with self.__performanceMonitor or _NullContextManager() :
				GafferSceneTest.traverseScene( scene )
		self.__timers["Scene generation"] = sceneTimer
		self.__memory["Scene generation"] = _Memory.maxRSS() - memory

		## \todo Calculate and print scene stats
		#  - Locations
		#  - Unique objects, attributes etc

	def __printMemory( self ) :

		objectPool = IECore.ObjectPool.defaultObjectPool()

		items = self.__memory.items()

		items.extend( [
			( "", "" ),
			( "Cache limit", _Memory( Gaffer.ValuePlug.getCacheMemoryLimit() ) ),
			( "Cache usage", _Memory( Gaffer.ValuePlug.cacheMemoryUsage() ) ),
			( "", "" ),
			( "Object pool limit", _Memory( objectPool.getMaxMemoryUsage() ) ),
			( "Object pool usage", _Memory( objectPool.memoryUsage() ) ),
			( "", "" ),
			( "Max resident size", _Memory.maxRSS() ),
		] )

		print "Memory :\n"
		self.__printItems( items )

	def __printStatisticsItems( self, script, stats, key, n ) :

		stats.sort( key = key, reverse = True )
		items = [ ( x[0].relativeName( script ), key( x ) ) for x in stats[:n] ]
		self.__printItems( items )

	def __printPerformance( self, script, args ) :

			print "Performance :\n"
			self.__printItems( self.__timers.items() )

			if self.__performanceMonitor is None :
				return

			stats = self.__performanceMonitor.allStatistics().items()

			print "\nMost frequently hashed :\n"
			self.__printStatisticsItems( script, stats, lambda x : x[1].hashCount, args["mostFrequentlyHashed"].value )

			print "\nMost frequently computed :\n"
			self.__printStatisticsItems( script, stats, lambda x : x[1].computeCount, args["mostFrequentlyComputed"].value )

class _Timer( object ) :

	def __enter__( self ) :

		self.__time = time.time()
		self.__clock = time.clock()

		return self

	def __exit__( self, type, value, traceBack ) :

		self.__time = time.time() - self.__time
		self.__clock = time.clock() - self.__clock

	def __str__( self ) :

		return "%.3fs (wall), %.3fs (CPU)" % ( self.__time, self.__clock )

class _Memory( object ) :

	def __init__( self, bytes ) :

		self.__bytes = bytes

	@classmethod
	def maxRSS( cls ) :

		if sys.platform == "darwin" :
			return cls( resource.getrusage( resource.RUSAGE_SELF ).ru_maxrss )
		else :
			return cls( resource.getrusage( resource.RUSAGE_SELF ).ru_maxrss * 1024 )

	def __str__( self ) :

		return "%.3fM" % ( self.__bytes / ( 1024 * 1024. ) )

	def __sub__( self, other ) :

		return _Memory( self.__bytes - other.__bytes )

class _NullContextManager( object ) :

	def __enter__( self ) :

		pass

	def __exit__( self, type, value, traceBack ) :

		pass

IECore.registerRunTimeTyped( stats )
<commit_msg>Stats app : Add image support.<commit_after>##########################################################################
#
#  Copyright (c) 2016, Image Engine Design Inc. All rights reserved.
#
#  Redistribution and use in source and binary forms, with or without
#  modification, are permitted provided that the following conditions are
#  met:
#
#      * Redistributions of source code must retain the above
#        copyright notice, this list of conditions and the following
#        disclaimer.
#
#      * Redistributions in binary form must reproduce the above
#        copyright notice, this list of conditions and the following
#        disclaimer in the documentation and/or other materials provided with
#        the distribution.
#
#      * Neither the name of John Haddon nor the names of
#        any other contributors to this software may be used to endorse or
#        promote products derived from this software without specific prior
#        written permission.
#
#  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
#  IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
#  THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
#  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
#  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
#  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
#  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
#  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
#  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
#  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
#  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
##########################################################################

import os
import gc
import sys
import time
import resource
import collections

import IECore

import Gaffer

class stats( Gaffer.Application ) :

	def __init__( self ) :

		Gaffer.Application.__init__( self )

		self.parameters().addParameters(

			[
				IECore.FileNameParameter(
					name = "script",
					description = "The script to examine.",
					defaultValue = "",
					allowEmptyString = False,
					extensions = "gfr",
					check = IECore.FileNameParameter.CheckType.MustExist,
				),

				IECore.FloatParameter(
					name = "frame",
					description = "The frame to evaluate statistics at.",
					defaultValue = 1,
				),

				IECore.StringParameter(
					name = "scene",
					description = "The name of a SceneNode or ScenePlug to examine.",
					defaultValue = "",
				),

				IECore.StringParameter(
					name = "image",
					description = "The name of an ImageNode or ImagePlug to examine.",
					defaultValue = "",
				),

				IECore.BoolParameter(
					name = "performanceMonitor",
					description = "Turns on a performance monitor to provide additional"
						"statistics about the operation of the node graph.",
					defaultValue = False,
				),

				IECore.IntParameter(
					name = "mostFrequentlyHashed",
					description = "The number of most-frequently hashed plugs to print. "
						"Only used when the performance monitor is on.",
					defaultValue = 50,
				),

				IECore.IntParameter(
					name = "mostFrequentlyComputed",
					description = "The number of most-frequently hashed plugs to print. "
						"Only used when the performance monitor is on.",
					defaultValue = 50,
				)

			]

		)

		self.parameters().userData()["parser"] = IECore.CompoundObject(
			{
				"flagless" : IECore.StringVectorData( [ "script" ] )
			}
		)

	def _run( self, args ) :

		if args["performanceMonitor"].value :
			self.__performanceMonitor = Gaffer.PerformanceMonitor()
		else :
			self.__performanceMonitor = None

		self.__timers = collections.OrderedDict()
		self.__memory = collections.OrderedDict()

		self.__memory["Application"] = _Memory.maxRSS()

		script = Gaffer.ScriptNode()
		script["fileName"].setValue( os.path.abspath( args["script"].value ) )

		with _Timer() as loadingTimer :
			script.load( continueOnError = True )
		self.__timers["Loading"] = loadingTimer

		self.__memory["Script"] = _Memory.maxRSS() - self.__memory["Application"]

		with Gaffer.Context( script.context() ) as context :

			context.setFrame( args["frame"].value )

			self.__printVersion( script )

			print ""

			self.__printSettings( script )

			print ""

			self.__printVariables( script )

			print ""

			self.__printNodes( script )

			if args["scene"].value :

				self.__printScene( script, args )

			if args["image"].value :

				self.__printImage( script, args )

		print ""

		self.__printMemory()

		print ""

		self.__printPerformance( script, args )

		print

	def __printVersion( self, script ) :

		numbers = [ Gaffer.Metadata.nodeValue( script, "serialiser:" + x + "Version" ) for x in ( "milestone", "major", "minor", "patch" ) ]
		if None not in numbers :
			version = ".".join( str( x ) for x in numbers )
		else :
			version = "unknown"

		print "Gaffer Version : {version}".format( version = version )

	def __printItems( self, items ) :

		if not len( items ) :
			return

		width = max( [ len( x[0] ) for x in items ] ) + 4
		for name, value in items :
			print "  {name:<{width}}{value}".format( name = name, width = width, value = value )

	def __printSettings( self, script ) :

		plugsToIgnore = {
			script["fileName"],
			script["unsavedChanges"],
			script["variables"],
		}

		items = []
		def itemsWalk( p ) :

			if p in plugsToIgnore :
				return

			if hasattr( p, "getValue" ) :
				items.append( ( p.relativeName( script ), p.getValue() ) )
			else :
				for c in p.children( Gaffer.Plug ) :
					itemsWalk( c )

		itemsWalk( script )

		print "Settings :\n"
		self.__printItems( items )

	def __printVariables( self, script ) :

		items = []
		for p in script["variables"] :
			data, name = script["variables"].memberDataAndName( p )
			if data is not None :
				items.append( ( name, data ) )

		print "Variables :\n"
		self.__printItems( items )

	def __printNodes( self, script ) :

		def countWalk( node, counter ) :

			if not isinstance( node, Gaffer.ScriptNode ) :
				counter[node.typeName()] += 1

			for c in node.children( Gaffer.Node ) :
				countWalk( c, counter )

		counter = collections.Counter()
		countWalk( script, counter )

		items = [ ( nodeType.rpartition( ":" )[2], count ) for nodeType, count in counter.most_common() ]
		items.extend( [
			( "", "" ),
			( "Total", sum( counter.values() ) ),
		] )

		print "Nodes :\n"
		self.__printItems( items )

	def __printScene( self, script, args ) :

		import GafferScene
		import GafferSceneTest

		scene = script.descendant( args["scene"].value )
		if isinstance( scene, Gaffer.Node ) :
			scene = next( ( x for x in scene.children( GafferScene.ScenePlug ) ), None )

		if scene is None :
			IECore.msg( IECore.Msg.Level.Error, "stats", "Scene \"%s\" does not exist" % args["scene"].value )
			return

		memory = _Memory.maxRSS()
		with _Timer() as sceneTimer :
			with self.__performanceMonitor or _NullContextManager() :
				GafferSceneTest.traverseScene( scene )
		self.__timers["Scene generation"] = sceneTimer
		self.__memory["Scene generation"] = _Memory.maxRSS() - memory

		## \todo Calculate and print scene stats
		#  - Locations
		#  - Unique objects, attributes etc

	def __printImage( self, script, args ) :

		import GafferImage
		import GafferImageTest

		image = script.descendant( args["image"].value )
		if isinstance( image, Gaffer.Node ) :
			image = next( ( x for x in image.children( GafferImage.ImagePlug ) ), None )

		if image is None :
			IECore.msg( IECore.Msg.Level.Error, "stats", "Image \"%s\" does not exist" % args["image"].value )
			return

		memory = _Memory.maxRSS()
		with _Timer() as sceneTimer :
			with self.__performanceMonitor or _NullContextManager() :
				GafferImageTest.processTiles( image )
		self.__timers["Image generation"] = sceneTimer
		self.__memory["Image generation"] = _Memory.maxRSS() - memory

		items = [
			( "Format", image["format"].getValue() ),
			( "Data window", image["dataWindow"].getValue() ),
			( "Channel names", image["channelNames"].getValue() ),
		]

		print "\nImage :\n"
		self.__printItems( items )

	def __printMemory( self ) :

		objectPool = IECore.ObjectPool.defaultObjectPool()

		items = self.__memory.items()

		items.extend( [
			( "", "" ),
			( "Cache limit", _Memory( Gaffer.ValuePlug.getCacheMemoryLimit() ) ),
			( "Cache usage", _Memory( Gaffer.ValuePlug.cacheMemoryUsage() ) ),
			( "", "" ),
			( "Object pool limit", _Memory( objectPool.getMaxMemoryUsage() ) ),
			( "Object pool usage", _Memory( objectPool.memoryUsage() ) ),
			( "", "" ),
			( "Max resident size", _Memory.maxRSS() ),
		] )

		print "Memory :\n"
		self.__printItems( items )

	def __printStatisticsItems( self, script, stats, key, n ) :

		stats.sort( key = key, reverse = True )
		items = [ ( x[0].relativeName( script ), key( x ) ) for x in stats[:n] ]
		self.__printItems( items )

	def __printPerformance( self, script, args ) :

			print "Performance :\n"
			self.__printItems( self.__timers.items() )

			if self.__performanceMonitor is None :
				return

			stats = self.__performanceMonitor.allStatistics().items()

			print "\nMost frequently hashed :\n"
			self.__printStatisticsItems( script, stats, lambda x : x[1].hashCount, args["mostFrequentlyHashed"].value )

			print "\nMost frequently computed :\n"
			self.__printStatisticsItems( script, stats, lambda x : x[1].computeCount, args["mostFrequentlyComputed"].value )

class _Timer( object ) :

	def __enter__( self ) :

		self.__time = time.time()
		self.__clock = time.clock()

		return self

	def __exit__( self, type, value, traceBack ) :

		self.__time = time.time() - self.__time
		self.__clock = time.clock() - self.__clock

	def __str__( self ) :

		return "%.3fs (wall), %.3fs (CPU)" % ( self.__time, self.__clock )

class _Memory( object ) :

	def __init__( self, bytes ) :

		self.__bytes = bytes

	@classmethod
	def maxRSS( cls ) :

		if sys.platform == "darwin" :
			return cls( resource.getrusage( resource.RUSAGE_SELF ).ru_maxrss )
		else :
			return cls( resource.getrusage( resource.RUSAGE_SELF ).ru_maxrss * 1024 )

	def __str__( self ) :

		return "%.3fM" % ( self.__bytes / ( 1024 * 1024. ) )

	def __sub__( self, other ) :

		return _Memory( self.__bytes - other.__bytes )

class _NullContextManager( object ) :

	def __enter__( self ) :

		pass

	def __exit__( self, type, value, traceBack ) :

		pass

IECore.registerRunTimeTyped( stats )
<|endoftext|>


<commit_before>from urllib.request import Request, urlopen
import json

req = Request('http://jsonplaceholder.typicode.com/users', headers={'User-Agent': 'Mozilla/5.0'})
response = urlopen(req)
response_string = response.read().decode("utf-8")

json_object = json.loads(response_string)

print(json_object)
#print(json.dumps(json_object, sort_keys=True, indent=4))
#print(json_object[4])
#print(json.dumps(json_object[4], sort_keys=True, indent=4))
#print(json_object[4]["name"])
#print(json_object[4]["address"]["geo"])
#print(json_object[4]["address"]["geo"]["lat"])
#print(json_object[4]["address"]["geo"]["lng"])

response.close()
<commit_msg>Adding Content-Serve Examples<commit_after>from urllib.request import Request, urlopen
import json

req = Request('http://jsonplaceholder.typicode.com/users', headers={'User-Agent': 'Mozilla/5.0'})
# req = Request('http://127.0.0.1:8000/object')
# req = Request('http://127.0.0.1:8000/array')
# req = Request('http://127.0.0.1:8000/random')
# req = Request('http://127.0.0.1:8000/random/array')
# req = Request('http://127.0.0.1:8000/complex')
# req = Request('http://127.0.0.1:8000/complex/array')

response = urlopen(req)
response_string = response.read().decode("utf-8")

json_object = json.loads(response_string)

print(json_object)
#print(json.dumps(json_object, sort_keys=True, indent=4))
#print(json_object[4])
#print(json.dumps(json_object[4], sort_keys=True, indent=4))
#print(json_object[4]["name"])
#print(json_object[4]["address"]["geo"])
#print(json_object[4]["address"]["geo"]["lat"])
#print(json_object[4]["address"]["geo"]["lng"])

response.close()
<|endoftext|>


<commit_before># Implement an algorithm that will check whether a given grid of numbers represents a valid Sudoku puzzle

def check_rows(grid):
	for i in range(9):
		ref_check = {}
		for j in range(9):
			if grid[i][j] != '.' and grid[i][j] in ref_check:
				return False
			else:
				ref_check[grid[i][j]] = 1
	return True

def check_columns(grid):
	for i in range(9):
		ref_check = {}
		for j in range(9):
			if grid[j][i] != '.' and grid[j][i] in ref_check:
				return False
			else:
				ref_check[grid[j][i]] = 1
	return True

def check_array(array):
	ref_check = {}
	for square in array:
		if square != '.' and square in ref_check:
			return False
		else:
			ref_check[square] = 1
	return True

def check_sub_grid(grid):
	for row in range(0, 9, 3):
		for i in range(0, 9, 3):
			a = []
			for j in range(row, row + 3):
				for column in range(i, i + 3):
					a.append(grid[j][column])
				if not check_array(a):
					return False
	return True

def sudoku_check(grid):
	return check_rows(grid) and check_columns(grid) and check_sub_grid(grid)
<commit_msg>Add test cases<commit_after># Implement an algorithm that will check whether a given grid of numbers represents a valid Sudoku puzzle

def check_rows(grid):
	for i in range(9):
		ref_check = {}
		for j in range(9):
			if grid[i][j] != '.' and grid[i][j] in ref_check:
				return False
			else:
				ref_check[grid[i][j]] = 1
	return True

def check_columns(grid):
	for i in range(9):
		ref_check = {}
		for j in range(9):
			if grid[j][i] != '.' and grid[j][i] in ref_check:
				return False
			else:
				ref_check[grid[j][i]] = 1
	return True

def check_array(array):
	ref_check = {}
	for square in array:
		if square != '.' and square in ref_check:
			return False
		else:
			ref_check[square] = 1
	return True

def check_sub_grid(grid):
	for row in range(0, 9, 3):
		for i in range(0, 9, 3):
			a = []
			for j in range(row, row + 3):
				for column in range(i, i + 3):
					a.append(grid[j][column])
				if not check_array(a):
					return False
	return True

def sudoku_check(grid):
	return check_rows(grid) and check_columns(grid) and check_sub_grid(grid)

# test cases
test_one = [[".",".",".","1","4",".",".","2","."],
 			[".",".","6",".",".",".",".",".","."],
 			[".",".",".",".",".",".",".",".","."],
 			[".",".","1",".",".",".",".",".","."],
 			[".","6","7",".",".",".",".",".","9"],
 			[".",".",".",".",".",".","8","1","."],
 			[".","3",".",".",".",".",".",".","6"],
 			[".",".",".",".",".","7",".",".","."],
 			[".",".",".","5",".",".",".","7","."]]
print sudoku_check(test_one)

test_two = [[".",".",".",".","2",".",".","9","."],
 			[".",".",".",".","6",".",".",".","."],
 			["7","1",".",".","7","5",".",".","."],
 			[".","7",".",".",".",".",".",".","."],
 			[".",".",".",".","8","3",".",".","."],
 			[".",".","8",".",".","7",".","6","."],
 			[".",".",".",".",".","2",".",".","."],
 			[".","1",".","2",".",".",".",".","."],
 			[".","2",".",".","3",".",".",".","."]]
print sudoku_check(test_two)

test_three = [[".",".","4",".",".",".","6","3","."],
 			  [".",".",".",".",".",".",".",".","."],
 			  ["5",".",".",".",".",".",".","9","."],
 			  [".",".",".","5","6",".",".",".","."],
 			  ["4",".","3",".",".",".",".",".","1"],
 			  [".",".",".","7",".",".",".",".","."],
 			  [".",".",".","5",".",".",".",".","."],
 			  [".",".",".",".",".",".",".",".","."],
 			  [".",".",".",".",".",".",".",".","."]]
print sudoku_check(test_three)
<|endoftext|>


<commit_before>from django.db import models
from django.contrib.auth.models import User
import datetime

class Position(models.Model):
    """A position in ASPC (elected, appointed, or hired)"""

    title = models.CharField(
        max_length=80,
        help_text="The official title of the position")
    description = models.TextField(
        blank=True,
        help_text="(optional) Description of the position")
    appointments = models.ManyToManyField(
        User,
        through="Appointment",
        help_text="Current and past appointees to this position")
    active = models.BooleanField(
        default=True,
        help_text="Whether or not a position is still active (for display "
                  "in the list of Senate positions)")
    sort_order = models.PositiveSmallIntegerField(
        blank=True,
        help_text="Sort ordering")

    class Meta:
        ordering = ['sort_order', 'title']

    def __unicode__(self):
        return self.title

    def current_appointee(self):
        appts = self.appointments.filter(start__lte=datetime.date.today())
        appts = (
            appts.filter(end__isnull=True) |
            appts.filter(end__gte=datetime.date.today())
        )
        if appts.count():
            return appts[0]
        else:
            return none

    def save(self, *args, **kwargs):
        if not self.sort_order:
            positions = Position.objects.order_by('-sort_order')
            if not positions.count():
                self.sort_order = 1
            else:
                self.sort_order = positions[0].sort_order + 1
        super(Position, self).save(*args, **kwargs)

class Appointment(models.Model):
    """Information on the start and end dates of a particular ASPC position"""

    position = models.ForeignKey(Position)
    login_id = models.CharField(max_length=20, blank=True, null=True)

    user = models.ForeignKey(User, blank=True, null=True)

    start = models.DateField()
    end = models.DateField(null=True, blank=True)

    class Meta:
        ordering = ['start', 'position']

    def __unicode__(self):
        return u"{0}: {1} from {2} to {3}".format(
            self.position.title,
            self.user.get_full_name(),
            self.start,
            self.end)
<commit_msg>Cleaning up stashes; not a working version<commit_after>from django.db import models
from django.contrib.auth.models import User, Group
import datetime

class Position(models.Model):
    """A position in ASPC (elected, appointed, or hired)"""

    title = models.CharField(
        max_length=80,
        help_text="The official title of the position")
    description = models.TextField(
        blank=True,
        help_text="(optional) Description of the position")
    appointments = models.ManyToManyField(
        User,
        through="Appointment",
        help_text="Current and past appointees to this position")
    active = models.BooleanField(
        default=True,
        help_text="Whether or not a position is still active (for display "
                  "in the list of Senate positions)")
    groups = models.ManyToManyField(
        Group,
        help_text="Groups that people holding this position should be added "
                  "to for permissions reasons"
    )
    sort_order = models.PositiveSmallIntegerField(
        blank=True,
        help_text="Sort ordering")

    class Meta:
        ordering = ['sort_order', 'title']

    def __unicode__(self):
        return self.title

    def current_appointee(self):
        appts = self.appointments.filter(start__lte=datetime.date.today())
        appts = (
            appts.filter(end__isnull=True) |
            appts.filter(end__gte=datetime.date.today())
        )
        if appts.count():
            return appts[0]
        else:
            return none

    def save(self, *args, **kwargs):
        if not self.sort_order:
            positions = Position.objects.order_by('-sort_order')
            if not positions.count():
                self.sort_order = 1
            else:
                self.sort_order = positions[0].sort_order + 1
        super(Position, self).save(*args, **kwargs)

class Appointment(models.Model):
    """Information on the start and end dates of a particular ASPC position"""

    position = models.ForeignKey(Position)
    login_id = models.CharField(max_length=20, blank=True, null=True)

    user = models.ForeignKey(User, blank=True, null=True)

    start = models.DateField()
    end = models.DateField(null=True, blank=True)

    class Meta:
        ordering = ['start', 'position']

    def __unicode__(self):
        return u"{0}: {1} from {2} to {3}".format(
            self.position.title,
            self.user.get_full_name(),
            self.start,
            self.end)

# Watch for user logins to make sure they have the permissions their position
# requires

from django.contrib.auth.signals import user_logged_in

def sync_permissions(sender, user, request, **kwargs):
    try:
        # Does the user have an active appointment?
        appt = Appointment.objects.get(
            login_id=user.username,
            start__lte=datetime.date.today(),
            end__gte=datetime.date.today(),
        )
        appt.user = user

        # One side effect of this is that users will not be removed from a
        # group just because their position has been removed from a group
        user.groups.add(list(appt.position.groups.all()))

        appt.save()
    except Appointment.DoesNotExist:
        # No current appointment for this user
        pass

    try:
        # Does the user have an expired appointment?
        appt = Appointment.objects.get(
            user=user,
            end__lte=datetime.date.today(),
        )
    except Appointment.DoesNotExist:

user_logged_in.connect(sync_permissions)<|endoftext|>


<commit_before>from collections import namedtuple

from telegram import InlineKeyboardButton, InlineKeyboardMarkup, ParseMode, Update
from telegram.error import BadRequest
from telegram.ext import CommandHandler, RegexHandler, run_async, Filters, MessageHandler, CallbackContext

import const
import util

HINTS = {
    '#inline': {
        'message': "Consider using me in inline-mode 😎\n`@roolsbot {query}`",
        'default': "Your search terms",
        'buttons': [{
            'text': '🔎 Try it out',
            'switch_inline_query': '{query}'
        }],
        'help': 'Give a query that will be used for a `switch_to_inline`-button'
    },
    '#private': {
        'message': "Please don't spam the group with {query}, and go to a private "
                   "chat with me instead. Thanks a lot, the other members will appreciate it 😊",
        'default': 'searches or commands',
        'buttons': [{
            'text': '🤖 Go to private chat',
            'url': "https://t.me/{}".format(const.SELF_BOT_NAME)
        }],
        'help': 'Tell a member to stop spamming and switch to a private chat',
    },
    '#issue': {
        'message': "Hi,\n\nThis is not an issue with the library's code, but a usage question. "
                   "Feel free to ask it in our [telegram group](https://t.me/pythontelegrambotgroup). "
                   "Or (if you can't reach our group) our [IRC channel](https://webchat.freenode.net/?channels=##python-telegram-bot).\n{query}",
        'default': '',
        'help': 'Send issue template',
    },
    '#userbot': {
        'message': "Refer to [this article](http://telegra.ph/How-a-"
                   "Userbot-superacharges-your-Telegram-Bot-07-09) to learn more about *Userbots*.",
        'help': "@JosXa's article about Userbots"
    },
    '#snippets': {
        'message': "[Here](https://github.com/python-telegram-bot/python-telegram-bot/wiki/Code-snippets) "
                   "you can find many useful code snippets for the work with python-telegram-bot",
        'help': "Link to the wiki's *snippets* section",
    },
    '#pprint': {
        'message': """
            The most convenient way of *pretty-printing an update* is:

    `from pprint import pprint`
    `pprint(update.to_dict())`

It shows you what attributes are available in an update. Alternatively, use a json dumping bot like @JsonDumpBot or @JsonDumpBetaBot for a general overview, but keep in mind that this method won't be entirely consistent with your bot's updates (different file\_ids for example).""",
        'help': "Explain how to pretty-print an update"
    },
    '#meta': {
        'message': """No need for meta questions. Just ask! 🤗
_"Has anyone done .. before?"_
Probably. *Just ask your question and somebody will help!*
        """,
        'help': "Show our stance on meta-questions"
    },
    '#tutorial': {
        'message': """Oh, hey! There's someone new joining our awesome community of Python developers ❤ We have compiled a list of learning resources _just for you_:
• [As Beginner](https://wiki.python.org/moin/BeginnersGuide/NonProgrammers)
• [As Programmer](https://wiki.python.org/moin/BeginnersGuide/Programmers)
• [Official Tutorial](https://docs.python.org/3/tutorial/)
• [Dive into Python](http://www.diveintopython3.net/)
• [Learn Python](https://www.learnpython.org/)
• [Computer Science Circles](https://cscircles.cemc.uwaterloo.ca/)
• [MIT OpenCourse](https://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-0001-introduction-to-computer-science-and-programming-in-python-fall-2016/)
• [Hitchhiker’s Guide to Python](https://docs.python-guide.org/)
• The @PythonRes Telegram Channel.
• Corey Schafer videos for [beginners](https://www.youtube.com/watch?v=YYXdXT2l-Gg&list=PL-osiE80TeTskrapNbzXhwoFUiLCjGgY7) and in [general](https://www.youtube.com/watch?v=YYXdXT2l-Gg&list=PL-osiE80TeTt2d9bfVyTiXJA-UTHn6WwU)
• [Project Python](http://projectpython.net/chapter00/)""",
        'help': "How to find a Python tutorial"
    },
    '#wronglib': {
        'message': """Hey, I think you're wrong 🧐
It looks like you're not using the python-telegram-bot library. If you insist on using that other one, please go where you belong:
[pyTelegramBotApi](https://telegram.me/joinchat/Bn4ixj84FIZVkwhk2jag6A)
[Telepot](https://github.com/nickoala/telepot)
        """,
        'help': "Other Python wrappers for Telegram"
    }
}

@run_async
def list_available_hints(update: Update, context: CallbackContext):
    message = "You can use the following hashtags to guide new members:\n\n"
    message += '\n'.join(
        '🗣 {tag} ➖ {help}'.format(
            tag=k, help=v['help']
        ) for k, v in HINTS.items()
    )
    message += "\n\nMake sure to reply to another message, so I know who to refer to."
    update.effective_message.reply_text(message, parse_mode='markdown',
                                        disable_web_page_preview=True)

Hint = namedtuple('Hint', 'help, msg, reply_markup')

def get_hints(query):
    results = {}
    hashtag, _, query = query.partition(' ')

    for k, v in HINTS.items():
        if k.startswith(hashtag):
            reply_markup = InlineKeyboardMarkup(util.build_menu([InlineKeyboardButton(
                **{k: v.format(query=query) for k, v in b.items()}
            ) for b in v['buttons']], 1)) if 'buttons' in v else None

            msg = v['message'].format(query=query if query else v.get('default', ''))

            results[k] = Hint(help=v.get('help', ''), msg=msg, reply_markup=reply_markup)

    return results

@run_async
def hint_handler(update: Update, context: CallbackContext):
    reply_to = update.message.reply_to_message

    hint = get_hints(update.message.text).popitem()[1]

    if hint is not None:
        update.effective_message.reply_text(hint.msg,
                                            reply_markup=hint.reply_markup,
                                            reply_to_message_id=reply_to.message_id if reply_to else None,
                                            parse_mode=ParseMode.MARKDOWN,
                                            disable_web_page_preview=True)
        try:
            update.effective_message.delete()
        except BadRequest:
            pass

def register(dispatcher):
    dispatcher.add_handler(MessageHandler(Filters.regex(rf'{"|".join(HINTS.keys())}.*'), hint_handler))
    dispatcher.add_handler(CommandHandler(('hints', 'listhints'), list_available_hints))
<commit_msg>Add hint about asking technical questions (#41)<commit_after>from collections import namedtuple

from telegram import InlineKeyboardButton, InlineKeyboardMarkup, ParseMode, Update
from telegram.error import BadRequest
from telegram.ext import CommandHandler, RegexHandler, run_async, Filters, MessageHandler, CallbackContext

import const
import util

HINTS = {
    '#inline': {
        'message': "Consider using me in inline-mode 😎\n`@roolsbot {query}`",
        'default': "Your search terms",
        'buttons': [{
            'text': '🔎 Try it out',
            'switch_inline_query': '{query}'
        }],
        'help': 'Give a query that will be used for a `switch_to_inline`-button'
    },
    '#private': {
        'message': "Please don't spam the group with {query}, and go to a private "
                   "chat with me instead. Thanks a lot, the other members will appreciate it 😊",
        'default': 'searches or commands',
        'buttons': [{
            'text': '🤖 Go to private chat',
            'url': "https://t.me/{}".format(const.SELF_BOT_NAME)
        }],
        'help': 'Tell a member to stop spamming and switch to a private chat',
    },
    '#issue': {
        'message': "Hi,\n\nThis is not an issue with the library's code, but a usage question. "
                   "Feel free to ask it in our [telegram group](https://t.me/pythontelegrambotgroup). "
                   "Or (if you can't reach our group) our [IRC channel](https://webchat.freenode.net/?channels=##python-telegram-bot).\n{query}",
        'default': '',
        'help': 'Send issue template',
    },
    '#userbot': {
        'message': "Refer to [this article](http://telegra.ph/How-a-"
                   "Userbot-superacharges-your-Telegram-Bot-07-09) to learn more about *Userbots*.",
        'help': "@JosXa's article about Userbots"
    },
    '#snippets': {
        'message': "[Here](https://github.com/python-telegram-bot/python-telegram-bot/wiki/Code-snippets) "
                   "you can find many useful code snippets for the work with python-telegram-bot",
        'help': "Link to the wiki's *snippets* section",
    },
    '#pprint': {
        'message': """
            The most convenient way of *pretty-printing an update* is:

    `from pprint import pprint`
    `pprint(update.to_dict())`

It shows you what attributes are available in an update. Alternatively, use a json dumping bot like @JsonDumpBot or @JsonDumpBetaBot for a general overview, but keep in mind that this method won't be entirely consistent with your bot's updates (different file\_ids for example).""",
        'help': "Explain how to pretty-print an update"
    },
    '#meta': {
        'message': """No need for meta questions. Just ask! 🤗
_"Has anyone done .. before?"_
Probably. *Just ask your question and somebody will help!*
        """,
        'help': "Show our stance on meta-questions"
    },
    '#tutorial': {
        'message': """Oh, hey! There's someone new joining our awesome community of Python developers ❤ We have compiled a list of learning resources _just for you_:
• [As Beginner](https://wiki.python.org/moin/BeginnersGuide/NonProgrammers)
• [As Programmer](https://wiki.python.org/moin/BeginnersGuide/Programmers)
• [Official Tutorial](https://docs.python.org/3/tutorial/)
• [Dive into Python](http://www.diveintopython3.net/)
• [Learn Python](https://www.learnpython.org/)
• [Computer Science Circles](https://cscircles.cemc.uwaterloo.ca/)
• [MIT OpenCourse](https://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-0001-introduction-to-computer-science-and-programming-in-python-fall-2016/)
• [Hitchhiker’s Guide to Python](https://docs.python-guide.org/)
• The @PythonRes Telegram Channel.
• Corey Schafer videos for [beginners](https://www.youtube.com/watch?v=YYXdXT2l-Gg&list=PL-osiE80TeTskrapNbzXhwoFUiLCjGgY7) and in [general](https://www.youtube.com/watch?v=YYXdXT2l-Gg&list=PL-osiE80TeTt2d9bfVyTiXJA-UTHn6WwU)
• [Project Python](http://projectpython.net/chapter00/)""",
        'help': "How to find a Python tutorial"
    },
    '#wronglib': {
        'message': """Hey, I think you're wrong 🧐
It looks like you're not using the python-telegram-bot library. If you insist on using that other one, please go where you belong:
[pyTelegramBotApi](https://telegram.me/joinchat/Bn4ixj84FIZVkwhk2jag6A)
[Telepot](https://github.com/nickoala/telepot)
        """,
        'help': "Other Python wrappers for Telegram"
    },
    '#askright': {
        'message': """Hey.
        In order for someone to be able to help you, you must ask a *good technical question*. Please read [this short article](http://telegra.ph/How-not-to-ask-technical-questions-05-10) and try again ;)
        """,
        'help': "@d_Rickyy_b's article about asking technical questions"
    }
}

@run_async
def list_available_hints(update: Update, context: CallbackContext):
    message = "You can use the following hashtags to guide new members:\n\n"
    message += '\n'.join(
        '🗣 {tag} ➖ {help}'.format(
            tag=k, help=v['help']
        ) for k, v in HINTS.items()
    )
    message += "\n\nMake sure to reply to another message, so I know who to refer to."
    update.effective_message.reply_text(message, parse_mode='markdown',
                                        disable_web_page_preview=True)

Hint = namedtuple('Hint', 'help, msg, reply_markup')

def get_hints(query):
    results = {}
    hashtag, _, query = query.partition(' ')

    for k, v in HINTS.items():
        if k.startswith(hashtag):
            reply_markup = InlineKeyboardMarkup(util.build_menu([InlineKeyboardButton(
                **{k: v.format(query=query) for k, v in b.items()}
            ) for b in v['buttons']], 1)) if 'buttons' in v else None

            msg = v['message'].format(query=query if query else v.get('default', ''))

            results[k] = Hint(help=v.get('help', ''), msg=msg, reply_markup=reply_markup)

    return results

@run_async
def hint_handler(update: Update, context: CallbackContext):
    reply_to = update.message.reply_to_message

    hint = get_hints(update.message.text).popitem()[1]

    if hint is not None:
        update.effective_message.reply_text(hint.msg,
                                            reply_markup=hint.reply_markup,
                                            reply_to_message_id=reply_to.message_id if reply_to else None,
                                            parse_mode=ParseMode.MARKDOWN,
                                            disable_web_page_preview=True)
        try:
            update.effective_message.delete()
        except BadRequest:
            pass

def register(dispatcher):
    dispatcher.add_handler(MessageHandler(Filters.regex(rf'{"|".join(HINTS.keys())}.*'), hint_handler))
    dispatcher.add_handler(CommandHandler(('hints', 'listhints'), list_available_hints))
<|endoftext|>