<commit_before>import flask
from flask import render_template
from flask import request
from flask import url_for
import json
import logging
import uuid

# Date handling
import arrow  # Replacement for datetime, based on moment.js
import datetime  # But we still need time
from dateutil import tz  # For interpreting local times

# OAuth2  - Google library implementation for convenience
from oauth2client import client
import httplib2  # used in oauth2 flow

# Google API for services
from apiclient import discovery

import CONFIG

# Globals
app = flask.Flask(__name__)
app.secret_key = str(uuid.uuid4())
app.debug = CONFIG.DEBUG
app.logger.setLevel(logging.DEBUG)

SCOPES = 'https://www.googleapis.com/auth/calendar.readonly'
CLIENT_SECRET_FILE = CONFIG.GOOGLE_LICENSE_KEY  # You'll need this
APPLICATION_NAME = 'auth0-server'

# Pages (routed from URLs)

@app.route("/")
@app.route("/index")
def index():
    app.logger.debug("Entering index")
    if 'begin_date' not in flask.session:
        init_session_values()
    return render_template('index.html')

@app.route("/choose")
def choose():
    """
    Renders the index.html page after a choose request.
    """
    # We'll need authorization to list calendars
    # I wanted to put what follows into a function, but had
    # to pull it back here because the redirect has to be a
    # 'return'
    app.logger.debug("Checking credentials for Google calendar access")
    credentials = valid_credentials()

    if not credentials:
        app.logger.debug("Redirecting to authorization")
        return flask.redirect(flask.url_for('oauth2callback'))

    gcal_service = get_gcal_service(credentials)
    app.logger.debug("Returned from get_gcal_service")
    flask.session['calendars'] = list_calendars(gcal_service)

    return render_template('index.html')

@app.route("/get-busy-times")
def get_busy_times():
    """
    Renders the index.html page after a get-busy-times request.
    """
    app.logger.debug("Checking credentials for Google calendar access")
    credentials = valid_credentials()

    if not credentials:
        app.logger.debug("Redirecting to authorization")
        return flask.redirect(flask.url_for('oauth2callback'))

    gcal_service = get_gcal_service(credentials)
    app.logger.debug("Returned from get_gcal_service")
    flask.session['busy_times'] = list_busy_times(gcal_service)

    return render_template('index.html')

#  Google calendar authorization:
#      Returns us to the main /choose screen after inserting
#      the calendar_service object in the session state.  May
#      redirect to OAuth server first, and may take multiple
#      trips through the oauth2 callback function.
#
#  Protocol for use ON EACH REQUEST:
#     First, check for valid credentials
#     If we don't have valid credentials
#         Get credentials (jump to the oauth2 protocol)
#         (redirects back to /choose, this time with credentials)
#     If we do have valid credentials
#         Get the service object
#
#  The final result of successful authorization is a 'service'
#  object.  We use a 'service' object to actually retrieve data
#  from the Google services. Service objects are NOT serializable ---
#  we can't stash one in a cookie.  Instead, on each request we
#  get a fresh service object from our credentials, which are
#  serializable.
#
#  Note that after authorization we always redirect to /choose;
#  If this is unsatisfactory, we'll need a session variable to use
#  as a 'continuation' or 'return address' to use instead.

def valid_credentials():
    """
    Returns OAuth2 credentials if we have valid
    credentials in the session.  This is a 'truthy' value.
    Return None if we don't have credentials, or if they
    have expired or are otherwise invalid.  This is a 'falsy' value.
    :return: a Google OAuth2 credentials object
    """
    if 'credentials' not in flask.session:
        return None

    credentials = client.OAuth2Credentials.from_json(
        flask.session['credentials'])

    if credentials.invalid or credentials.access_token_expired:
        return None

    return credentials

def get_gcal_service(credentials):
    """
    We need a Google calendar 'service' object to obtain
    list of calendars, busy times, etc.  This requires
    authorization. If authorization is already in effect,
    we'll just return with the authorization. Otherwise,
    control flow will be interrupted by authorization, and we'll
    end up redirected back to /choose *without a service object*.
    Then the second call will succeed without additional authorization.
    :param credentials: a Google OAuth2 credentials object
    """
    app.logger.debug("Entering get_gcal_service")
    http_auth = credentials.authorize(httplib2.Http())
    service = discovery.build('calendar', 'v3', http=http_auth)
    app.logger.debug("Returning service")

    return service

@app.route('/oauth2callback')
def oauth2callback():
    """
    The 'flow' has this one place to call back to.  We'll enter here
    more than once as steps in the flow are completed, and need to keep
    track of how far we've gotten. The first time we'll do the first
    step, the second time we'll skip the first step and do the second,
    and so on.
    """
    app.logger.debug("Entering oauth2callback")
    flow = client.flow_from_clientsecrets(
        CLIENT_SECRET_FILE,
        scope=SCOPES,
        redirect_uri=flask.url_for('oauth2callback', _external=True))
    # Note we are *not* redirecting above.  We are noting *where*
    # we will redirect to, which is this function.

    # The *second* time we enter here, it's a callback
    # with 'code' set in the URL parameter.  If we don't
    # see that, it must be the first time through, so we
    # need to do step 1.
    app.logger.debug("Got flow")
    if 'code' not in flask.request.args:
        app.logger.debug("Code not in flask.request.args")
        auth_uri = flow.step1_get_authorize_url()
        return flask.redirect(auth_uri)
        # This will redirect back here, but the second time through
        # we'll have the 'code' parameter set
    else:
        # It's the second time through ... we can tell because
        # we got the 'code' argument in the URL.
        app.logger.debug("Code was in flask.request.args")
        auth_code = flask.request.args.get('code')
        credentials = flow.step2_exchange(auth_code)
        flask.session['credentials'] = credentials.to_json()
        # Now I can build the service and execute the query,
        # but for the moment I'll just log it and go back to
        # the main screen
        app.logger.debug("Got credentials")

        return flask.redirect(flask.url_for('choose'))

#  Option setting:  Buttons or forms that add some
#     information into session state.  Don't do the
#     computation here; use of the information might
#     depend on what other information we have.
#   Setting an option sends us back to the main display
#      page, where we may put the new information to use.

@app.route('/set-range', methods=['POST'])
def set_range():
    """
    User chose a date range with the bootstrap daterange widget.
    :return: redirects to the choose page
    """
    app.logger.debug("Entering setrange")
    # flask.flash("Setrange gave us '{}'".format(request.form.get('daterange')))

    daterange = request.form.get('daterange')
    flask.session['daterange'] = daterange

    daterange_parts = daterange.split()
    flask.session['begin_date'] = interpret_date(daterange_parts[0])
    flask.session['end_date'] = interpret_date(daterange_parts[2])

    app.logger.debug("Setrange parsed {} - {}  dates as {} - {}".format(
        daterange_parts[0], daterange_parts[1],
        flask.session['begin_date'], flask.session['end_date']))

    return flask.redirect(flask.url_for("choose"))

@app.route('/set-checked-calendars', methods=['POST'])
def set_checked_calendars():
    """
    User chose one or more calendars from the list.
    :return: redirects to the get-busy-times page
    """
    app.logger.debug("Entering get_busy_times")
    calendars = request.form.getlist('calendar')

    flask.session['checked_calendars'] = calendars

    return flask.redirect(flask.url_for("get_busy_times"))

@app.route('/clear-session', methods=['POST'])
def clear_session():
    flask.session.clear()
    return flask.redirect(flask.url_for('index'))

#  Initialize session variables

def init_session_values():
    """
    Start with some reasonable defaults for date and time ranges.
    Note this must be run in app context ... can't call from main.
    """
    # Default date span = tomorrow to 1 week from now
    now = arrow.now('local')
    tomorrow = now.replace(days=+1)
    nextweek = now.replace(days=+7)

    flask.session["begin_date"] = tomorrow.floor('day').isoformat()
    flask.session["end_date"] = nextweek.ceil('day').isoformat()
    flask.session["daterange"] = "{} - {}".format(
        tomorrow.format("MM/DD/YYYY"),
        nextweek.format("MM/DD/YYYY"))

    # Default time span each day, 9 to 5
    flask.session["begin_time"] = interpret_time("9am")
    flask.session["end_time"] = interpret_time("5pm")

def interpret_time(text):
    """
    Read time in a human-compatible format and
    interpret as ISO format with local timezone.
    May throw exception if time can't be interpreted. In that
    case it will also flash a message explaining accepted formats.
    :param text: a human-compatible time
    :return: an arrow date time object
    """
    app.logger.debug("Decoding time '{}'".format(text))
    time_formats = ["ha", "h:mma", "h:mm a", "H:mm"]

    try:
        as_arrow = arrow.get(text, time_formats).replace(tzinfo=tz.tzlocal())
        app.logger.debug("Succeeded interpreting time")
    except:
        app.logger.debug("Failed to interpret time")
        flask.flash("Time '{}' didn't match accepted formats 13:30 or 1:30pm"
                    .format(text))
        raise

    return as_arrow.isoformat()

def interpret_date(text):
    """
    Convert text of date to ISO format used internally,
    with the local time zone.
    :param text: an ISO date
    :return: an arrow date time object
    """
    try:
        as_arrow = arrow.get(text, "MM/DD/YYYY").replace(
            tzinfo=tz.tzlocal())
    except:
        flask.flash("Date '{}' didn't fit expected format MM/DD/YYYY")
        raise

    return as_arrow.isoformat()

def next_day(iso_text):
    """
    ISO date + 1 day (used in query to Google calendar)
    :param iso_text: an ISO date
    :return: an arrow date time object
    """
    as_arrow = arrow.get(iso_text)

    return as_arrow.replace(days=+1).isoformat()

#  Functions (NOT pages) that return some information

def list_busy_times(service):
    """
    Lists the busy times from the selected calendar in ascending order.
    :param service: a google 'service' object
    :return: a sorted list of busy times for the selected calendar(s)
    """
    app.logger.debug('Entering list_busy_times')
    result_dict = {}
    result = []
    begin_date = arrow.get(flask.session["begin_date"])
    end_date = arrow.get(flask.session['end_date'])

    app.logger.debug('Events:')
    for cal_id in flask.session['checked_calendars']:
        events = service.events().list(calendarId=cal_id).execute()
        for event in events['items']:
            try:
                transparency = event['transparency']
                available = True
            except:
                available = False
            try:
                event_start = arrow.get(event['start']['dateTime'])
                event_end = arrow.get(event['end']['dateTime'])
            except:
                event_start = arrow.get(event['start']['date'])
                event_end = arrow.get(event['end']['date'])

            if (event_start >= begin_date and event_end <= end_date and
                    not available):
                result_dict[event_start.isoformat()] = event

    for item in sorted(result_dict):
        result.append(result_dict[item])

    return result

def list_calendars(service):
    """
    Given a google 'service' object, return a list of
    calendars.  Each calendar is represented by a dict, so that
    it can be stored in the session object and converted to
    json for cookies. The returned list is sorted to have
    the primary calendar first, and selected (that is, displayed in
    Google Calendars web app) calendars before unselected calendars.
    :param service: a google 'service' object
    :return: a sorted list of calendars
    """
    app.logger.debug("Entering list_calendars")
    calendar_list = service.calendarList().list().execute()
    result = []

    for cal in calendar_list["items"]:
        kind = cal["kind"]
        cal_id = cal["id"]

        if "description" in cal:
            desc = cal["description"]
        else:
            desc = "(no description)"
        summary = cal["summary"]

        # Optional binary attributes with False as default
        selected = ("selected" in cal) and cal["selected"]
        primary = ("primary" in cal) and cal["primary"]

        result.append(
            {"kind": kind,
             "id": cal_id,
             "summary": summary,
             "selected": selected,
             "primary": primary
             })

    return sorted(result, key=cal_sort_key)

def cal_sort_key(cal):
    """
    Sort key for the list of calendars:  primary calendar first,
    then other selected calendars, then unselected calendars.
    (" " sorts before "X", and tuples are compared piecewise)
    :param cal: a calendars
    :return: the sorted calendar
    """
    if cal["selected"]:
        selected_key = " "
    else:
        selected_key = "X"
    if cal["primary"]:
        primary_key = " "
    else:
        primary_key = "X"

    return primary_key, selected_key, cal["summary"]

# Functions used within the templates

@app.template_filter('fmtdate')
def format_arrow_date(date):
    try:
        normal = arrow.get(date)
        return normal.format("ddd MM/DD/YYYY")
    except:
        return "(bad date)"

@app.template_filter('fmttime')
def format_arrow_time(time):
    try:
        normal = arrow.get(time)
        return normal.format("HH:mm")
    except:
        return "(bad time)"

@app.template_filter('fmtdatetime')
def format_arrow_date_time(date_time):
    try:
        normal = arrow.get(date_time)
        return normal.format("HH:mm, dddd, MM/DD/YYYY")
    except:
        return "(bad date)"

def main():
    # App is created above so that it will
    # exist whether this is 'main' or not
    # (e.g., if we are running in a CGI script)
    import uuid

    app.secret_key = str(uuid.uuid4())
    app.debug = CONFIG.DEBUG
    app.logger.setLevel(logging.DEBUG)
    # We run on localhost only if debugging,
    # otherwise accessible to world
    if CONFIG.DEBUG:
        # Reachable only from the same computer
        app.run(port=CONFIG.PORT)
    else:
        # Reachable from anywhere
        app.run(port=CONFIG.PORT, host="0.0.0.0")

if __name__ == "__main__":
    # main()
    import uuid

    app.secret_key = str(uuid.uuid4())
    app.debug = CONFIG.DEBUG
    app.logger.setLevel(logging.DEBUG)
    app.run(port=CONFIG.PORT)
<commit_msg>serve on 0.0.0.0 on ix<commit_after>import flask
from flask import render_template
from flask import request
from flask import url_for
import json
import logging
import uuid

# Date handling
import arrow  # Replacement for datetime, based on moment.js
import datetime  # But we still need time
from dateutil import tz  # For interpreting local times

# OAuth2  - Google library implementation for convenience
from oauth2client import client
import httplib2  # used in oauth2 flow

# Google API for services
from apiclient import discovery

import CONFIG

# Globals
app = flask.Flask(__name__)
app.secret_key = str(uuid.uuid4())
app.debug = CONFIG.DEBUG
app.logger.setLevel(logging.DEBUG)

SCOPES = 'https://www.googleapis.com/auth/calendar.readonly'
CLIENT_SECRET_FILE = CONFIG.GOOGLE_LICENSE_KEY  # You'll need this
APPLICATION_NAME = 'auth0-server'

# Pages (routed from URLs)

@app.route("/")
@app.route("/index")
def index():
    app.logger.debug("Entering index")
    if 'begin_date' not in flask.session:
        init_session_values()
    return render_template('index.html')

@app.route("/choose")
def choose():
    """
    Renders the index.html page after a choose request.
    """
    # We'll need authorization to list calendars
    # I wanted to put what follows into a function, but had
    # to pull it back here because the redirect has to be a
    # 'return'
    app.logger.debug("Checking credentials for Google calendar access")
    credentials = valid_credentials()

    if not credentials:
        app.logger.debug("Redirecting to authorization")
        return flask.redirect(flask.url_for('oauth2callback'))

    gcal_service = get_gcal_service(credentials)
    app.logger.debug("Returned from get_gcal_service")
    flask.session['calendars'] = list_calendars(gcal_service)

    return render_template('index.html')

@app.route("/get-busy-times")
def get_busy_times():
    """
    Renders the index.html page after a get-busy-times request.
    """
    app.logger.debug("Checking credentials for Google calendar access")
    credentials = valid_credentials()

    if not credentials:
        app.logger.debug("Redirecting to authorization")
        return flask.redirect(flask.url_for('oauth2callback'))

    gcal_service = get_gcal_service(credentials)
    app.logger.debug("Returned from get_gcal_service")
    flask.session['busy_times'] = list_busy_times(gcal_service)

    return render_template('index.html')

#  Google calendar authorization:
#      Returns us to the main /choose screen after inserting
#      the calendar_service object in the session state.  May
#      redirect to OAuth server first, and may take multiple
#      trips through the oauth2 callback function.
#
#  Protocol for use ON EACH REQUEST:
#     First, check for valid credentials
#     If we don't have valid credentials
#         Get credentials (jump to the oauth2 protocol)
#         (redirects back to /choose, this time with credentials)
#     If we do have valid credentials
#         Get the service object
#
#  The final result of successful authorization is a 'service'
#  object.  We use a 'service' object to actually retrieve data
#  from the Google services. Service objects are NOT serializable ---
#  we can't stash one in a cookie.  Instead, on each request we
#  get a fresh service object from our credentials, which are
#  serializable.
#
#  Note that after authorization we always redirect to /choose;
#  If this is unsatisfactory, we'll need a session variable to use
#  as a 'continuation' or 'return address' to use instead.

def valid_credentials():
    """
    Returns OAuth2 credentials if we have valid
    credentials in the session.  This is a 'truthy' value.
    Return None if we don't have credentials, or if they
    have expired or are otherwise invalid.  This is a 'falsy' value.
    :return: a Google OAuth2 credentials object
    """
    if 'credentials' not in flask.session:
        return None

    credentials = client.OAuth2Credentials.from_json(
        flask.session['credentials'])

    if credentials.invalid or credentials.access_token_expired:
        return None

    return credentials

def get_gcal_service(credentials):
    """
    We need a Google calendar 'service' object to obtain
    list of calendars, busy times, etc.  This requires
    authorization. If authorization is already in effect,
    we'll just return with the authorization. Otherwise,
    control flow will be interrupted by authorization, and we'll
    end up redirected back to /choose *without a service object*.
    Then the second call will succeed without additional authorization.
    :param credentials: a Google OAuth2 credentials object
    """
    app.logger.debug("Entering get_gcal_service")
    http_auth = credentials.authorize(httplib2.Http())
    service = discovery.build('calendar', 'v3', http=http_auth)
    app.logger.debug("Returning service")

    return service

@app.route('/oauth2callback')
def oauth2callback():
    """
    The 'flow' has this one place to call back to.  We'll enter here
    more than once as steps in the flow are completed, and need to keep
    track of how far we've gotten. The first time we'll do the first
    step, the second time we'll skip the first step and do the second,
    and so on.
    """
    app.logger.debug("Entering oauth2callback")
    flow = client.flow_from_clientsecrets(
        CLIENT_SECRET_FILE,
        scope=SCOPES,
        redirect_uri=flask.url_for('oauth2callback', _external=True))
    # Note we are *not* redirecting above.  We are noting *where*
    # we will redirect to, which is this function.

    # The *second* time we enter here, it's a callback
    # with 'code' set in the URL parameter.  If we don't
    # see that, it must be the first time through, so we
    # need to do step 1.
    app.logger.debug("Got flow")
    if 'code' not in flask.request.args:
        app.logger.debug("Code not in flask.request.args")
        auth_uri = flow.step1_get_authorize_url()
        return flask.redirect(auth_uri)
        # This will redirect back here, but the second time through
        # we'll have the 'code' parameter set
    else:
        # It's the second time through ... we can tell because
        # we got the 'code' argument in the URL.
        app.logger.debug("Code was in flask.request.args")
        auth_code = flask.request.args.get('code')
        credentials = flow.step2_exchange(auth_code)
        flask.session['credentials'] = credentials.to_json()
        # Now I can build the service and execute the query,
        # but for the moment I'll just log it and go back to
        # the main screen
        app.logger.debug("Got credentials")

        return flask.redirect(flask.url_for('choose'))

#  Option setting:  Buttons or forms that add some
#     information into session state.  Don't do the
#     computation here; use of the information might
#     depend on what other information we have.
#   Setting an option sends us back to the main display
#      page, where we may put the new information to use.

@app.route('/set-range', methods=['POST'])
def set_range():
    """
    User chose a date range with the bootstrap daterange widget.
    :return: redirects to the choose page
    """
    app.logger.debug("Entering setrange")
    # flask.flash("Setrange gave us '{}'".format(request.form.get('daterange')))

    daterange = request.form.get('daterange')
    flask.session['daterange'] = daterange

    daterange_parts = daterange.split()
    flask.session['begin_date'] = interpret_date(daterange_parts[0])
    flask.session['end_date'] = interpret_date(daterange_parts[2])

    app.logger.debug("Setrange parsed {} - {}  dates as {} - {}".format(
        daterange_parts[0], daterange_parts[1],
        flask.session['begin_date'], flask.session['end_date']))

    return flask.redirect(flask.url_for("choose"))

@app.route('/set-checked-calendars', methods=['POST'])
def set_checked_calendars():
    """
    User chose one or more calendars from the list.
    :return: redirects to the get-busy-times page
    """
    app.logger.debug("Entering get_busy_times")
    calendars = request.form.getlist('calendar')

    flask.session['checked_calendars'] = calendars

    return flask.redirect(flask.url_for("get_busy_times"))

@app.route('/clear-session', methods=['POST'])
def clear_session():
    flask.session.clear()
    return flask.redirect(flask.url_for('index'))

#  Initialize session variables

def init_session_values():
    """
    Start with some reasonable defaults for date and time ranges.
    Note this must be run in app context ... can't call from main.
    """
    # Default date span = tomorrow to 1 week from now
    now = arrow.now('local')
    tomorrow = now.replace(days=+1)
    nextweek = now.replace(days=+7)

    flask.session["begin_date"] = tomorrow.floor('day').isoformat()
    flask.session["end_date"] = nextweek.ceil('day').isoformat()
    flask.session["daterange"] = "{} - {}".format(
        tomorrow.format("MM/DD/YYYY"),
        nextweek.format("MM/DD/YYYY"))

    # Default time span each day, 9 to 5
    flask.session["begin_time"] = interpret_time("9am")
    flask.session["end_time"] = interpret_time("5pm")

def interpret_time(text):
    """
    Read time in a human-compatible format and
    interpret as ISO format with local timezone.
    May throw exception if time can't be interpreted. In that
    case it will also flash a message explaining accepted formats.
    :param text: a human-compatible time
    :return: an arrow date time object
    """
    app.logger.debug("Decoding time '{}'".format(text))
    time_formats = ["ha", "h:mma", "h:mm a", "H:mm"]

    try:
        as_arrow = arrow.get(text, time_formats).replace(tzinfo=tz.tzlocal())
        app.logger.debug("Succeeded interpreting time")
    except:
        app.logger.debug("Failed to interpret time")
        flask.flash("Time '{}' didn't match accepted formats 13:30 or 1:30pm"
                    .format(text))
        raise

    return as_arrow.isoformat()

def interpret_date(text):
    """
    Convert text of date to ISO format used internally,
    with the local time zone.
    :param text: an ISO date
    :return: an arrow date time object
    """
    try:
        as_arrow = arrow.get(text, "MM/DD/YYYY").replace(
            tzinfo=tz.tzlocal())
    except:
        flask.flash("Date '{}' didn't fit expected format MM/DD/YYYY")
        raise

    return as_arrow.isoformat()

def next_day(iso_text):
    """
    ISO date + 1 day (used in query to Google calendar)
    :param iso_text: an ISO date
    :return: an arrow date time object
    """
    as_arrow = arrow.get(iso_text)

    return as_arrow.replace(days=+1).isoformat()

#  Functions (NOT pages) that return some information

def list_busy_times(service):
    """
    Lists the busy times from the selected calendar in ascending order.
    :param service: a google 'service' object
    :return: a sorted list of busy times for the selected calendar(s)
    """
    app.logger.debug('Entering list_busy_times')
    result_dict = {}
    result = []
    begin_date = arrow.get(flask.session["begin_date"])
    end_date = arrow.get(flask.session['end_date'])

    app.logger.debug('Events:')
    for cal_id in flask.session['checked_calendars']:
        events = service.events().list(calendarId=cal_id).execute()
        for event in events['items']:
            try:
                transparency = event['transparency']
                available = True
            except:
                available = False
            try:
                event_start = arrow.get(event['start']['dateTime'])
                event_end = arrow.get(event['end']['dateTime'])
            except:
                event_start = arrow.get(event['start']['date'])
                event_end = arrow.get(event['end']['date'])

            if (event_start >= begin_date and event_end <= end_date and
                    not available):
                result_dict[event_start.isoformat()] = event

    for item in sorted(result_dict):
        result.append(result_dict[item])

    return result

def list_calendars(service):
    """
    Given a google 'service' object, return a list of
    calendars.  Each calendar is represented by a dict, so that
    it can be stored in the session object and converted to
    json for cookies. The returned list is sorted to have
    the primary calendar first, and selected (that is, displayed in
    Google Calendars web app) calendars before unselected calendars.
    :param service: a google 'service' object
    :return: a sorted list of calendars
    """
    app.logger.debug("Entering list_calendars")
    calendar_list = service.calendarList().list().execute()
    result = []

    for cal in calendar_list["items"]:
        kind = cal["kind"]
        cal_id = cal["id"]

        if "description" in cal:
            desc = cal["description"]
        else:
            desc = "(no description)"
        summary = cal["summary"]

        # Optional binary attributes with False as default
        selected = ("selected" in cal) and cal["selected"]
        primary = ("primary" in cal) and cal["primary"]

        result.append(
            {"kind": kind,
             "id": cal_id,
             "summary": summary,
             "selected": selected,
             "primary": primary
             })

    return sorted(result, key=cal_sort_key)

def cal_sort_key(cal):
    """
    Sort key for the list of calendars:  primary calendar first,
    then other selected calendars, then unselected calendars.
    (" " sorts before "X", and tuples are compared piecewise)
    :param cal: a calendars
    :return: the sorted calendar
    """
    if cal["selected"]:
        selected_key = " "
    else:
        selected_key = "X"
    if cal["primary"]:
        primary_key = " "
    else:
        primary_key = "X"

    return primary_key, selected_key, cal["summary"]

# Functions used within the templates

@app.template_filter('fmtdate')
def format_arrow_date(date):
    try:
        normal = arrow.get(date)
        return normal.format("ddd MM/DD/YYYY")
    except:
        return "(bad date)"

@app.template_filter('fmttime')
def format_arrow_time(time):
    try:
        normal = arrow.get(time)
        return normal.format("HH:mm")
    except:
        return "(bad time)"

@app.template_filter('fmtdatetime')
def format_arrow_date_time(date_time):
    try:
        normal = arrow.get(date_time)
        return normal.format("HH:mm, dddd, MM/DD/YYYY")
    except:
        return "(bad date)"

def main():
    # App is created above so that it will
    # exist whether this is 'main' or not
    # (e.g., if we are running in a CGI script)
    import uuid

    app.secret_key = str(uuid.uuid4())
    app.debug = CONFIG.DEBUG
    app.logger.setLevel(logging.DEBUG)
    # We run on localhost only if debugging,
    # otherwise accessible to world
    if CONFIG.DEBUG:
        # Reachable only from the same computer
        app.run(port=CONFIG.PORT)
    else:
        # Reachable from anywhere
        app.run(port=CONFIG.PORT, host="0.0.0.0")

if __name__ == "__main__":
    # main()
    import uuid

    app.secret_key = str(uuid.uuid4())
    app.debug = CONFIG.DEBUG
    app.logger.setLevel(logging.DEBUG)
    if CONFIG.DEBUG:
        app.run(port=CONFIG.PORT)
    else:
        app.run(port=CONFIG.PORT, host="0.0.0.0")

<|endoftext|>


<commit_before>#!/bin/python3
from curses import wrapper
import curses
import os

class Window():
    def __init__(self, x, y, w, h):
        self.win = curses.newwin(h,w,y,x)
        self.win.immedok(True)

class CWindow():
    def __init__(self):
        self.window = Window(1, curses.LINES - 4, curses.COLS - 2, 3)
        self.win = self.window.win
        self.win.border()
        self.text = ""

    def set_text(self, text):
        self.win.clear()
        self.win.border()
        self.win.addstr(1,1, text)
        self.text = text

    def add_text(self, text):
        self.text += text
        self.set_text(self.text)

    def get_command(self, scr):
        bak_text = self.text
        self.set_text(":")
        text = ""
        while True:
            c = scr.getch()
            if c == 27:
                n = scr.getch()
                if n == curses.ERR:
                    self.set_text(bak_text)
                    return None
                else:
                    pass
            elif c == curses.KEY_ENTER or c == 10 or c == 13:
                return text
            elif c in range(0, 128):
                text += chr(c)
                self.add_text(chr(c))

class NormalMode():
    def handle(self, app):
        while True:
            c = app.screen.getch()
            if c == ord('q'):
                return
            elif c == ord(':'):
                app.command.get_command(self.screen)
            elif c == 27:
                n = app.screen.getch()
                if n == curses.ERR:
                    #ESC
                    app.command.set_text('esc')
                else:
                    #ALT + n
                    app.command.set_text(chr(n))
            elif c == ord('p'):
                app.command.add_text('woo')

class App():
    def __init__(self):
        pass

    def initialize(self):
        os.environ.setdefault('ESCDELAY', '25')
        self.set_mode(NormalMode())

    def startscr(self, screen):
        self.screen = screen
        self.screen.nodelay(True)
        self.screen.clear()
        self.screen.immedok(True)
        self.screen.border()
        self.command = CWindow()
        self.loop()

    def set_mode(self, mode):
        self.mode = mode

    def loop(self):
        self.mode.handle(self)

if __name__ == "__main__":
    app = App()
    app.initialize()
    wrapper(app.startscr)

<commit_msg>Added commands, Command Mode<commit_after>#!/bin/python3
from curses import wrapper
import curses
import os

class Window():
    def __init__(self, x, y, w, h):
        self.win = curses.newwin(h,w,y,x)
        self.win.immedok(True)

class CWindow():
    def __init__(self):
        self.window = Window(1, curses.LINES - 4, curses.COLS - 2, 3)
        self.win = self.window.win
        self.win.border()
        self.text = ""

    def set_text(self, text):
        self.win.clear()
        self.win.border()
        self.win.addstr(1,1, text)
        self.text = text

    def add_text(self, text):
        self.text += text
        self.set_text(self.text)

class CommandMode():
    def handle(self, app):
        cwindow = app.cwin
        bak_text = cwindow.text
        text = ""
        while True:
            c = app.screen.getch()
            if c == 27:
                n = app.screen.getch()
                if n == curses.ERR:
                    #ESC
                    cwindow.set_text(bak_text)
                    app.set_mode('normal')
                    return
            elif c == curses.KEY_ENTER or c == 10 or c == 13:
                app.set_mode('normal')
                app.command(text)
                return
            elif c in range(0,128):
                text += chr(c)
                cwindow.add_text(chr(c))

class NormalMode():
    def handle(self, app):
        while True:
            c = app.screen.getch()
            if c == ord('q'):
                app.command('quit')
                return
            elif c == ord(':'):
                app.set_mode('command')
                return
            elif c == 27:
                n = app.screen.getch()
                if n == curses.ERR:
                    #ESC
                    app.cwin.set_text('esc')
                else:
                    #ALT + n
                    app.cwin.set_text(chr(n))
            elif c == ord('p'):
                app.command('write', text = 'Yolo')

class App():
    def __init__(self):
        self.run = True
        self.modes = {}
        self.commands = {}
        pass

    def initialize(self):
        os.environ.setdefault('ESCDELAY', '25')
        self.add_mode(NormalMode(), 'normal')
        self.add_mode(CommandMode(), 'command')
        self.set_mode('normal')
        def f(app, **kwargs):
            app.run = False
        self.add_command('quit',f)
        def f(app, **kwargs):
            if 'text' not in kwargs:
                return
            app.cwin.set_text( kwargs.get('text'))
        self.add_command('write', f)

    def startscr(self, screen):
        self.screen = screen
        self.screen.nodelay(True)
        self.screen.clear()
        self.screen.immedok(True)
        self.screen.border()
        self.cwin = CWindow()
        self.loop()

    def add_command(self, command, func):
        self.commands.update({command: func})

    def command(self, command, **kwargs):
        self.commands.get(command)(self,**kwargs)

    def add_mode(self, mode, tag):
        self.modes.update({tag: mode})

    def set_mode(self, mode):
        self.mode = self.modes.get(mode)

    def loop(self):
        while self.run:
            self.mode.handle(self)

if __name__ == "__main__":
    app = App()
    app.initialize()
    wrapper(app.startscr)

<|endoftext|>


<commit_before>import json
import urllib2
import boto3
import botocore
from time import sleep
import datetime
import argparse
import logging
from operator import itemgetter

def main():
    BUCKET = 'epic-archive-mirror'
    API = 'http://epic.gsfc.nasa.gov/api'
    ARCHIVE = 'http://epic.gsfc.nasa.gov/epic-archive'
    RETRIES = 5
    DAYS_TRACK_CHANGES = 14

    def get_available_dates():
        data = urllib2.urlopen(
            '{endpoint}/images.php?available_dates'.format(
                endpoint=API))
        if data.code == 200:
            dates = json.loads(data.read())
            dates.reverse()
            return dates
        logging.info('Failed getting available dates')
        return None

    def get_list_by_date(date):
        data = urllib2.urlopen(
            '{endpoint}/images.php?date={date}'.format(
                endpoint=API, date=date))
        if data.code == 200:
            return json.loads(data.read())
        logging.info('Failed getting list by date for date: {}'.format(date))
        return None

    def get_mirror_list_by_date(date):
        client = boto3.client('s3')
        list_path = 'images/list/images_{date}.json'.format(date=date)
        mirror_list = ''
        try:
            mirror_list = client.get_object(
                Bucket=BUCKET,
                Key=list_path)['Body'].read()
        except botocore.exceptions.ClientError as e:
            logging.info(
                'Failed getting list by date from mirror for date: {}'.format(date))
            return None
        return json.loads(mirror_list)

    def get_images_names_from_list(image_list):
        images = []
        for l in image_list:
            images.append(l['image'])
        return images

    def get_image_data(image_path):
        data = urllib2.urlopen(image_path)
        for i in range(RETRIES):
            if data.code == 200:
                return data
            sleep(1)
        logging.info(
            'Failed getting image data for image path: {}'.format(image_path))
        return None

    def too_old_to_sync(date):
        now = datetime.datetime.today()
        test_date = datetime.datetime.strptime(date, '%Y-%m-%d')
        delta = now - test_date

        if delta.days > DAYS_TRACK_CHANGES:
            logging.info('Date {} too old'.format(date))
            return True

        return False

    def upload_file(data, key):
        client = boto3.client('s3')

        if isinstance(data, basestring):
            body = data
            content_type = 'text/html; charset=UTF-8'
        else:
            body = data.read()
            content_type = data.info()['Content-type']

        if not args.dryrun:
            client.put_object(
                Body=body,
                Bucket=BUCKET,
                Key=key,
                ContentType=content_type)

    def download_images_in_list(image_list):
        images = get_images_names_from_list(image_list)
        all_images_downloaded = True
        for image in images:
            logging.info('image: {}'.format(image))
            thumb = '{endpoint}/thumbs/{image}.jpg'.format(
                endpoint=ARCHIVE, image=image)
            jpg = '{endpoint}/jpg/{image}.jpg'.format(
                endpoint=ARCHIVE, image=image)
            png = '{endpoint}/png/{image}.png'.format(
                endpoint=ARCHIVE, image=image)
            thumb_key = 'images/thumbs/{image}.jpg'.format(image=image)
            logging.info('thumb key: {}'.format(thumb_key))
            jpg_key = 'images/jpg/{image}.jpg'.format(image=image)
            logging.info('jpg key: {}'.format(jpg_key))
            png_key = 'images/png/{image}.png'.format(image=image)
            logging.info('png key: {}'.format(png_key))
            thumb_data = get_image_data(thumb)
            jpg_data = get_image_data(jpg)
            png_data = get_image_data(png)
            if thumb_data is None or jpg_data is None or png_data is None:
                logging.info('Failed downloading one of the images')
                all_images_downloaded = False
                break
            upload_file(thumb_data, thumb_key)
            upload_file(jpg_data, jpg_key)
            upload_file(png_data, png_key)
        return all_images_downloaded

    parser = argparse.ArgumentParser()
    parser.add_argument(
        '--full',
        help='Sync all dates',
        action='store_true')
    parser.add_argument(
        '--dryrun',
        help='Not writing to mirror',
        action='store_true')
    parser.add_argument(
        '--verbose',
        help='Print debug messages',
        action='store_true')
    args = parser.parse_args()

    if args.verbose:
        logging.basicConfig(level=logging.INFO)

    dates = get_available_dates()
    upload_file(json.dumps(dates), 'images/available_dates.json')

    first_iteration = True
    for date in dates:
        logging.info('date: {}'.format(date))
        if not args.full and too_old_to_sync(date):
            break

        daily_image_list_from_archive = get_mirror_list_by_date(date)
        daily_image_list_from_api = get_list_by_date(date)

        list_of_images_to_download = []
        daily_image_list_to_archive = daily_image_list_from_api
        if daily_image_list_from_archive is None:
            logging.info('New list')
            list_of_images_to_download = daily_image_list_from_api
        else:
            logging.info('Existing list')
            archive_names = set(
                get_images_names_from_list(daily_image_list_from_archive))
            api_names = set(
                get_images_names_from_list(daily_image_list_from_api))
            new_images = api_names - archive_names
            for new_image in new_images:
                new_image_key = next(
                    (item for item in daily_image_list_from_api if item['image'] == new_image), None)
                new_image_key['new'] = True
                list_of_images_to_download.append(new_image_key)
            daily_image_list_to_archive = daily_image_list_from_archive + \
                list_of_images_to_download

        if len(list_of_images_to_download) > 0 and download_images_in_list(
                list_of_images_to_download):
            logging.info('New images')
            list_path = 'images/list/images_{date}.json'.format(date=date)
            list_content = sorted(
                daily_image_list_to_archive,
                key=itemgetter('date'))
            upload_file(json.dumps(list_content), list_path)
            if first_iteration:
                upload_file(
                    json.dumps(list_content), 'images/images_latest.json')

        first_iteration = False

if __name__ == '__main__':
    main()
<commit_msg>Invalidate files in cloudfront.<commit_after>import json
import urllib2
import boto3
import botocore
from time import sleep, time
import datetime
import argparse
import logging
from operator import itemgetter

def main():
    BUCKET = 'epic-archive-mirror'
    DISTRIBUTION_ID = 'E2NGB7E5BXXA9J'
    API = 'http://epic.gsfc.nasa.gov/api'
    ARCHIVE = 'http://epic.gsfc.nasa.gov/epic-archive'
    AVAILABLE_DATES_PATH_ON_MIRROR = 'images/available_dates.json'
    LATEST_IMAGES_PATH_ON_MIRROR = 'images/images_latest.json'
    RETRIES = 5
    DAYS_TRACK_CHANGES = 14

    def invalidate_files(files):
        client = boto3.client('cloudfront')
        response = client.create_invalidation(
            DistributionId=DISTRIBUTION_ID,
            InvalidationBatch={
                'Paths': {
                    'Quantity': len(files),
                    'Items': files
                },
                'CallerReference': str(int(time()))
            }
        )
        invalidation_id = response['Invalidation']['Id']
        logging.info(
            'Created invalidation for files {files} with ID {id}'.format(
                files=files, id=invalidation_id))

    def file_exists(file):
        client = boto3.client('s3')
        try:
            client.head_object(
                Bucket=BUCKET,
                Key=file)
        except botocore.exceptions.ClientError as e:
            error_code = int(e.response['Error']['Code'])
            if error_code == 404:
                return False
        return True

    def get_available_dates():
        data = urllib2.urlopen(
            '{endpoint}/images.php?available_dates'.format(
                endpoint=API))
        if data.code == 200:
            dates = json.loads(data.read())
            dates.reverse()
            return dates
        logging.info('Failed getting available dates')
        return None

    def get_list_by_date(date):
        data = urllib2.urlopen(
            '{endpoint}/images.php?date={date}'.format(
                endpoint=API, date=date))
        if data.code == 200:
            return json.loads(data.read())
        logging.info('Failed getting list by date for date: {}'.format(date))
        return None

    def get_json_file_from_mirror(list_path):
        client = boto3.client('s3')
        try:
            data = client.get_object(
                Bucket=BUCKET,
                Key=list_path)['Body'].read()
        except botocore.exceptions.ClientError as e:
            logging.info(
                'Failed getting json file {} from mirror'.format(file))
            return None
        return json.loads(data)

    def get_mirror_list_by_date(date):
        path = 'images/list/images_{date}.json'.format(date=date)
        return get_json_file_from_mirror(path)

    def get_images_names_from_list(image_list):
        images = []
        for l in image_list:
            images.append(l['image'])
        return images

    def get_image_data(image_path):
        data = urllib2.urlopen(image_path)
        for i in range(RETRIES):
            if data.code == 200:
                return data
            sleep(1)
        logging.info(
            'Failed getting image data for image path: {}'.format(image_path))
        return None

    def too_old_to_sync(date):
        now = datetime.datetime.today()
        test_date = datetime.datetime.strptime(date, '%Y-%m-%d')
        delta = now - test_date

        if delta.days > DAYS_TRACK_CHANGES:
            logging.info('Date {} too old'.format(date))
            return True

        return False

    def upload_file(data, key):
        client = boto3.client('s3')

        if isinstance(data, basestring):
            body = data
            content_type = 'text/html; charset=UTF-8'
        else:
            body = data.read()
            content_type = data.info()['Content-type']

        if not args.dryrun:
            client.put_object(
                Body=body,
                Bucket=BUCKET,
                Key=key,
                ContentType=content_type)

    def download_images_in_list(image_list):
        images = get_images_names_from_list(image_list)
        all_images_downloaded = True
        for image in images:
            logging.info('image: {}'.format(image))
            thumb = '{endpoint}/thumbs/{image}.jpg'.format(
                endpoint=ARCHIVE, image=image)
            jpg = '{endpoint}/jpg/{image}.jpg'.format(
                endpoint=ARCHIVE, image=image)
            png = '{endpoint}/png/{image}.png'.format(
                endpoint=ARCHIVE, image=image)
            thumb_key = 'images/thumbs/{image}.jpg'.format(image=image)
            logging.info('thumb key: {}'.format(thumb_key))
            jpg_key = 'images/jpg/{image}.jpg'.format(image=image)
            logging.info('jpg key: {}'.format(jpg_key))
            png_key = 'images/png/{image}.png'.format(image=image)
            logging.info('png key: {}'.format(png_key))
            thumb_data = get_image_data(thumb)
            jpg_data = get_image_data(jpg)
            png_data = get_image_data(png)
            if thumb_data is None or jpg_data is None or png_data is None:
                logging.info('Failed downloading one of the images')
                all_images_downloaded = False
                break
            upload_file(thumb_data, thumb_key)
            upload_file(jpg_data, jpg_key)
            upload_file(png_data, png_key)
        return all_images_downloaded

    parser = argparse.ArgumentParser()
    parser.add_argument(
        '--full',
        help='Sync all dates',
        action='store_true')
    parser.add_argument(
        '--dryrun',
        help='Not writing to mirror',
        action='store_true')
    parser.add_argument(
        '--verbose',
        help='Print debug messages',
        action='store_true')
    args = parser.parse_args()

    if args.verbose:
        logging.basicConfig(level=logging.INFO)

    files_to_invalidate = []

    dates = get_available_dates()
    dates_on_mirror = get_json_file_from_mirror(AVAILABLE_DATES_PATH_ON_MIRROR)
    if dates_on_mirror != dates:
        upload_file(json.dumps(dates), AVAILABLE_DATES_PATH_ON_MIRROR)
        files_to_invalidate.append('/' + AVAILABLE_DATES_PATH_ON_MIRROR)

    first_iteration = True
    for date in dates:
        logging.info('date: {}'.format(date))
        if not args.full and too_old_to_sync(date):
            break

        daily_image_list_from_archive = get_mirror_list_by_date(date)
        daily_image_list_from_api = get_list_by_date(date)

        list_of_images_to_download = []
        daily_image_list_to_archive = daily_image_list_from_api
        if daily_image_list_from_archive is None:
            logging.info('New list')
            list_of_images_to_download = daily_image_list_from_api
        else:
            logging.info('Existing list')
            archive_names = set(
                get_images_names_from_list(daily_image_list_from_archive))
            api_names = set(
                get_images_names_from_list(daily_image_list_from_api))
            new_images = api_names - archive_names
            for new_image in new_images:
                new_image_key = next(
                    (item for item in daily_image_list_from_api if item['image'] == new_image), None)
                new_image_key['new'] = True
                list_of_images_to_download.append(new_image_key)
            daily_image_list_to_archive = daily_image_list_from_archive + \
                list_of_images_to_download

        if len(list_of_images_to_download) > 0 and download_images_in_list(
                list_of_images_to_download):
            logging.info('New images')
            list_path = 'images/list/images_{date}.json'.format(date=date)
            list_content = sorted(
                daily_image_list_to_archive,
                key=itemgetter('date'))
            upload_file(json.dumps(list_content), list_path)
            files_to_invalidate.append('/' + list_path)
            if first_iteration:
                upload_file(
                    json.dumps(list_content), LATEST_IMAGES_PATH_ON_MIRROR)
                files_to_invalidate.append('/' + LATEST_IMAGES_PATH_ON_MIRROR)

        first_iteration = False

    if len(files_to_invalidate) > 0:
        invalidate_files(files_to_invalidate)

if __name__ == '__main__':
    main()
<|endoftext|>


<commit_before>from rl.session import game_specs, run

if __name__ == '__main__':
    # print(list(game_specs.keys()))
    # ['dummy', 'q_table', 'lunar_double_dqn',
    #     'mountain_double_dqn', 'lunar_dqn', 'double_dqn', 'dqn']
    run('dqn', run_param_selection=False, times=1)
    # run('lunar_dqn')
<commit_msg>set default main to run lunar dqn<commit_after>from rl.session import game_specs, run

if __name__ == '__main__':
    # print(list(game_specs.keys()))
    # ['dummy', 'q_table', 'lunar_double_dqn',
    #     'mountain_double_dqn', 'lunar_dqn', 'double_dqn', 'dqn']
    # run('dqn', run_param_selection=False, times=1)
    run('lunar_dqn')
<|endoftext|>


<commit_before># coding: utf-8
import wx
import time
import requests
import psutil
import re
import subprocess
import sys

# detect automatical controller
detect_controller = psutil.sensors_fans()
for control in detect_controller:
    Controller = control

class Fader(wx.Frame):

    def __init__(self):
        global label_fan
        global panel
        no_sys_menu = wx.CAPTION
        wx.Frame.__init__(self, None, title='WidgetMonitor', size=(200, 330), style=no_sys_menu)
        self.amount = 200
        self.delta = 5
        #self.ToggleWindowStyle(wx.STAY_ON_TOP)
        style = wx.TRANSPARENT_WINDOW if sys.platform.lower() == 'win32' else 0
        panel = wx.Panel(self, wx.ID_ANY, style=style)
        if panel.CanSetTransparent:
            panel.SetTransparent(100)

        self.SetTransparent(self.amount)
        self.Maximize(False)
        topSizer = wx.BoxSizer(wx.VERTICAL)

        ## ------- Fader Timer -------- ##
        self.timer = wx.Timer(self)
        self.Bind(wx.EVT_TIMER, self.update, self.timer)

        self.toggleBtn = wx.Button(panel, wx.ID_ANY, "Start", size=(50,50), pos=(75,0))
        self.toggleBtn.Bind(wx.EVT_BUTTON, self.onToggle)

        self.label = wx.StaticText(panel, wx.ID_ANY, label=time.ctime(), pos=(0,50), size=(200,20), style=wx.ALIGN_CENTRE)
        self.labelIpEXT = wx.StaticText(panel, wx.ID_ANY, label="Your ip Externe : 0.0.0.0", pos=(0,75), size=(200,20), style=wx.ALIGN_CENTRE)
        self.labelping = wx.StaticText(panel, wx.ID_ANY, label="check ping...", pos=(0,90), size=(200,20), style=wx.ALIGN_CENTRE)
        self.labeltemp0 = wx.StaticText(panel, wx.ID_ANY, label="temp0 : 0°C", pos=(0,110), size=(200,20), style=wx.ALIGN_CENTRE)

        #check fan speed
        correct = 0
        label_fan = {}
        data_fans = psutil.sensors_fans()
        for i in range(0, 9):
        	try:
	            data2 = re.sub('sfan', '', str(data_fans[Controller][i]))
	            data2 = re.sub('[()]', '', str(data2))
	            data2 = data2.split(",")
	            data2[1] = data2[1].replace("current=", "")
	            if int(data2[1]) > 0:
	                correct = correct + 1
	                print('detecte label_fan' + str(i+1))
	                label_fan[str(i)] = wx.StaticText(panel, wx.ID_ANY, label="fan "+ str(i+1) +" : "+data2[1]+" RPM", pos=(0,110+correct*20), size=(200,20), style=wx.ALIGN_CENTRE)
	        except IndexError:
	        	break

        if correct > 1:
	        # check update system
	        self.labelupdate_sys = wx.StaticText(panel, wx.ID_ANY, label="checking... update", pos=(0,110+correct*30), size=(200,20), style=wx.ALIGN_CENTRE)

	        # check cpu count
	        self.labelinfo_sys = wx.StaticText(panel, wx.ID_ANY, label="Information system", pos=(0,110+correct*40), size=(200,20), style=wx.ALIGN_CENTRE)

	        self.labelcpu_sys = wx.StaticText(panel, wx.ID_ANY, label="Number core CPU " + str(psutil.cpu_count()), pos=(0,110+correct*45), size=(200,20), style=wx.ALIGN_CENTRE)
	        users = psutil.users()
	        for user in users:
	            self.labelusername_sys = wx.StaticText(panel, wx.ID_ANY, label="Username " + str(user[0]), pos=(0,110+correct*50), size=(200,20), style=wx.ALIGN_CENTRE)

	        self.labelcopyright = wx.StaticText(panel, wx.ID_ANY, label="© vBlackOut", pos=(0,110+correct*55), size=(200,20), style=wx.ALIGN_CENTRE)

        else:
	    	# check update system
	        self.labelupdate_sys = wx.StaticText(panel, wx.ID_ANY, label="checking... update", pos=(0,120+correct*30), size=(200,20), style=wx.ALIGN_CENTRE)

	        # check cpu count
	        self.labelinfo_sys = wx.StaticText(panel, wx.ID_ANY, label="Information system", pos=(0,130+correct*40), size=(200,20), style=wx.ALIGN_CENTRE)

	        self.labelcpu_sys = wx.StaticText(panel, wx.ID_ANY, label="Number core CPU " + str(psutil.cpu_count()), pos=(0,140+correct*45), size=(200,20), style=wx.ALIGN_CENTRE)
	        users = psutil.users()
	        for user in users:
	            self.labelusername_sys = wx.StaticText(panel, wx.ID_ANY, label="Username " + str(user[0]), pos=(0,150+correct*50), size=(200,20), style=wx.ALIGN_CENTRE)

	        self.labelcopyright = wx.StaticText(panel, wx.ID_ANY, label="© vBlackOut", pos=(0,160+correct*55), size=(200,20), style=wx.ALIGN_CENTRE)

        #self.timer = wx.Timer(self, wx.ID_ANY)
        #self.timer.Start(60)
        #self.Bind(wx.EVT_TIMER, self.AlphaCycle)
        self.Bind(wx.EVT_ENTER_WINDOW, self.onMouseOver)
        self.Bind(wx.EVT_LEAVE_WINDOW, self.onMouseLeave)
        ## ---------------------------- ##

    def onToggle(self, event):
        btnLabel = self.toggleBtn.GetLabel()
        if btnLabel == "Start":
            print "starting timer..."
            self.timer.Start(5000)
            self.toggleBtn.SetLabel("Stop")
        else:
            print "timer stopped!"
            self.timer.Stop()
            self.toggleBtn.SetLabel("Start")

    def update(self, event):
        try:
        # get ip
            ipEXT = requests.get("https://ip4.cuby-hebergs.com")
            ipEXT = ipEXT.text
        except:
            ipEXT = "no network"

        # get temperature
        data = psutil.sensors_temperatures()
        data_fans = psutil.sensors_fans()
        for i in range(0, 9):
            try:
                if Controller == "thinkpad":
                    data2 = re.sub('sfan', '', str(data_fans[Controller][i]))
                    data2 = re.sub('[()]', '', str(data2))
                    data2 = data2.split(",")
                    data2[1] = data2[1].replace("current=", "")

                else:
                    data2 = re.sub('sfan', '', str(data_fans[Controller][i]))
                    data2 = re.sub('[()]', '', str(data2))
                    data2 = data2.split(",")
                    data2[1] = data2[1].replace("current=", "")

	            if int(data2[1]) > 0:
	                try:
	                    label_fan[str(i)].SetLabel("fan "+ str(i+1) +" : "+data2[1]+" RPM")
	                except KeyError:
	                    continue
            except IndexError:
	        	break

        if Controller == "thinkpad":
            data2 = re.sub('shwtemp', '', str(data["acpitz"][0]))
            data2 = re.sub('[()]', '', str(data2))
            data2 = data2.split(",")
            data2[1] = data2[1].replace("current=", "")

        else:
            data2 = re.sub('shwtemp', '', str(data[Controller][0]))
            data2 = re.sub('[()]', '', str(data2))
            data2 = data2.split(",")
            data2[1] = data2[1].replace("current=", "")

        self.label.SetLabel(time.ctime())
        self.labelIpEXT.SetLabel("Your ip Externe : "+ipEXT)

        # Run the "ping" command
        command = "ping -W 1 -c 1 www.google.com"  # the shell command
        output = subprocess.check_output(command, shell=True)

        # And interpret the output
        matches = re.findall(" time=([\d.]+) ms", output)
        matches = [float(match) for match in matches]
        ms = round(sum(matches)/len(matches),1)
        self.labelping.SetLabel("your ping : "+str(ms)+" ms")

        if ms < 200.0:
            self.labelping.SetForegroundColour((127,255,0)) # set text color
        else:
            self.labelping.SetForegroundColour((255,0,0))

        self.labeltemp0.SetLabel("Temp0 : "+data2[1]+"°C")
        try:
            if float(data2[1]) >= 0:
                try:
                    if int(data2[1]) < 55:
                        self.labeltemp0.SetForegroundColour((127,255,0)) # set text color
                    if int(data2[1]) > 55:
                        self.labeltemp0.SetForegroundColour((255,150,0)) # set text color
                    if int(data2[1]) > 80:
                        self.labeltemp0.SetForegroundColour((255,0,0)) # set text color
                    if int(data2[1]) > 85:
                        self.labeltemp0.SetLabel("Temp0 : "+data2[1]+"°C Warning /!\\")
                        self.labeltemp0.SetForegroundColour((255,0,0)) # set text color
                except ValueError:
                    if float(data2[1]) < 55:
                        self.labeltemp0.SetForegroundColour((127,255,0)) # set text color
                    if float(data2[1]) > 55:
                        self.labeltemp0.SetForegroundColour((255,150,0)) # set text color
                    if float(data2[1]) > 80:
                        self.labeltemp0.SetForegroundColour((255,0,0)) # set text color
                    if float(data2[1]) > 85:
                        self.labeltemp0.SetLabel("Temp0 : "+data2[1]+"°C Warning /!\\")
                        self.labeltemp0.SetForegroundColour((255,0,0)) # set text color
            else:
                self.labeltemp0.SetLabel("Temp0 : Error sensors !")
                self.labeltemp0.SetForegroundColour((255,0,0)) # set text color

        except ValueError:
            if int(data2[1]) >= 0:
                try:
                    if int(data2[1]) < 55:
                        self.labeltemp0.SetForegroundColour((127,255,0)) # set text color
                    if int(data2[1]) > 55:
                        self.labeltemp0.SetForegroundColour((255,150,0)) # set text color
                    if int(data2[1]) > 80:
                        self.labeltemp0.SetForegroundColour((255,0,0)) # set text color
                    if int(data2[1]) > 85:
                        self.labeltemp0.SetLabel("Temp0 : "+data2[1]+"°C Warning /!\\")
                        self.labeltemp0.SetForegroundColour((255,0,0)) # set text color
                except ValueError:
                    if float(data2[1]) < 55:
                        self.labeltemp0.SetForegroundColour((127,255,0)) # set text color
                    if float(data2[1]) > 55:
                        self.labeltemp0.SetForegroundColour((255,150,0)) # set text color
                    if float(data2[1]) > 80:
                        self.labeltemp0.SetForegroundColour((255,0,0)) # set text color
                    if float(data2[1]) > 85:
                        self.labeltemp0.SetLabel("Temp0 : "+data2[1]+"°C Warning /!\\")
                        self.labeltemp0.SetForegroundColour((255,0,0)) # set text color
            else:
                self.labeltemp0.SetLabel("Temp0 : Error sensors !")
                self.labeltemp0.SetForegroundColour((255,0,0)) # set text color

        _reg_ex_pkg = re.compile(b'^\S+\.', re.M)
        output, error = subprocess.Popen(['dnf', 'check-update'], stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()
        updates = len(_reg_ex_pkg.findall(output))
        if updates == 0:
            self.labelupdate_sys.SetLabel("No update for your system")
            self.labelupdate_sys.SetForegroundColour((127,255,0))
        else:
            self.labelupdate_sys.SetLabel("new update ("+str(updates)+") total packages")
            self.labelupdate_sys.SetForegroundColour((255,150,0))
            self.toggleBtn_update = wx.Button(self, wx.ID_ANY, "Update system", size=(100,52), pos=(50,-1))
            self.toggleBtn_update.Bind(wx.EVT_BUTTON, self.UpdateSys)

    def UpdateSys(self, event):
        self.toggleBtn_update.Show(False)
        self.labelupdate_sys.SetLabel("Update progress...")
        output, error = subprocess.Popen(['dnf', 'update'], stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()
        event.Skip()

    def onMouseOver(self, event):
        # mouseover changes colour of button
        self.SetTransparent(255)
        event.Skip()

    def onMouseLeave(self, event):
        # mouse not over button, back to original colour
        self.SetTransparent(200)
        event.Skip()

    def AlphaCycle(self, evt):
        self.amount += self.delta
        if self.amount >= 255:
            self.delta = -self.delta
            self.amount = 255
        if self.amount <= 0:
            self.amount = 0
        self.SetTransparent(self.amount)

if __name__ == '__main__':
    app = wx.App(False)
    frm = Fader()
    frm.Show()
    app.MainLoop()
<commit_msg>Fix update module packages<commit_after># coding: utf-8
import wx
import time
import requests
import psutil
import re
import subprocess
import sys

# detect automatical controller
detect_controller = psutil.sensors_fans()
for control in detect_controller:
    Controller = control

class Fader(wx.Frame):

    def __init__(self):
        global label_fan
        global panel
        no_sys_menu = wx.CAPTION
        wx.Frame.__init__(self, None, title='WidgetMonitor', size=(200, 330), style=no_sys_menu)
        self.amount = 200
        self.delta = 5
        #self.ToggleWindowStyle(wx.STAY_ON_TOP)
        style = wx.TRANSPARENT_WINDOW if sys.platform.lower() == 'win32' else 0
        panel = wx.Panel(self, wx.ID_ANY, style=style)
        if panel.CanSetTransparent:
            panel.SetTransparent(100)

        self.SetTransparent(self.amount)
        self.Maximize(False)
        topSizer = wx.BoxSizer(wx.VERTICAL)

        ## ------- Fader Timer -------- ##
        self.timer = wx.Timer(self)
        self.Bind(wx.EVT_TIMER, self.update, self.timer)

        self.toggleBtn = wx.Button(panel, wx.ID_ANY, "Start", size=(50,50), pos=(75,0))
        self.toggleBtn.Bind(wx.EVT_BUTTON, self.onToggle)

        self.label = wx.StaticText(panel, wx.ID_ANY, label=time.ctime(), pos=(0,50), size=(200,20), style=wx.ALIGN_CENTRE)
        self.labelIpEXT = wx.StaticText(panel, wx.ID_ANY, label="Your ip Externe : 0.0.0.0", pos=(0,75), size=(200,20), style=wx.ALIGN_CENTRE)
        self.labelping = wx.StaticText(panel, wx.ID_ANY, label="check ping...", pos=(0,90), size=(200,20), style=wx.ALIGN_CENTRE)
        self.labeltemp0 = wx.StaticText(panel, wx.ID_ANY, label="temp0 : 0°C", pos=(0,110), size=(200,20), style=wx.ALIGN_CENTRE)

        #check fan speed
        correct = 0
        label_fan = {}
        data_fans = psutil.sensors_fans()
        for i in range(0, 9):
            try:
                data2 = re.sub('sfan', '', str(data_fans[Controller][i]))
                data2 = re.sub('[()]', '', str(data2))
                data2 = data2.split(",")
                data2[1] = data2[1].replace("current=", "")
                if int(data2[1]) > 0:
                    correct = correct + 1
                    print('detecte label_fan' + str(i+1))
                    label_fan[str(i)] = wx.StaticText(panel, wx.ID_ANY, label="fan "+ str(i+1) +" : "+data2[1]+" RPM", pos=(0,110+correct*20), size=(200,20), style=wx.ALIGN_CENTRE)
            except IndexError:
                break

        if correct > 1:
            # check update system
            self.labelupdate_sys = wx.StaticText(panel, wx.ID_ANY, label="checking... update", pos=(0,110+correct*30), size=(200,20), style=wx.ALIGN_CENTRE)

            # check cpu count
            self.labelinfo_sys = wx.StaticText(panel, wx.ID_ANY, label="Information system", pos=(0,110+correct*40), size=(200,20), style=wx.ALIGN_CENTRE)

            self.labelcpu_sys = wx.StaticText(panel, wx.ID_ANY, label="Number core CPU " + str(psutil.cpu_count()), pos=(0,110+correct*45), size=(200,20), style=wx.ALIGN_CENTRE)
            users = psutil.users()
            for user in users:
                self.labelusername_sys = wx.StaticText(panel, wx.ID_ANY, label="Username " + str(user[0]), pos=(0,110+correct*50), size=(200,20), style=wx.ALIGN_CENTRE)

            self.labelcopyright = wx.StaticText(panel, wx.ID_ANY, label="© vBlackOut", pos=(0,110+correct*55), size=(200,20), style=wx.ALIGN_CENTRE)

        else:
            # check update system
            self.labelupdate_sys = wx.StaticText(panel, wx.ID_ANY, label="checking... update", pos=(0,120+correct*30), size=(200,20), style=wx.ALIGN_CENTRE)

            # check cpu count
            self.labelinfo_sys = wx.StaticText(panel, wx.ID_ANY, label="Information system", pos=(0,130+correct*40), size=(200,20), style=wx.ALIGN_CENTRE)

            self.labelcpu_sys = wx.StaticText(panel, wx.ID_ANY, label="Number core CPU " + str(psutil.cpu_count()), pos=(0,140+correct*45), size=(200,20), style=wx.ALIGN_CENTRE)
            users = psutil.users()
            for user in users:
                self.labelusername_sys = wx.StaticText(panel, wx.ID_ANY, label="Username " + str(user[0]), pos=(0,150+correct*50), size=(200,20), style=wx.ALIGN_CENTRE)

            self.labelcopyright = wx.StaticText(panel, wx.ID_ANY, label="© vBlackOut", pos=(0,160+correct*55), size=(200,20), style=wx.ALIGN_CENTRE)

        #self.timer = wx.Timer(self, wx.ID_ANY)
        #self.timer.Start(60)
        #self.Bind(wx.EVT_TIMER, self.AlphaCycle)
        self.Bind(wx.EVT_ENTER_WINDOW, self.onMouseOver)
        self.Bind(wx.EVT_LEAVE_WINDOW, self.onMouseLeave)
        ## ---------------------------- ##

    def onToggle(self, event):
        btnLabel = self.toggleBtn.GetLabel()
        if btnLabel == "Start":
            print "starting timer..."
            self.timer.Start(5000)
            self.toggleBtn.SetLabel("Stop")
        else:
            print "timer stopped!"
            self.timer.Stop()
            self.toggleBtn.SetLabel("Start")

    def update(self, event):
        try:
        # get ip
            ipEXT = requests.get("https://ip4.cuby-hebergs.com")
            ipEXT = ipEXT.text
        except:
            ipEXT = "no network"

        # get temperature
        data = psutil.sensors_temperatures()
        data_fans = psutil.sensors_fans()
        for i in range(0, 9):
            try:
                if Controller == "thinkpad":
                    data2 = re.sub('sfan', '', str(data_fans[Controller][i]))
                    data2 = re.sub('[()]', '', str(data2))
                    data2 = data2.split(",")
                    data2[1] = data2[1].replace("current=", "")

                else:
                    data2 = re.sub('sfan', '', str(data_fans[Controller][i]))
                    data2 = re.sub('[()]', '', str(data2))
                    data2 = data2.split(",")
                    data2[1] = data2[1].replace("current=", "")

                if int(data2[1]) > 0:
                    try:
                        label_fan[str(i)].SetLabel("fan "+ str(i+1) +" : "+data2[1]+" RPM")
                    except KeyError:
                        continue
            except IndexError:
                break

        if Controller == "thinkpad":
            data2 = re.sub('shwtemp', '', str(data["acpitz"][0]))
            data2 = re.sub('[()]', '', str(data2))
            data2 = data2.split(",")
            data2[1] = data2[1].replace("current=", "")

        else:
            data2 = re.sub('shwtemp', '', str(data[Controller][0]))
            data2 = re.sub('[()]', '', str(data2))
            data2 = data2.split(",")
            data2[1] = data2[1].replace("current=", "")

        self.label.SetLabel(time.ctime())
        self.labelIpEXT.SetLabel("Your ip Externe : "+ipEXT)

        # Run the "ping" command
        command = "ping -W 1 -c 1 www.google.com"  # the shell command
        output = subprocess.check_output(command, shell=True)

        # And interpret the output
        matches = re.findall(" time=([\d.]+) ms", output)
        matches = [float(match) for match in matches]
        ms = round(sum(matches)/len(matches),1)
        self.labelping.SetLabel("your ping : "+str(ms)+" ms")

        if ms < 200.0:
            self.labelping.SetForegroundColour((127,255,0)) # set text color
        else:
            self.labelping.SetForegroundColour((255,0,0))

        self.labeltemp0.SetLabel("Temp0 : "+data2[1]+"°C")
        try:
            if float(data2[1]) >= 0:
                try:
                    if int(data2[1]) < 55:
                        self.labeltemp0.SetForegroundColour((127,255,0)) # set text color
                    if int(data2[1]) > 55:
                        self.labeltemp0.SetForegroundColour((255,150,0)) # set text color
                    if int(data2[1]) > 80:
                        self.labeltemp0.SetForegroundColour((255,0,0)) # set text color
                    if int(data2[1]) > 85:
                        self.labeltemp0.SetLabel("Temp0 : "+data2[1]+"°C Warning /!\\")
                        self.labeltemp0.SetForegroundColour((255,0,0)) # set text color
                except ValueError:
                    if float(data2[1]) < 55:
                        self.labeltemp0.SetForegroundColour((127,255,0)) # set text color
                    if float(data2[1]) > 55:
                        self.labeltemp0.SetForegroundColour((255,150,0)) # set text color
                    if float(data2[1]) > 80:
                        self.labeltemp0.SetForegroundColour((255,0,0)) # set text color
                    if float(data2[1]) > 85:
                        self.labeltemp0.SetLabel("Temp0 : "+data2[1]+"°C Warning /!\\")
                        self.labeltemp0.SetForegroundColour((255,0,0)) # set text color
            else:
                self.labeltemp0.SetLabel("Temp0 : Error sensors !")
                self.labeltemp0.SetForegroundColour((255,0,0)) # set text color

        except ValueError:
            if int(data2[1]) >= 0:
                try:
                    if int(data2[1]) < 55:
                        self.labeltemp0.SetForegroundColour((127,255,0)) # set text color
                    if int(data2[1]) > 55:
                        self.labeltemp0.SetForegroundColour((255,150,0)) # set text color
                    if int(data2[1]) > 80:
                        self.labeltemp0.SetForegroundColour((255,0,0)) # set text color
                    if int(data2[1]) > 85:
                        self.labeltemp0.SetLabel("Temp0 : "+data2[1]+"°C Warning /!\\")
                        self.labeltemp0.SetForegroundColour((255,0,0)) # set text color
                except ValueError:
                    if float(data2[1]) < 55:
                        self.labeltemp0.SetForegroundColour((127,255,0)) # set text color
                    if float(data2[1]) > 55:
                        self.labeltemp0.SetForegroundColour((255,150,0)) # set text color
                    if float(data2[1]) > 80:
                        self.labeltemp0.SetForegroundColour((255,0,0)) # set text color
                    if float(data2[1]) > 85:
                        self.labeltemp0.SetLabel("Temp0 : "+data2[1]+"°C Warning /!\\")
                        self.labeltemp0.SetForegroundColour((255,0,0)) # set text color
            else:
                self.labeltemp0.SetLabel("Temp0 : Error sensors !")
                self.labeltemp0.SetForegroundColour((255,0,0)) # set text color

        _reg_ex_pkg = re.compile(b'^\S+\.', re.M)
        output, error = subprocess.Popen(['dnf', 'check-update'], stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()
        updates = len(_reg_ex_pkg.findall(output))
        if updates == 0:
            self.labelupdate_sys.SetLabel("No update for your system")
            self.labelupdate_sys.SetForegroundColour((127,255,0))
        else:
            self.labelupdate_sys.SetLabel("new update ("+str(updates)+") packages")
            self.labelupdate_sys.SetForegroundColour((255,150,0))
            self.toggleBtn_update = wx.Button(self, wx.ID_ANY, "Update system", size=(100,52), pos=(50,-1))
            self.toggleBtn_update.Bind(wx.EVT_BUTTON, self.UpdateSys)

    def UpdateSys(self, event):
        self.toggleBtn_update.Show(False)
        self.labelupdate_sys.SetLabel("Update progress...")
        time.sleep(2)
        output, error = subprocess.Popen(['sudo', 'dnf', 'update', "-y"], stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()
        print(output, error)
        self.labelupdate_sys.SetLabel("Finish")
        time.sleep(2)
        event.Skip()

    def onMouseOver(self, event):
        # mouseover changes colour of button
        self.SetTransparent(255)
        event.Skip()

    def onMouseLeave(self, event):
        # mouse not over button, back to original colour
        self.SetTransparent(200)
        event.Skip()

    def AlphaCycle(self, evt):
        self.amount += self.delta
        if self.amount >= 255:
            self.delta = -self.delta
            self.amount = 255
        if self.amount <= 0:
            self.amount = 0
        self.SetTransparent(self.amount)

if __name__ == '__main__':
    app = wx.App(False)
    frm = Fader()
    frm.Show()
    app.MainLoop()
<|endoftext|>


<commit_before>#!/usr/bin/env python

"""
recursive descent parser/tokenizer/evaluator bignum calculator

based off of Rob Pike's slides implementing one in golang
 https://www.youtube.com/watch?v=PXoG0WX0r_E
"""

# python 2/3 compatibility
from __future__ import (
    absolute_import,
    division,
    print_function,
    unicode_literals
)
import sys
if sys.version_info < (3, 0):
    input = raw_input

# APL GRAMMAR
#
# operand
#   ( expression )
#   ( expression ) [ expression ]...
#   operand
#   number
#   rational
#   vector
#   variable
#   operand [ expression ]...
#   unary_op expression
#
# expression
#   operand
#   operand binary_op expr
#
# statement_list
#   statement
#   statement ';' statement
#
# statement
#   identifier '=' expression
#   expression

class Token(object):
    # meta
    statement_list = 1000
    statement = 1001
    identifier = 1002
    expression = 1003

    operator = 1004
    number = 1005
    rational = 1006
    identifier = 1007

    # character
    eof = 2000
    newline = 2001
    left_paren = 2002
    right_paren = 2003
    left_bracket = 2004
    right_bracket = 2005
    semicolon = 2006
    equal = 2007
    space = 2008

    def __init__(self, typ, text):
        self.typ = typ
        self.text = text

    def __str__(self):
        return self.text

    def __repr__(self):
        return "(" + str(self.typ) + ", " + self.text + ")"

class Value(object):
    def __str__(self):
        return str(self.val)

    def eval(self):
        return self.val

    # returns the most constrained type that matches the passed in value
    def value_as(self, value):
        return self

    # shrink the value to the smallest type possible
    def shrink(self):
        return self

    # get values v1 and v2 as the same underlying type (int, vector, matrix)
    @staticmethod
    def same(v1, v2):
        return (v1.value_as(v2), v2.value_as(v1))

    @staticmethod
    def binary_op(v1, op, v2):
        v1, v2 = Value.same(v1, v2)
        if op == '+':
            return v1.add(v2).shrink()

class Integer(Value):
    def __init__(self, str_val):
        self.val = int(str_val)

    def add(self, v):
        return Integer(self.val + v.val)

class Parser(object):
    def __init__(self):
        self.variables = {}
        self.cursor = 0
        self.data = ""

    def evaluate(self, data):
        # reset data and cursor, variable persist
        self.data = data
        self.cursor = 0

        # prime with first token
        return self.expression(self.next_tok())

    # Tokenizer functions

    # get the next token without advancing
    def peek_tok(self):
        tok, _ = self._next_tok_and_cursor()
        return tok

    # get the next token and advance
    def next_tok(self):
        tok, self.cursor = self._next_tok_and_cursor()
        return tok

    def _next_tok_and_cursor(self):
        cursor = self.cursor
        if cursor >= len(self.data):
            return (Token(Token.eof, ''), cursor+1)

        c = self.data[cursor]
        if c == "\n":
            return (Token(Token.newline, '\n'), cursor+1)
        elif c == '(':
            return (Token(Token.left_paren, '('), cursor+1)
        elif c == ')':
            return (Token(Token.right_paren, ')'), cursor+1)
        elif c == '[':
            return (Token(Token.left_bracket, '['), cursor+1)
        elif c == ']':
            return (Token(Token.right_bracket, ']'), cursor+1)
        elif c == ';':
            return (Token(Token.semicolon, ';'), cursor+1)
        elif c == '+':
            return (Token(Token.operator, '+'), cursor+1)
        elif c == '=':
            return (Token(Token.operator, '='), cursor+1)
        elif c in " \t":
            # consume all but one space
            while c in " \t":
                cursor += 1
                if cursor >= len(self.data):
                    break
                c = self.data[cursor]
            return (Token(Token.space, '<space>'), cursor)
        elif c.isdigit():
            text = ""
            while c.isdigit():
                text += c
                cursor += 1
                if cursor >= len(self.data):
                    break
                c = self.data[cursor]
            return (Token(Token.number, text), cursor)

        raise Exception("unexpected " + c)

    # Grammar functions

    def expression(self, tok):
        # whitespace is valid but does nothing
        if tok.typ == Token.space:
            tok = self.next_tok()

        # left side
        expr = self.operand(tok)

        # right side
        tok_next = self.peek_tok()

        # whitespace is valid but does nothing
        if tok_next.typ == Token.space:
            self.next_tok()
            tok_next = self.peek_tok()

        if tok_next.typ == Token.newline or \
                tok_next.typ == Token.eof or \
                tok_next.typ == Token.right_paren or \
                tok_next.typ == Token.right_bracket or \
                tok_next.typ == Token.semicolon:
            return expr

        # an operator on the right means binary operation
        if tok_next.typ == Token.operator:
            tok = self.next_tok()
            return Value.binary_op(expr, tok.text, self.expression(self.next_tok()))  # recurse

        raise Exception("after expresion: unexpected " + str(tok_next))

    def operand(self, tok):
        # an operator means a unary operation
        if tok.typ == Token.operator:
            expr = Value.unary_op(tok.text, self.expression(self.next_tok()))  # recurse

        elif tok.typ == Token.left_paren:
            expr = self.expression(self.next_tok())  # recurse
            tok = self.next_tok()
            if tok.typ != Token.right_paren:
                raise Exception("expected ')', found " + str(tok))

        elif tok.typ == Token.number or \
                tok.typ == Token.rational:
            expr = self.number(tok)

        elif tok.typ == Token.identifier:
            expr = variables.get(tok.text, None)
            if expr is None:
                raise Exception(str(tok) + " undefined")

        else:
            raise Exception("unexpected " + str(tok))

        return expr

    def number(self, tok):
        return Integer(tok.text)

if __name__ == '__main__':
    p = Parser()
    while True:
        try:
            output = p.evaluate(input())
        except EOFError:
            break
        print(output)
        print()

<commit_msg>support for variables<commit_after>#!/usr/bin/env python

"""
recursive descent parser/tokenizer/evaluator bignum calculator

based off of Rob Pike's slides implementing one in golang
 https://www.youtube.com/watch?v=PXoG0WX0r_E
"""

# python 2/3 compatibility
from __future__ import (
    absolute_import,
    division,
    print_function,
    unicode_literals
)
import sys
if sys.version_info < (3, 0):
    input = raw_input

# APL GRAMMAR
#
# operand
#   ( expression )
#   ( expression ) [ expression ]...
#   operand
#   number
#   rational
#   vector
#   variable
#   operand [ expression ]...
#   unary_op expression
#
# expression
#   operand
#   operand binary_op expr
#
# statement_list
#   statement
#   statement ';' statement
#
# statement
#   identifier '=' expression
#   expression

class Token(object):
    # meta
    statement_list = 1000
    statement = 1001
    identifier = 1002
    expression = 1003

    operator = 1004
    number = 1005
    rational = 1006
    identifier = 1007

    # character
    eof = 2000
    newline = 2001
    left_paren = 2002
    right_paren = 2003
    left_bracket = 2004
    right_bracket = 2005
    semicolon = 2006
    assign = 2007
    whitespace = 2008

    def __init__(self, typ, text):
        self.typ = typ
        self.text = text

    def __str__(self):
        return self.text

    def __repr__(self):
        return "(" + str(self.typ) + ", " + self.text + ")"

class Value(object):
    def __str__(self):
        return str(self.val)

    def eval(self):
        return self.val

    # returns the most constrained type that matches the passed in value
    def value_as(self, value):
        return self

    # shrink the value to the smallest type possible
    def shrink(self):
        return self

    # get values v1 and v2 as the same underlying type (int, vector, matrix)
    @staticmethod
    def same(v1, v2):
        return (v1.value_as(v2), v2.value_as(v1))

    @staticmethod
    def binary_op(v1, op, v2):
        v1, v2 = Value.same(v1, v2)
        if op == '+':
            return v1.add(v2).shrink()

class Integer(Value):
    def __init__(self, str_val):
        self.val = int(str_val)

    def add(self, v):
        return Integer(self.val + v.val)

class Parser(object):
    def __init__(self):
        self.variables = {}
        self.cursor = 0
        self.data = ""

    def evaluate(self, data):
        # reset data and cursor, variable persist
        self.data = data
        self.cursor = 0

        # prime with first token
        return self.expression(self.next_tok_skip_whitespace())

    # Tokenizer functions

    # get the next token without advancing
    def peek_tok(self):
        tok, _ = self._next_tok_and_cursor()
        return tok

    # get the next token and advance
    def next_tok(self):
        tok, self.cursor = self._next_tok_and_cursor()
        return tok

    # get the next non-whitespace token without advancing
    def peek_tok_skip_whitespace(self):
        cursor_saved = self.cursor
        tok, self.cursor = self._next_tok_and_cursor()
        while tok.typ == Token.whitespace:
            tok, self.cursor = self._next_tok_and_cursor()
        self.cursor = cursor_saved
        return tok

    # get the next non-whitespace token and advance
    def next_tok_skip_whitespace(self):
        tok, self.cursor = self._next_tok_and_cursor()
        while tok.typ == Token.whitespace:
            tok, self.cursor = self._next_tok_and_cursor()
        return tok

    def _next_tok_and_cursor(self):
        cursor = self.cursor
        if cursor >= len(self.data):
            return (Token(Token.eof, ''), cursor+1)

        c = self.data[cursor]
        if c == "\n":
            return (Token(Token.newline, '\n'), cursor+1)
        elif c == '(':
            return (Token(Token.left_paren, '('), cursor+1)
        elif c == ')':
            return (Token(Token.right_paren, ')'), cursor+1)
        elif c == '[':
            return (Token(Token.left_bracket, '['), cursor+1)
        elif c == ']':
            return (Token(Token.right_bracket, ']'), cursor+1)
        elif c == ';':
            return (Token(Token.semicolon, ';'), cursor+1)
        elif c == '+':
            return (Token(Token.operator, '+'), cursor+1)
        elif c == '=':
            return (Token(Token.assign, '='), cursor+1)

        elif c in " \t":
            # consume all but one space
            while c in " \t":
                cursor += 1
                if cursor >= len(self.data):
                    break
                c = self.data[cursor]
            return (Token(Token.whitespace, '<space>'), cursor)

        elif c.isdigit():
            text = ""
            while c.isdigit():
                text += c
                cursor += 1
                if cursor >= len(self.data):
                    break
                c = self.data[cursor]
            return (Token(Token.number, text), cursor)

        # identifier must start with alpha, but can then be alphanumeric
        elif c.isalpha():
            text = ""
            while c.isalnum():
                text += c
                cursor += 1
                if cursor >= len(self.data):
                    break
                c = self.data[cursor]
            return (Token(Token.identifier, text), cursor)

        raise Exception("unexpected " + c)

    # Grammar functions

    def expression(self, tok):
       # left side
        expr = self.operand(tok)

        # right side
        tok_next = self.peek_tok_skip_whitespace()

        if tok_next.typ == Token.newline or \
                tok_next.typ == Token.eof or \
                tok_next.typ == Token.right_paren or \
                tok_next.typ == Token.right_bracket or \
                tok_next.typ == Token.semicolon:
            return expr

        # an operator on the right means binary operation
        if tok_next.typ == Token.operator:
            tok = self.next_tok_skip_whitespace()
            return Value.binary_op(expr, tok.text, self.expression(self.next_tok_skip_whitespace()))  # recurse

        # assignment
        if tok_next.typ == Token.assign:
            identifier = tok.text
            tok = self.next_tok_skip_whitespace()
            val = self.expression(self.next_tok_skip_whitespace())  # recurse
            self.variables[identifier] = val
            return val

        raise Exception("after expresion: unexpected " + str(tok_next))

    def operand(self, tok):
        # an operator means a unary operation
        if tok.typ == Token.operator:
            expr = Value.unary_op(tok.text, self.expression(self.next_tok_skip_whitespace()))  # recurse

        elif tok.typ == Token.left_paren:
            expr = self.expression(self.next_tok_skip_whitespace())  # recurse
            tok = self.next_tok_skip_whitespace()
            if tok.typ != Token.right_paren:
                raise Exception("expected ')', found " + str(tok))

        elif tok.typ == Token.number or \
                tok.typ == Token.rational:
            expr = self.number(tok)

        elif tok.typ == Token.identifier:
            # first check if we are assigning, then evaluate
            tok_next = self.peek_tok_skip_whitespace()
            if tok_next.typ == Token.assign:
                self.next_tok_skip_whitespace()  # consume assignment operator
                self.variables[tok.text] = self.expression(self.next_tok_skip_whitespace())  # recurse
            expr = self.variables.get(tok.text, None)
            if expr is None:
                raise Exception(str(tok) + " undefined")

        else:
            raise Exception("unexpected " + str(tok))

        return expr

    def number(self, tok):
        return Integer(tok.text)

if __name__ == '__main__':
    p = Parser()
    while True:
        try:
            output = p.evaluate(input())
        except EOFError:
            break
        print(output)
        print()

<|endoftext|>


<commit_before># its a comment
<commit_msg>Main part<commit_after># main part of Traffic Jam

import numpy as np
import matplotlib.pyplot as pl

vi=input("please enter the initial velocity=")
nm=input("please enter the max number of cars in the street=")
dt=input("please enter the time step for computation (e.g. 0.1, 0.01, ...)=")
tt=input("please enter the total time of simulation (based on min=")
ti=input("please enter the time interval for adding new car to street= ")

tt*=60

st=[]   # creation of street
tv=[]

# creation of target of velecities

for i in range of (nm+1):
    tv=uniform(2*vi,10*vi)

for t in range of (0,tt,dt) :
    if t % ti == 0 :
        st.append(t)<|endoftext|>