<commit_before>import numpy as np
import matplotlib as mpl
from distutils.version import LooseVersion
import nose
import matplotlib.pyplot as plt
import nose.tools as nt
import numpy.testing as npt

from . import PlotTestCase
from .. import rcmod

class RCParamTester(object):

    def flatten_list(self, orig_list):

        iter_list = map(np.atleast_1d, orig_list)
        flat_list = [item for sublist in iter_list for item in sublist]
        return flat_list

    def assert_rc_params(self, params):

        for k, v in params.items():
            if k == "svg.embed_char_paths":
                # This param causes test issues and is deprecated anyway
                continue
            elif isinstance(v, np.ndarray):
                npt.assert_array_equal(mpl.rcParams[k], v)
            else:
                nt.assert_equal((k, mpl.rcParams[k]), (k, v))

class TestAxesStyle(RCParamTester):

    styles = ["white", "dark", "whitegrid", "darkgrid", "ticks"]

    def test_default_return(self):

        current = rcmod.axes_style()
        self.assert_rc_params(current)

    def test_key_usage(self):

        _style_keys = set(rcmod._style_keys)
        for style in self.styles:
            nt.assert_true(not set(rcmod.axes_style(style)) ^ _style_keys)

    def test_bad_style(self):

        with nt.assert_raises(ValueError):
            rcmod.axes_style("i_am_not_a_style")

    def test_rc_override(self):

        rc = {"axes.facecolor": "blue", "foo.notaparam": "bar"}
        out = rcmod.axes_style("darkgrid", rc)
        nt.assert_equal(out["axes.facecolor"], "blue")
        nt.assert_not_in("foo.notaparam", out)

    def test_set_style(self):

        for style in self.styles:

            style_dict = rcmod.axes_style(style)
            rcmod.set_style(style)
            self.assert_rc_params(style_dict)

    def test_style_context_manager(self):

        rcmod.set_style("darkgrid")
        orig_params = rcmod.axes_style()
        context_params = rcmod.axes_style("whitegrid")

        with rcmod.axes_style("whitegrid"):
            self.assert_rc_params(context_params)
        self.assert_rc_params(orig_params)

        @rcmod.axes_style("whitegrid")
        def func():
            self.assert_rc_params(context_params)
        func()
        self.assert_rc_params(orig_params)

    def test_style_context_independence(self):

        nt.assert_true(set(rcmod._style_keys) ^ set(rcmod._context_keys))

    def test_set_rc(self):

        rcmod.set(rc={"lines.linewidth": 4})
        nt.assert_equal(mpl.rcParams["lines.linewidth"], 4)
        rcmod.set()

    def test_reset_defaults(self):

        # Changes to the rc parameters make this test hard to manage
        # on older versions of matplotlib, so we'll skip it
        if LooseVersion(mpl.__version__) < LooseVersion("1.3"):
            raise nose.SkipTest

        rcmod.reset_defaults()
        self.assert_rc_params(mpl.rcParamsDefault)
        rcmod.set()

    def test_reset_orig(self):

        # Changes to the rc parameters make this test hard to manage
        # on older versions of matplotlib, so we'll skip it
        if LooseVersion(mpl.__version__) < LooseVersion("1.3"):
            raise nose.SkipTest

        rcmod.reset_orig()
        self.assert_rc_params(mpl.rcParamsOrig)
        rcmod.set()

class TestPlottingContext(RCParamTester):

    contexts = ["paper", "notebook", "talk", "poster"]

    def test_default_return(self):

        current = rcmod.plotting_context()
        self.assert_rc_params(current)

    def test_key_usage(self):

        _context_keys = set(rcmod._context_keys)
        for context in self.contexts:
            missing = set(rcmod.plotting_context(context)) ^ _context_keys
            nt.assert_true(not missing)

    def test_bad_context(self):

        with nt.assert_raises(ValueError):
            rcmod.plotting_context("i_am_not_a_context")

    def test_font_scale(self):

        notebook_ref = rcmod.plotting_context("notebook")
        notebook_big = rcmod.plotting_context("notebook", 2)

        font_keys = ["axes.labelsize", "axes.titlesize", "legend.fontsize",
                     "xtick.labelsize", "ytick.labelsize", "font.size"]

        for k in font_keys:
            nt.assert_equal(notebook_ref[k] * 2, notebook_big[k])

    def test_rc_override(self):

        key, val = "grid.linewidth", 5
        rc = {key: val, "foo": "bar"}
        out = rcmod.plotting_context("talk", rc=rc)
        nt.assert_equal(out[key], val)
        nt.assert_not_in("foo", out)

    def test_set_context(self):

        for context in self.contexts:

            context_dict = rcmod.plotting_context(context)
            rcmod.set_context(context)
            self.assert_rc_params(context_dict)

    def test_context_context_manager(self):

        rcmod.set_context("notebook")
        orig_params = rcmod.plotting_context()
        context_params = rcmod.plotting_context("paper")

        with rcmod.plotting_context("paper"):
            self.assert_rc_params(context_params)
        self.assert_rc_params(orig_params)

        @rcmod.plotting_context("paper")
        def func():
            self.assert_rc_params(context_params)
        func()
        self.assert_rc_params(orig_params)

class TestFonts(PlotTestCase):

    def test_set_font(self):

        rcmod.set(font="Verdana")

        _, ax = plt.subplots()
        ax.set_xlabel("foo")

        try:
            nt.assert_equal(ax.xaxis.label.get_fontname(),
                            "Verdana")
        except AssertionError:
            if has_verdana():
                raise
            else:
                raise nose.SkipTest("Verdana font is not present")
        finally:
            rcmod.set()

    def test_set_serif_font(self):

        rcmod.set(font="serif")

        _, ax = plt.subplots()
        ax.set_xlabel("foo")

        nt.assert_in(ax.xaxis.label.get_fontname(),
                     mpl.rcParams["font.serif"])

        rcmod.set()

    def test_different_sans_serif(self):

        if LooseVersion(mpl.__version__) < LooseVersion("1.4"):
            raise nose.SkipTest

        rcmod.set()
        rcmod.set_style(rc={"font.sans-serif":
                            ["Verdana"]})

        _, ax = plt.subplots()
        ax.set_xlabel("foo")

        try:
            nt.assert_equal(ax.xaxis.label.get_fontname(),
                            "Verdana")
        except AssertionError:
            if has_verdana():
                raise
            else:
                raise nose.SkipTest("Verdana font is not present")
        finally:
            rcmod.set()

def has_verdana():
    """Helper to verify if Verdana font is present"""
    # This import is relatively lengthy, so to prevent its import for
    # testing other tests in this module not requiring this knowledge,
    # import font_manager here
    import matplotlib.font_manager as mplfm
    try:
        verdana_font = mplfm.findfont('Verdana', fallback_to_default=False)
    except:
        # if https://github.com/matplotlib/matplotlib/pull/3435
        # gets accepted
        return False
    # otherwise check if not matching the logic for a 'default' one
    try:
        unlikely_font = mplfm.findfont("very_unlikely_to_exist1234",
                                       fallback_to_default=False)
    except:
        # if matched verdana but not unlikely, Verdana must exist
        return True
    # otherwise -- if they match, must be the same default
    return verdana_font != unlikely_font
<commit_msg>Remove handling of deprecated rcparam<commit_after>import numpy as np
import matplotlib as mpl
from distutils.version import LooseVersion
import nose
import matplotlib.pyplot as plt
import nose.tools as nt
import numpy.testing as npt

from . import PlotTestCase
from .. import rcmod

class RCParamTester(object):

    def flatten_list(self, orig_list):

        iter_list = map(np.atleast_1d, orig_list)
        flat_list = [item for sublist in iter_list for item in sublist]
        return flat_list

    def assert_rc_params(self, params):

        for k, v in params.items():
            if isinstance(v, np.ndarray):
                npt.assert_array_equal(mpl.rcParams[k], v)
            else:
                nt.assert_equal((k, mpl.rcParams[k]), (k, v))

class TestAxesStyle(RCParamTester):

    styles = ["white", "dark", "whitegrid", "darkgrid", "ticks"]

    def test_default_return(self):

        current = rcmod.axes_style()
        self.assert_rc_params(current)

    def test_key_usage(self):

        _style_keys = set(rcmod._style_keys)
        for style in self.styles:
            nt.assert_true(not set(rcmod.axes_style(style)) ^ _style_keys)

    def test_bad_style(self):

        with nt.assert_raises(ValueError):
            rcmod.axes_style("i_am_not_a_style")

    def test_rc_override(self):

        rc = {"axes.facecolor": "blue", "foo.notaparam": "bar"}
        out = rcmod.axes_style("darkgrid", rc)
        nt.assert_equal(out["axes.facecolor"], "blue")
        nt.assert_not_in("foo.notaparam", out)

    def test_set_style(self):

        for style in self.styles:

            style_dict = rcmod.axes_style(style)
            rcmod.set_style(style)
            self.assert_rc_params(style_dict)

    def test_style_context_manager(self):

        rcmod.set_style("darkgrid")
        orig_params = rcmod.axes_style()
        context_params = rcmod.axes_style("whitegrid")

        with rcmod.axes_style("whitegrid"):
            self.assert_rc_params(context_params)
        self.assert_rc_params(orig_params)

        @rcmod.axes_style("whitegrid")
        def func():
            self.assert_rc_params(context_params)
        func()
        self.assert_rc_params(orig_params)

    def test_style_context_independence(self):

        nt.assert_true(set(rcmod._style_keys) ^ set(rcmod._context_keys))

    def test_set_rc(self):

        rcmod.set(rc={"lines.linewidth": 4})
        nt.assert_equal(mpl.rcParams["lines.linewidth"], 4)
        rcmod.set()

    def test_reset_defaults(self):

        # Changes to the rc parameters make this test hard to manage
        # on older versions of matplotlib, so we'll skip it
        if LooseVersion(mpl.__version__) < LooseVersion("1.3"):
            raise nose.SkipTest

        rcmod.reset_defaults()
        self.assert_rc_params(mpl.rcParamsDefault)
        rcmod.set()

    def test_reset_orig(self):

        # Changes to the rc parameters make this test hard to manage
        # on older versions of matplotlib, so we'll skip it
        if LooseVersion(mpl.__version__) < LooseVersion("1.3"):
            raise nose.SkipTest

        rcmod.reset_orig()
        self.assert_rc_params(mpl.rcParamsOrig)
        rcmod.set()

class TestPlottingContext(RCParamTester):

    contexts = ["paper", "notebook", "talk", "poster"]

    def test_default_return(self):

        current = rcmod.plotting_context()
        self.assert_rc_params(current)

    def test_key_usage(self):

        _context_keys = set(rcmod._context_keys)
        for context in self.contexts:
            missing = set(rcmod.plotting_context(context)) ^ _context_keys
            nt.assert_true(not missing)

    def test_bad_context(self):

        with nt.assert_raises(ValueError):
            rcmod.plotting_context("i_am_not_a_context")

    def test_font_scale(self):

        notebook_ref = rcmod.plotting_context("notebook")
        notebook_big = rcmod.plotting_context("notebook", 2)

        font_keys = ["axes.labelsize", "axes.titlesize", "legend.fontsize",
                     "xtick.labelsize", "ytick.labelsize", "font.size"]

        for k in font_keys:
            nt.assert_equal(notebook_ref[k] * 2, notebook_big[k])

    def test_rc_override(self):

        key, val = "grid.linewidth", 5
        rc = {key: val, "foo": "bar"}
        out = rcmod.plotting_context("talk", rc=rc)
        nt.assert_equal(out[key], val)
        nt.assert_not_in("foo", out)

    def test_set_context(self):

        for context in self.contexts:

            context_dict = rcmod.plotting_context(context)
            rcmod.set_context(context)
            self.assert_rc_params(context_dict)

    def test_context_context_manager(self):

        rcmod.set_context("notebook")
        orig_params = rcmod.plotting_context()
        context_params = rcmod.plotting_context("paper")

        with rcmod.plotting_context("paper"):
            self.assert_rc_params(context_params)
        self.assert_rc_params(orig_params)

        @rcmod.plotting_context("paper")
        def func():
            self.assert_rc_params(context_params)
        func()
        self.assert_rc_params(orig_params)

class TestFonts(PlotTestCase):

    def test_set_font(self):

        rcmod.set(font="Verdana")

        _, ax = plt.subplots()
        ax.set_xlabel("foo")

        try:
            nt.assert_equal(ax.xaxis.label.get_fontname(),
                            "Verdana")
        except AssertionError:
            if has_verdana():
                raise
            else:
                raise nose.SkipTest("Verdana font is not present")
        finally:
            rcmod.set()

    def test_set_serif_font(self):

        rcmod.set(font="serif")

        _, ax = plt.subplots()
        ax.set_xlabel("foo")

        nt.assert_in(ax.xaxis.label.get_fontname(),
                     mpl.rcParams["font.serif"])

        rcmod.set()

    def test_different_sans_serif(self):

        if LooseVersion(mpl.__version__) < LooseVersion("1.4"):
            raise nose.SkipTest

        rcmod.set()
        rcmod.set_style(rc={"font.sans-serif":
                            ["Verdana"]})

        _, ax = plt.subplots()
        ax.set_xlabel("foo")

        try:
            nt.assert_equal(ax.xaxis.label.get_fontname(),
                            "Verdana")
        except AssertionError:
            if has_verdana():
                raise
            else:
                raise nose.SkipTest("Verdana font is not present")
        finally:
            rcmod.set()

def has_verdana():
    """Helper to verify if Verdana font is present"""
    # This import is relatively lengthy, so to prevent its import for
    # testing other tests in this module not requiring this knowledge,
    # import font_manager here
    import matplotlib.font_manager as mplfm
    try:
        verdana_font = mplfm.findfont('Verdana', fallback_to_default=False)
    except:
        # if https://github.com/matplotlib/matplotlib/pull/3435
        # gets accepted
        return False
    # otherwise check if not matching the logic for a 'default' one
    try:
        unlikely_font = mplfm.findfont("very_unlikely_to_exist1234",
                                       fallback_to_default=False)
    except:
        # if matched verdana but not unlikely, Verdana must exist
        return True
    # otherwise -- if they match, must be the same default
    return verdana_font != unlikely_font
<|endoftext|>


<commit_before>{
    "name": "Avalara Avatax Connector",
    "version": "13.0.3.1.1",
    "author": "Fabrice Henrion, Odoo Community Association (OCA)",
    "summary": "Automatic Tax application using the Avalara Avatax Service",
    "license": "AGPL-3",
    "category": "Accounting",
    "depends": ["account", "sale_stock", "base_geolocalize"],
    "data": [
        "security/avalara_salestax_security.xml",
        "security/ir.model.access.csv",
        "data/avalara_salestax_data.xml",
        "data/avalara_salestax_exemptions.xml",
        "wizard/avalara_salestax_ping_view.xml",
        "wizard/avalara_salestax_address_validate_view.xml",
        "views/avalara_salestax_view.xml",
        "views/partner_view.xml",
        "views/product_view.xml",
        "views/account_move_action.xml",
        "views/account_move_view.xml",
        "views/account_tax_view.xml",
        "views/account_fiscal_position_view.xml",
    ],
    "image": ["static/description/avatax_icon.png"],
    "installable": True,
    "application": True,
    "external_dependencies": {"python": ["Avalara"]},
    "development_status": "Beta",
    "maintainers": ["dreispt"],
}
<commit_msg>account_avatax 13.0.3.1.2<commit_after>{
    "name": "Avalara Avatax Connector",
    "version": "13.0.3.1.2",
    "author": "Fabrice Henrion, Odoo Community Association (OCA)",
    "summary": "Automatic Tax application using the Avalara Avatax Service",
    "license": "AGPL-3",
    "category": "Accounting",
    "depends": ["account", "sale_stock", "base_geolocalize"],
    "data": [
        "security/avalara_salestax_security.xml",
        "security/ir.model.access.csv",
        "data/avalara_salestax_data.xml",
        "data/avalara_salestax_exemptions.xml",
        "wizard/avalara_salestax_ping_view.xml",
        "wizard/avalara_salestax_address_validate_view.xml",
        "views/avalara_salestax_view.xml",
        "views/partner_view.xml",
        "views/product_view.xml",
        "views/account_move_action.xml",
        "views/account_move_view.xml",
        "views/account_tax_view.xml",
        "views/account_fiscal_position_view.xml",
    ],
    "image": ["static/description/avatax_icon.png"],
    "installable": True,
    "application": True,
    "external_dependencies": {"python": ["Avalara"]},
    "development_status": "Beta",
    "maintainers": ["dreispt"],
}
<|endoftext|>


<commit_before>from traitlets import List, Unicode
from oauthenticator.generic import GenericOAuthenticator
import aiohttp

class CanvasOAuthenticator(GenericOAuthenticator):
    """
    Canvas OAuth2 based authenticator for JupyterHub.

    Collects info about user & enrolled courses from canvas,
    puts them into auth_state. To refresh, user has to re-login.
    """

    strip_email_domain = Unicode(
        '',
        config=True,
        help="""
        Strip this domain from user emails when making their JupyterHub user name.

        For example, if almost all your users have emails of form username@berkeley.edu,
        you can set this to 'berkeley.edu'. A canvas user with email yuvipanda@berkeley.edu
        will get a JupyterHub user name of 'yuvipanda', while a canvas user with email
        yuvipanda@gmail.com will get a JupyterHub username of 'yuvipanda@gmail.com'.

        By default, *no* domain stripping is performed, and the JupyterHub username
        is the primary email of the canvas user.
        """
    )

    canvas_url = Unicode(
        '',
        config=True,
        help="""
        URL to canvas installation to use for authentication.

        Must have a trailing slash
        """
    )

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        if not self.canvas_url:
            raise ValueError('c.CanvasOAuthenticator.canvas_url must be set')

        # canvas_url must have a trailing slash
        if self.canvas_url[-1] != '/':
            raise ValueError('c.CanvasOAuthenticator.canvas_url must have a trailing slash')

        self.token_url = f'{self.canvas_url}login/oauth2/token'
        self.userdata_url = f'{self.canvas_url}api/v1/users/self/profile'

        self.extra_params = {
            'client_id': self.client_id,
            'client_secret': self.client_secret
        }

    async def get_canvas_items(self, token, url):
        """
        Get paginated items from Canvas.
        https://canvas.instructure.com/doc/api/file.pagination.html
        """
        headers = dict(Authorization = f"Bearer {token}")
        data = []

        async with aiohttp.ClientSession() as session:
            async with session.get(url, headers=headers, params=self.extra_params) as r:
                if r.status != 200:
                    raise Exception(f"error fetching items for {self.username}: {url} -- {r.status} -- {r.text()}")
                data = await r.json()
                if 'next' in r.links.keys():
                    url = r.links['next']['url']
                    data += await self.get_canvas_items(token, url)

        return data

    async def get_courses(self, token):
        """
        Get list of courses enrolled by the current user
        """
        url = f"{self.canvas_url}/api/v1/courses"

        data = await self.get_canvas_items(token, url)

        return data

    async def authenticate(self, handler, data=None):
        """
        Augment base user auth info with course info
        """
        user = await super().authenticate(handler, data)
        user['auth_state']['courses'] = await self.get_courses(
            user['auth_state']['access_token']
        )
        return user

    def normalize_username(self, username):
        username = username.lower()
        # To make life easier & match usernames with existing users who were
        # created with google auth, we want to strip the domain name. If not,
        # we use the full email as the official user name
        if self.strip_email_domain and username.endswith('@' + self.strip_email_domain):
            return username.split('@')[0]
        return username

    async def pre_spawn_start(self, user, spawner):
        """Pass oauth data to spawner via OAUTH2_ prefixed env variables."""
        auth_state = yield user.get_auth_state()
        if not auth_state:
            return
        if 'access_token' in auth_state:
            spawner.environment["OAUTH2_ACCESS_TOKEN"] = auth_state['access_token']
        # others are lti_user_id, id, integration_id
        if 'oauth_user' in auth_state:
            for k in ['login_id', 'name', 'sortable_name', 'primary_email']:
                if k in auth_state['oauth_user']:
                    spawner.environment[f"OAUTH2_{k.upper()}"] = auth_state['oauth_user'][k]
<commit_msg>Add user to course-based groups.<commit_after>from traitlets import List, Unicode
from oauthenticator.generic import GenericOAuthenticator
import aiohttp

class CanvasOAuthenticator(GenericOAuthenticator):
    """
    Canvas OAuth2 based authenticator for JupyterHub.

    Collects info about user & enrolled courses from canvas,
    puts them into auth_state. To refresh, user has to re-login.
    """

    strip_email_domain = Unicode(
        '',
        config=True,
        help="""
        Strip this domain from user emails when making their JupyterHub user name.

        For example, if almost all your users have emails of form username@berkeley.edu,
        you can set this to 'berkeley.edu'. A canvas user with email yuvipanda@berkeley.edu
        will get a JupyterHub user name of 'yuvipanda', while a canvas user with email
        yuvipanda@gmail.com will get a JupyterHub username of 'yuvipanda@gmail.com'.

        By default, *no* domain stripping is performed, and the JupyterHub username
        is the primary email of the canvas user.
        """
    )

    canvas_url = Unicode(
        '',
        config=True,
        help="""
        URL to canvas installation to use for authentication.

        Must have a trailing slash
        """
    )

    course_key = Unicode(
        '',
        config=True,
        help="""
        Key to lookup course identifier from Canvas course data.

        This might be sis_course_id, course_code, id, etc.

        sis_course_id examples: CRS:MATH-98-2021-C, CRS:CHEM-1A-2021-D, CRS:PHYSICS-77-2022-C
        course_code examples: "Math 98", "Chem 1A Fall 2021", "PHYSICS 77-LEC-001"
        """
    )

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        if not self.canvas_url:
            raise ValueError('c.CanvasOAuthenticator.canvas_url must be set')

        # canvas_url must have a trailing slash
        if self.canvas_url[-1] != '/':
            raise ValueError('c.CanvasOAuthenticator.canvas_url must have a trailing slash')

        self.token_url = f'{self.canvas_url}login/oauth2/token'
        self.userdata_url = f'{self.canvas_url}api/v1/users/self/profile'

        self.extra_params = {
            'client_id': self.client_id,
            'client_secret': self.client_secret
        }

    async def get_canvas_items(self, token, url):
        """
        Get paginated items from Canvas.
        https://canvas.instructure.com/doc/api/file.pagination.html
        """
        headers = dict(Authorization = f"Bearer {token}")
        data = []

        async with aiohttp.ClientSession() as session:
            async with session.get(url, headers=headers, params=self.extra_params) as r:
                if r.status != 200:
                    raise Exception(f"error fetching items for {self.username}: {url} -- {r.status} -- {r.text()}")
                data = await r.json()
                if 'next' in r.links.keys():
                    url = r.links['next']['url']
                    data += await self.get_canvas_items(token, url)

        return data

    async def get_courses(self, token):
        """
        Get list of courses enrolled by the current user

        See https://canvas.instructure.com/doc/api/courses.html#method.courses.index
        """
        url = f"{self.canvas_url}/api/v1/courses"

        data = await self.get_canvas_items(token, url)

        return data

    def format_group(course_identifier, enrollment_type):
        if enrollment_type is None:
            return f'canvas::{course_identifier}'
        else
            return f'canvas::{course_identifier}::{enrollment_type}'

    def extract_course_groups(courses):
        '''
        Extract course identifiers for each course the user is enrolled in
        and format them as group names.
        '''
        groups = []

        for course in user['auth_state']['courses']:
            course_id = course.get(self.course_key, None)
            if course_id is None:
                continue

            # examples: [{'enrollment_state': 'active', 'role': 'TeacherEnrollment', 'role_id': 1773, 'type': 'teacher', 'user_id': 12345}],
            # https://canvas.instructure.com/doc/api/courses.html#method.courses.index
            # there may be multiple enrollments per course
            enrollment_types = list(
                map(
                    lambda x: x.get('type', None), course.get('enrollments', [])
                )
            )

            for enrollment_type in enrollment_types:
                groups.append(format_group(course_id, enrollment_type)

        return groups

    async def authenticate(self, handler, data=None):
        """
        Augment base user auth info with course info
        """
        user = await super().authenticate(handler, data)
        courses = await self.get_courses(user['auth_state']['access_token'])
        user['auth_state']['courses'] = courses
        user['groups'] = self.extract_course_groups(courses)

        return user

    def normalize_username(self, username):
        username = username.lower()
        # To make life easier & match usernames with existing users who were
        # created with google auth, we want to strip the domain name. If not,
        # we use the full email as the official user name
        if self.strip_email_domain and username.endswith('@' + self.strip_email_domain):
            return username.split('@')[0]
        return username

    async def pre_spawn_start(self, user, spawner):
        """Pass oauth data to spawner via OAUTH2_ prefixed env variables."""
        auth_state = yield user.get_auth_state()
        if not auth_state:
            return
        if 'access_token' in auth_state:
            spawner.environment["OAUTH2_ACCESS_TOKEN"] = auth_state['access_token']
        # others are lti_user_id, id, integration_id
        if 'oauth_user' in auth_state:
            for k in ['login_id', 'name', 'sortable_name', 'primary_email']:
                if k in auth_state['oauth_user']:
                    spawner.environment[f"OAUTH2_{k.upper()}"] = auth_state['oauth_user'][k]
<|endoftext|>


<commit_before>import string
import math
from enum import Enum

class Weighting(Enum):
    TermFrequency = 1,
    LogTermFrequency = 2,
    Tf_Idf = 3

class Index:
    def __init__(self, common_words, documents=None):
        self.__index = {}  # a dict mapping words to TermInfo
        self.__stats = {}  # a dict mapping doc IDs to DocStats
        self.common_words = common_words
        self.__nb_documents = 0
        if documents is not None:
            for doc in documents:
                self.add_document(doc)

    def get_words_by_doc_id(self, doc_id):
        return self.__stats[doc_id].frequency.keys()

    def add_document(self, document):
        """
        Parameters:
            document : a document (must respond to `doc_id` and `get_full_text`).

            Document IDs must be unique in the index.
        Raises:
            ValueError: when trying to insert a document whose ID already exists in the index
        """
        stats = document_word_count(document, self.common_words)
        if document.doc_id in self.__stats:
            raise ValueError("Document ID {0} is already present in this index".format(document.doc_id))
        for word, count in stats.frequency.items():
            assert(count > 0)
            if word not in self.__index:
                self.__index[word] = TermInfo()
            self.__index[word].add_document(document.doc_id, count)
        self.__stats[document.doc_id] = stats
        self.__nb_documents += 1

    def get_word_count(self, word):
        """
        Returns:
            the number of occurences of the given word in the collection
        """
        if word in self.__index:
            return self.__index[word].count
        return 0

    def get_nb_docs_with_word(self, word):
        if word not in self.__index:
            return 0
        return self.__index[word].nb_documents

    @property
    def words(self):
        """
        Returns:
            list of str: the words in this index dictionnary (e.g. the indexed keywords)
        """
        return self.__index.keys()

    @property
    def doc_ids(self):
        """
        Returns:
            list of int: a list of the IDs of the documents indexed in this index
        """
        return self.__stats.keys()

    def get_weights(self, doc_id, weighting_method, corpus_index=None):
        """
        Parameter:
            doc_id (int): a document ID. This document must be present in the index.
            weighting_method (Weighting): the method used to compute the weight of each term in the document
            corpus_index (Index): used only for the method Tf_Idf, the index for the corpus (not of the request). This parameter is ignored for other weighting methods.
        Returns:
            A dict mapping the words in the given document to their weights.
        """
        return self.__stats[doc_id].weights(weighting_method, corpus_index)

    @property
    def nb_documents(self):
        return self.__nb_documents

    def get_doc_ids_containing(self, word):
        """
        Parameter:
            word (str)
        Returns:
            list of int: a list of the IDs of documents containing the word (may be empty)
        """
        if word not in self.__index:
            return []
        return self.__index[word].docs.keys()

    def probability_rsv(self, request_index, doc_id):
        """
        Parameters:
            request_index (Index)
            doc_id (int)
        Returns:
          (float) The retrieval status value for the document (relative to the given request), under the PRP (probability ranking principe) model and the BIR (binary independance retrieval) hypothesis
        """
        intersect = set(request_index.words) & set(self.__stats[doc_id].words)
        if len(intersect) == 0:
            return None
        rsv = 0
        for word in intersect:
            dft = self.get_nb_docs_with_word(word)
            assert(dft >= 1)  # dft >= 1 by definition of intersect
            a = math.log10(self.nb_documents / dft)
            pr = 0.5  # TODO: use a more sophisticated method
            b = math.log10(pr / (1 - pr))
            rsv += b + a
        return rsv

class TermInfo:
    """Various statistics about a word (relative to the entire collection)
    """
    def __init__(self):
        self.docs = {} # doc_id, freq
        self.count = 0

    def add_document(self, doc_id, count):
        if doc_id in self.docs:
            self.docs[doc_id] += count
        else:
            self.docs[doc_id] = count
        self.count += count

    @property
    def nb_documents(self):
        return len(self.docs)

class DocStats:
    """Various statistics about a document.
    """

    def __init__(self, frequency, nb_words):
        """
        Parameters:
            frequency (dict): a dictionary mapping words to their number of occurences
            nb_words (int): the number of words in the document.
        """
        self.frequency = frequency
        self.nb_words = nb_words

    def weights(self, weighting, index=None):
        """
        Returns:
            a dictionary mapping each word in the document to a weight
        """
        if weighting == Weighting.TermFrequency:
            return self.__term_frequency_weights()
        elif weighting == Weighting.LogTermFrequency:
            return self.__log_term_frequency_weights()
        elif weighting == Weighting.Tf_Idf:
            if index is None:
                raise ValueError("An index must be provided to compute the tf-idf weights")
            return  self.__tf_idf_weights(index)
        else:
            raise ValueError("Unsupported weighting method: {0}".format(weighting))

    @property
    def words(self):
        return self.frequency.keys()

    def __term_frequency_weights(self):
        """
        Returns:
            a dictionary mapping each word in the document to a tf weight
        """
        out = {}
        for word in self.frequency.keys():
            out[word] = self.frequency[word]
        # Normalization
        return {word: frequency / max(out.values()) for word, frequency in out.items()}

    def __log_term_frequency_weights(self):
        """
        Returns:
            a dictionary mapping each word in the document to a ltf weight
        """
        out = {}
        for word in self.frequency.keys():
            if self.frequency[word] > 0:
                out[word] = 1 + math.log10(self.frequency[word])
        # Normalization
        return {word: weight / max(out.values()) for word, weight in out.items()}

    def __tf_idf_weights(self, index):
        """
        Returns:
            a dictionary mapping each word in the document to a tf-idf weight
        """
        out = {}
        for word in self.frequency.keys():
            dft = index.get_nb_docs_with_word(word)
            if self.frequency[word] > 0 and dft > 0:
                out[word] = (1 + math.log10(self.frequency[word])) * math.log10(index.nb_documents / dft)
        # Normalization
        return {word: weight / max(out.values()) for word, weight in out.items()}

def document_word_count(document, common_words):
    """
    Parameters:
        document (Document)
        common_words (list of str)
    Returns:
        A dictionnary:
        - keys: words inside the `document`, except the `common_words`
        - values: number of occurences of the word in the `document`
    Example:
        >>> document = CacmDocument(2382,"aujourd \n toto \n tata","il fait \n tyty","toto \n tata tyty")
        >>> common_words= ["aujourd", "il", "fait", "ca", "mot", "ok"]
        >>> document_statistics(document,common_words)
        { "toto":2, "tata":2, "tyty":2 }
    """
    word_list = get_word_list(document)
    return count_occurences(remove_stop_words(word_list, common_words))

def count_occurences(word_list):
    """
    Parameter:
        word_list (list of str)
    Returns:
        A dictionnary:
        - keys : each word in the `word_list`
        - values : number of occurences of the word in the `word_list`
    Example:
        >>> statistics(["toto", "tata", "tyty", "toto", "toto", "tata"]) == DocStats({"toto":3,"tata":2,"tyty":1},9)
        True
    """
    out = {}
    for word in word_list:
        if word not in out.keys():
            out[word] = 1
        else:
            out[word] = out[word] + 1
    return DocStats(out, len(word_list))

def _punctuation_to_space(character):
    """
    Parameter:
        character (char)
    Returns:
        char: a space if `character` was a punctuation character, `character` otherwise
    Example:
        >>> _punctuation_to_space("-") == " "
        True
    """
    separators = string.punctuation
    if character in separators:
        return " "
    return character

def tokenize(line):
    """
    Parameter:
        line (str)
    Returns:
        a list a words without ponctuation or spaces
    Example:
        >>> tokenize("aujourd'hui (lundi) il fait beau -")
        ["aujourd", "hui", "lundi", "il", "fait", "beau"]
    """
    cleaned = ''.join([_punctuation_to_space(c) for c in list(line)])
    tokens = [token for token in cleaned.split(" ") if token not in string.whitespace]
    return tokens
def normalize(term):
    """
    Parameter:
        term (str)
    Returns:
        string: `term` converted to lowercase
    Example:
        >>> normalize("tEsT")
        test
    """
    return term.lower()

def remove_stop_words(word_list, common_words):
    """
    Parameters:
        word_list (list of str)
        common_words (list of str)
    Returns:
        list of str: all the words in `word_list` that do not belong to `common_words`
    Example:
        remove_stop_words([tata", "titi"], ["titi"]) returns ["tata"]
    """
    return [normalize(word) for word in word_list if word not in common_words]

def get_word_list(document):
    """
    Parameter:
        document (CacmDocument)
    Returns:
        list of str: all the words inside a document, without the punctation
    Example:
        >>> get_word_list(document) returns ["aujourd", "toto", "tata","il", "fait", "tyty","toto","tata","tyty"] == CacmDocument(2382,"aujourd \n toto \n tata","il fait \n tyty","toto \n tata tyty")
        True
    """
    word_list = []
    for line in document.get_full_text().split("\n"):
        word_list = word_list + tokenize(line)
    return word_list

def document_size(document):
    """
    Parameter:
        document (Document)
    Returns:
        int: the number of words in the document
    Example:
        >>> document_size(CacmDocument(2382,"aujourd \n toto \n tata","il fait \n tyty","toto \n tata tyty"))
        9
    """
    size = 0
    for word in get_word_list(document):
        size = size + 1
    return size
<commit_msg>Remove TODO.<commit_after>import string
import math
from enum import Enum

class Weighting(Enum):
    TermFrequency = 1,
    LogTermFrequency = 2,
    Tf_Idf = 3

class Index:
    def __init__(self, common_words, documents=None):
        self.__index = {}  # a dict mapping words to TermInfo
        self.__stats = {}  # a dict mapping doc IDs to DocStats
        self.common_words = common_words
        self.__nb_documents = 0
        if documents is not None:
            for doc in documents:
                self.add_document(doc)

    def get_words_by_doc_id(self, doc_id):
        return self.__stats[doc_id].frequency.keys()

    def add_document(self, document):
        """
        Parameters:
            document : a document (must respond to `doc_id` and `get_full_text`).

            Document IDs must be unique in the index.
        Raises:
            ValueError: when trying to insert a document whose ID already exists in the index
        """
        stats = document_word_count(document, self.common_words)
        if document.doc_id in self.__stats:
            raise ValueError("Document ID {0} is already present in this index".format(document.doc_id))
        for word, count in stats.frequency.items():
            assert(count > 0)
            if word not in self.__index:
                self.__index[word] = TermInfo()
            self.__index[word].add_document(document.doc_id, count)
        self.__stats[document.doc_id] = stats
        self.__nb_documents += 1

    def get_word_count(self, word):
        """
        Returns:
            the number of occurences of the given word in the collection
        """
        if word in self.__index:
            return self.__index[word].count
        return 0

    def get_nb_docs_with_word(self, word):
        if word not in self.__index:
            return 0
        return self.__index[word].nb_documents

    @property
    def words(self):
        """
        Returns:
            list of str: the words in this index dictionnary (e.g. the indexed keywords)
        """
        return self.__index.keys()

    @property
    def doc_ids(self):
        """
        Returns:
            list of int: a list of the IDs of the documents indexed in this index
        """
        return self.__stats.keys()

    def get_weights(self, doc_id, weighting_method, corpus_index=None):
        """
        Parameter:
            doc_id (int): a document ID. This document must be present in the index.
            weighting_method (Weighting): the method used to compute the weight of each term in the document
            corpus_index (Index): used only for the method Tf_Idf, the index for the corpus (not of the request). This parameter is ignored for other weighting methods.
        Returns:
            A dict mapping the words in the given document to their weights.
        """
        return self.__stats[doc_id].weights(weighting_method, corpus_index)

    @property
    def nb_documents(self):
        return self.__nb_documents

    def get_doc_ids_containing(self, word):
        """
        Parameter:
            word (str)
        Returns:
            list of int: a list of the IDs of documents containing the word (may be empty)
        """
        if word not in self.__index:
            return []
        return self.__index[word].docs.keys()

    def probability_rsv(self, request_index, doc_id):
        """
        Parameters:
            request_index (Index)
            doc_id (int)
        Returns:
          (float) The retrieval status value for the document (relative to the given request), under the PRP (probability ranking principe) model and the BIR (binary independance retrieval) hypothesis
        """
        intersect = set(request_index.words) & set(self.__stats[doc_id].words)
        if len(intersect) == 0:
            return None
        rsv = 0
        for word in intersect:
            dft = self.get_nb_docs_with_word(word)
            assert(dft >= 1)  # dft >= 1 by definition of intersect
            a = math.log10(self.nb_documents / dft)
            pr = 0.5
            b = math.log10(pr / (1 - pr))
            rsv += b + a
        return rsv

class TermInfo:
    """Various statistics about a word (relative to the entire collection)
    """
    def __init__(self):
        self.docs = {} # doc_id, freq
        self.count = 0

    def add_document(self, doc_id, count):
        if doc_id in self.docs:
            self.docs[doc_id] += count
        else:
            self.docs[doc_id] = count
        self.count += count

    @property
    def nb_documents(self):
        return len(self.docs)

class DocStats:
    """Various statistics about a document.
    """

    def __init__(self, frequency, nb_words):
        """
        Parameters:
            frequency (dict): a dictionary mapping words to their number of occurences
            nb_words (int): the number of words in the document.
        """
        self.frequency = frequency
        self.nb_words = nb_words

    def weights(self, weighting, index=None):
        """
        Returns:
            a dictionary mapping each word in the document to a weight
        """
        if weighting == Weighting.TermFrequency:
            return self.__term_frequency_weights()
        elif weighting == Weighting.LogTermFrequency:
            return self.__log_term_frequency_weights()
        elif weighting == Weighting.Tf_Idf:
            if index is None:
                raise ValueError("An index must be provided to compute the tf-idf weights")
            return  self.__tf_idf_weights(index)
        else:
            raise ValueError("Unsupported weighting method: {0}".format(weighting))

    @property
    def words(self):
        return self.frequency.keys()

    def __term_frequency_weights(self):
        """
        Returns:
            a dictionary mapping each word in the document to a tf weight
        """
        out = {}
        for word in self.frequency.keys():
            out[word] = self.frequency[word]
        # Normalization
        return {word: frequency / max(out.values()) for word, frequency in out.items()}

    def __log_term_frequency_weights(self):
        """
        Returns:
            a dictionary mapping each word in the document to a ltf weight
        """
        out = {}
        for word in self.frequency.keys():
            if self.frequency[word] > 0:
                out[word] = 1 + math.log10(self.frequency[word])
        # Normalization
        return {word: weight / max(out.values()) for word, weight in out.items()}

    def __tf_idf_weights(self, index):
        """
        Returns:
            a dictionary mapping each word in the document to a tf-idf weight
        """
        out = {}
        for word in self.frequency.keys():
            dft = index.get_nb_docs_with_word(word)
            if self.frequency[word] > 0 and dft > 0:
                out[word] = (1 + math.log10(self.frequency[word])) * math.log10(index.nb_documents / dft)
        # Normalization
        return {word: weight / max(out.values()) for word, weight in out.items()}

def document_word_count(document, common_words):
    """
    Parameters:
        document (Document)
        common_words (list of str)
    Returns:
        A dictionnary:
        - keys: words inside the `document`, except the `common_words`
        - values: number of occurences of the word in the `document`
    Example:
        >>> document = CacmDocument(2382,"aujourd \n toto \n tata","il fait \n tyty","toto \n tata tyty")
        >>> common_words= ["aujourd", "il", "fait", "ca", "mot", "ok"]
        >>> document_statistics(document,common_words)
        { "toto":2, "tata":2, "tyty":2 }
    """
    word_list = get_word_list(document)
    return count_occurences(remove_stop_words(word_list, common_words))

def count_occurences(word_list):
    """
    Parameter:
        word_list (list of str)
    Returns:
        A dictionnary:
        - keys : each word in the `word_list`
        - values : number of occurences of the word in the `word_list`
    Example:
        >>> statistics(["toto", "tata", "tyty", "toto", "toto", "tata"]) == DocStats({"toto":3,"tata":2,"tyty":1},9)
        True
    """
    out = {}
    for word in word_list:
        if word not in out.keys():
            out[word] = 1
        else:
            out[word] = out[word] + 1
    return DocStats(out, len(word_list))

def _punctuation_to_space(character):
    """
    Parameter:
        character (char)
    Returns:
        char: a space if `character` was a punctuation character, `character` otherwise
    Example:
        >>> _punctuation_to_space("-") == " "
        True
    """
    separators = string.punctuation
    if character in separators:
        return " "
    return character

def tokenize(line):
    """
    Parameter:
        line (str)
    Returns:
        a list a words without ponctuation or spaces
    Example:
        >>> tokenize("aujourd'hui (lundi) il fait beau -")
        ["aujourd", "hui", "lundi", "il", "fait", "beau"]
    """
    cleaned = ''.join([_punctuation_to_space(c) for c in list(line)])
    tokens = [token for token in cleaned.split(" ") if token not in string.whitespace]
    return tokens
def normalize(term):
    """
    Parameter:
        term (str)
    Returns:
        string: `term` converted to lowercase
    Example:
        >>> normalize("tEsT")
        test
    """
    return term.lower()

def remove_stop_words(word_list, common_words):
    """
    Parameters:
        word_list (list of str)
        common_words (list of str)
    Returns:
        list of str: all the words in `word_list` that do not belong to `common_words`
    Example:
        remove_stop_words([tata", "titi"], ["titi"]) returns ["tata"]
    """
    return [normalize(word) for word in word_list if word not in common_words]

def get_word_list(document):
    """
    Parameter:
        document (CacmDocument)
    Returns:
        list of str: all the words inside a document, without the punctation
    Example:
        >>> get_word_list(document) returns ["aujourd", "toto", "tata","il", "fait", "tyty","toto","tata","tyty"] == CacmDocument(2382,"aujourd \n toto \n tata","il fait \n tyty","toto \n tata tyty")
        True
    """
    word_list = []
    for line in document.get_full_text().split("\n"):
        word_list = word_list + tokenize(line)
    return word_list

def document_size(document):
    """
    Parameter:
        document (Document)
    Returns:
        int: the number of words in the document
    Example:
        >>> document_size(CacmDocument(2382,"aujourd \n toto \n tata","il fait \n tyty","toto \n tata tyty"))
        9
    """
    size = 0
    for word in get_word_list(document):
        size = size + 1
    return size
<|endoftext|>


<commit_before>#     Copyright 2015, Kay Hayen, mailto:kay.hayen@gmail.com
#
#     Part of "Nuitka", an optimizing Python compiler that is compatible and
#     integrates with CPython, but also works on its own.
#
#     Licensed under the Apache License, Version 2.0 (the "License");
#     you may not use this file except in compliance with the License.
#     You may obtain a copy of the License at
#
#        http://www.apache.org/licenses/LICENSE-2.0
#
#     Unless required by applicable law or agreed to in writing, software
#     distributed under the License is distributed on an "AS IS" BASIS,
#     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#     See the License for the specific language governing permissions and
#     limitations under the License.
#
""" Finalize the markups

Set flags on functions and classes to indicate if a locals dict is really
needed.

Set a flag on loops if they really need to catch Continue and Break exceptions
or if it can be more simple code.

Set a flag on return statements and functions that require the use of
"ReturnValue" exceptions, or if it can be more simple code.

Set a flag on re-raises of exceptions if they can be simple throws or if they
are in another context.

"""

from logging import warning

from nuitka import Options
from nuitka.importing import StandardLibrary
from nuitka.utils import Utils

from .FinalizeBase import FinalizationVisitorBase

def isWhiteListedImport(node):
    module = node.getParentModule()

    return StandardLibrary.isStandardLibraryPath(module.getFilename())

class FinalizeMarkups(FinalizationVisitorBase):
    def onEnterNode(self, node):
        # This has many different things it deals with, so there need to be a
        # lot of branches and statements, pylint: disable=R0912,R0915
        if node.isExpressionFunctionBody():
            if node.isUnoptimized():
                node.markAsLocalsDict()

        if node.needsLocalsDict():
            provider = node.getParentVariableProvider()

            if provider.isExpressionFunctionBody():
                provider.markAsLocalsDict()

        if node.isStatementBreakLoop():
            search = node

            # Search up to the containing loop.
            while not search.isStatementLoop():
                last_search = search
                search = search.getParent()

                if search.isStatementTryFinally() and \
                   last_search == search.getBlockTry():
                    search.markAsNeedsBreakHandling()

        if node.isStatementContinueLoop():
            search = node

            # Search up to the containing loop.
            while not search.isStatementLoop():
                last_search = search
                search = search.getParent()

                if search.isStatementTryFinally() and \
                   last_search == search.getBlockTry():
                    search.markAsNeedsContinueHandling()

        if Utils.python_version >= 300:
            if node.isExpressionYield() or node.isExpressionYieldFrom():
                search = node.getParent()

                while not search.isExpressionFunctionBody():
                    last_search = search
                    search = search.getParent()

                    if search.isStatementTryFinally() and \
                       last_search == search.getBlockTry() and \
                       search.needsExceptionPublish():
                        node.markAsExceptionPreserving()
                        break

                    if search.isStatementTryExcept() and \
                       search.getExceptionHandling() is last_search and \
                       search.needsExceptionPublish():
                        node.markAsExceptionPreserving()
                        break

        if node.isStatementReturn() or node.isStatementGeneratorReturn():
            search = node

            # Search up to the containing function, and check for a try/finally
            # containing the "return" statement.
            while not search.isExpressionFunctionBody():
                last_search = search
                search = search.getParent()

                if search.isStatementTryFinally():
                    if last_search == search.getBlockTry():
                        search.markAsNeedsReturnHandling(1)

                        provider = search.getParentVariableProvider()
                        if provider.isGenerator():
                            provider.markAsNeedsGeneratorReturnHandling(2)

                    if last_search == search.getBlockFinal():
                        if search.needsReturnHandling():
                            search.markAsNeedsReturnHandling(2)

            if search.isGenerator():
                search.markAsNeedsGeneratorReturnHandling(1)

        if node.isStatementTryExcept():
            if node.public_exc:
                parent_frame = node.getParentStatementsFrame()
                assert parent_frame, node

                parent_frame.markAsFrameExceptionPreserving()

        if node.isStatementTryFinally():
            if Utils.python_version >= 300 and node.public_exc:
                parent_frame = node.getParentStatementsFrame()

                if parent_frame is not None:
                    parent_frame.markAsFrameExceptionPreserving()

        if node.isExpressionBuiltinImport() and \
           not Options.getShallFollowExtra() and \
           not Options.getShallFollowExtraFilePatterns() and \
           not Options.shallFollowNoImports() and \
           not isWhiteListedImport(node):
            warning("""Unresolved '__import__' call at '%s' may require use \
of '--recurse-directory'.""" % (
                    node.getSourceReference().getAsString()
                )
            )

        if node.isExpressionFunctionCreation():
            if not node.getParent().isExpressionFunctionCall() or \
                   node.getParent().getFunction() is not node:
                node.getFunctionRef().getFunctionBody().markAsNeedsCreation()

        if node.isExpressionFunctionCall():
            node.getFunction().getFunctionRef().getFunctionBody().\
              markAsDirectlyCalled()

        if node.isExpressionFunctionRef():
            function_body = node.getFunctionBody()
            parent_module = function_body.getParentModule()

            node_module = node.getParentModule()
            if node_module is not parent_module:
                function_body.markAsCrossModuleUsed()

                node_module.addCrossUsedFunction(function_body)

        if node.isStatementAssignmentVariable():
            target_var = node.getTargetVariableRef().getVariable()
            assign_source = node.getAssignSource()

            if assign_source.isExpressionOperationBinary():
                left_arg = assign_source.getLeft()

                if left_arg.isExpressionVariableRef():
                    if assign_source.getLeft().getVariable().isModuleVariable():
                        assign_source.unmarkAsInplaceSuspect()
                    elif assign_source.getLeft().getVariable() is target_var:
                        if assign_source.isInplaceSuspect():
                            node.markAsInplaceSuspect()
<commit_msg>Enhanced error output for errors in finalization.<commit_after>#     Copyright 2015, Kay Hayen, mailto:kay.hayen@gmail.com
#
#     Part of "Nuitka", an optimizing Python compiler that is compatible and
#     integrates with CPython, but also works on its own.
#
#     Licensed under the Apache License, Version 2.0 (the "License");
#     you may not use this file except in compliance with the License.
#     You may obtain a copy of the License at
#
#        http://www.apache.org/licenses/LICENSE-2.0
#
#     Unless required by applicable law or agreed to in writing, software
#     distributed under the License is distributed on an "AS IS" BASIS,
#     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#     See the License for the specific language governing permissions and
#     limitations under the License.
#
""" Finalize the markups

Set flags on functions and classes to indicate if a locals dict is really
needed.

Set a flag on loops if they really need to catch Continue and Break exceptions
or if it can be more simple code.

Set a flag on return statements and functions that require the use of
"ReturnValue" exceptions, or if it can be more simple code.

Set a flag on re-raises of exceptions if they can be simple throws or if they
are in another context.

"""

from logging import warning

from nuitka import Options, Tracing
from nuitka.importing import StandardLibrary
from nuitka.utils import Utils

from .FinalizeBase import FinalizationVisitorBase

def isWhiteListedImport(node):
    module = node.getParentModule()

    return StandardLibrary.isStandardLibraryPath(module.getFilename())

class FinalizeMarkups(FinalizationVisitorBase):
    def onEnterNode(self, node):
        try:
            self._onEnterNode(node)
        except Exception:
            Tracing.printError(
                "Problem with %r at %s" % (
                    node,
                    node.getSourceReference().getAsString()
                )
            )
            raise

    def _onEnterNode(self, node):
        # This has many different things it deals with, so there need to be a
        # lot of branches and statements, pylint: disable=R0912,R0915

        # Also all self specific things have been done on the outside,
        # pylint: disable=R0201

        if node.isExpressionFunctionBody():
            if node.isUnoptimized():
                node.markAsLocalsDict()

        if node.needsLocalsDict():
            provider = node.getParentVariableProvider()

            if provider.isExpressionFunctionBody():
                provider.markAsLocalsDict()

        if node.isStatementBreakLoop():
            search = node

            # Search up to the containing loop.
            while not search.isStatementLoop():
                last_search = search
                search = search.getParent()

                if search.isStatementTryFinally() and \
                   last_search == search.getBlockTry():
                    search.markAsNeedsBreakHandling()

        if node.isStatementContinueLoop():
            search = node

            # Search up to the containing loop.
            while not search.isStatementLoop():
                last_search = search
                search = search.getParent()

                if search.isStatementTryFinally() and \
                   last_search == search.getBlockTry():
                    search.markAsNeedsContinueHandling()

        if Utils.python_version >= 300:
            if node.isExpressionYield() or node.isExpressionYieldFrom():
                search = node.getParent()

                while not search.isExpressionFunctionBody():
                    last_search = search
                    search = search.getParent()

                    if search.isStatementTryFinally() and \
                       last_search == search.getBlockTry() and \
                       search.needsExceptionPublish():
                        node.markAsExceptionPreserving()
                        break

                    if search.isStatementTryExcept() and \
                       search.getExceptionHandling() is last_search and \
                       search.needsExceptionPublish():
                        node.markAsExceptionPreserving()
                        break

        if node.isStatementReturn() or node.isStatementGeneratorReturn():
            search = node

            # Search up to the containing function, and check for a try/finally
            # containing the "return" statement.
            while not search.isExpressionFunctionBody():
                last_search = search
                search = search.getParent()

                if search.isStatementTryFinally():
                    if last_search == search.getBlockTry():
                        search.markAsNeedsReturnHandling(1)

                        provider = search.getParentVariableProvider()
                        if provider.isGenerator():
                            provider.markAsNeedsGeneratorReturnHandling(2)

                    if last_search == search.getBlockFinal():
                        if search.needsReturnHandling():
                            search.markAsNeedsReturnHandling(2)

            if search.isGenerator():
                search.markAsNeedsGeneratorReturnHandling(1)

        if node.isStatementTryExcept():
            if node.public_exc:
                parent_frame = node.getParentStatementsFrame()
                assert parent_frame, node

                parent_frame.markAsFrameExceptionPreserving()

        if node.isStatementTryFinally():
            if Utils.python_version >= 300 and node.public_exc:
                parent_frame = node.getParentStatementsFrame()

                if parent_frame is not None:
                    parent_frame.markAsFrameExceptionPreserving()

        if node.isExpressionBuiltinImport() and \
           not Options.getShallFollowExtra() and \
           not Options.getShallFollowExtraFilePatterns() and \
           not Options.shallFollowNoImports() and \
           not isWhiteListedImport(node):
            warning("""Unresolved '__import__' call at '%s' may require use \
of '--recurse-directory'.""" % (
                    node.getSourceReference().getAsString()
                )
            )

        if node.isExpressionFunctionCreation():
            if not node.getParent().isExpressionFunctionCall() or \
                   node.getParent().getFunction() is not node:
                node.getFunctionRef().getFunctionBody().markAsNeedsCreation()

        if node.isExpressionFunctionCall():
            node.getFunction().getFunctionRef().getFunctionBody().\
              markAsDirectlyCalled()

        if node.isExpressionFunctionRef():
            function_body = node.getFunctionBody()
            parent_module = function_body.getParentModule()

            node_module = node.getParentModule()
            if node_module is not parent_module:
                function_body.markAsCrossModuleUsed()

                node_module.addCrossUsedFunction(function_body)

        if node.isStatementAssignmentVariable():
            target_var = node.getTargetVariableRef().getVariable()
            assign_source = node.getAssignSource()

            if assign_source.isExpressionOperationBinary():
                left_arg = assign_source.getLeft()

                if left_arg.isExpressionVariableRef():
                    if assign_source.getLeft().getVariable().isModuleVariable():
                        assign_source.unmarkAsInplaceSuspect()
                    elif assign_source.getLeft().getVariable() is target_var:
                        if assign_source.isInplaceSuspect():
                            node.markAsInplaceSuspect()
<|endoftext|>


<commit_before># Copyright 2020 The Bazel Authors. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#    http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""Exported builtins symbols that are not specific to OSS Bazel."""

load("@_builtins//:common/cc/cc_import.bzl", "cc_import")
load("@_builtins//:common/cc/cc_binary_wrapper.bzl", "cc_binary")
load("@_builtins//:common/cc/cc_test_wrapper.bzl", cc_test = "cc_test_wrapper")
load("@_builtins//:common/cc/experimental_cc_shared_library.bzl", "CcSharedLibraryInfo", "cc_shared_library", "cc_shared_library_permissions")
load("@_builtins//:common/objc/objc_import.bzl", "objc_import")
load("@_builtins//:common/objc/objc_library.bzl", "objc_library")
load("@_builtins//:common/objc/compilation_support.bzl", "compilation_support")
load("@_builtins//:common/objc/linking_support.bzl", "linking_support")
load("@_builtins//:common/proto/proto_common.bzl", "proto_common_do_not_use")
load("@_builtins//:common/proto/proto_library.bzl", "proto_library")
load("@_builtins//:common/proto/proto_lang_toolchain_wrapper.bzl", "proto_lang_toolchain")
load("@_builtins//:common/python/py_runtime_macro.bzl", "py_runtime")
load("@_builtins//:common/python/py_internal.bzl", "py_internal")
load("@_builtins//:common/python/providers.bzl", "PyInfo", "PyRuntimeInfo")
load("@_builtins//:common/java/proto/java_lite_proto_library.bzl", "java_lite_proto_library")
load("@_builtins//:common/cc/cc_library.bzl", "cc_library")

exported_toplevels = {
    # This dummy symbol is not part of the public API; it is only used to test
    # that builtins injection is working properly. Its built-in value is
    # "original value".
    "_builtins_dummy": "overridden value",
    "CcSharedLibraryInfo": CcSharedLibraryInfo,
    "proto_common_do_not_use": proto_common_do_not_use,
    "-PyRuntimeInfo": PyRuntimeInfo,
    "-PyInfo": PyInfo,
    "py_internal": py_internal,
}

# A list of Starlarkified native rules.
#
# * leading `+` means the Starlark rule is used by default, but can be overridden
#   on the Bazel command line
# * no leading symbol means the Starlark rule is used and can't be overridden
# * leading `-` means the Starlark rule exists, but is not used by default
exported_rules = {
    "+cc_import": cc_import,
    "java_lite_proto_library": java_lite_proto_library,
    "objc_import": objc_import,
    "objc_library": objc_library,
    "proto_library": proto_library,
    "+cc_shared_library": cc_shared_library,
    "+cc_shared_library_permissions": cc_shared_library_permissions,
    "+cc_binary": cc_binary,
    "+cc_test": cc_test,
    "+cc_library": cc_library,
    "proto_lang_toolchain": proto_lang_toolchain,
    "-py_runtime": py_runtime,
}

# A list of Starlark functions callable from native rules implementation.
exported_to_java = {
    "register_compile_and_archive_actions_for_j2objc": compilation_support.register_compile_and_archive_actions_for_j2objc,
    "proto_common_compile": proto_common_do_not_use.compile,
    "proto_common_declare_generated_files": proto_common_do_not_use.declare_generated_files,
    "proto_common_experimental_should_generate_code": proto_common_do_not_use.experimental_should_generate_code,
    "proto_common_experimental_filter_sources": proto_common_do_not_use.experimental_filter_sources,
    "link_multi_arch_static_library": linking_support.link_multi_arch_static_library,
}
<commit_msg>Enable Starlark `py_runtime`.<commit_after># Copyright 2020 The Bazel Authors. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#    http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""Exported builtins symbols that are not specific to OSS Bazel."""

load("@_builtins//:common/cc/cc_import.bzl", "cc_import")
load("@_builtins//:common/cc/cc_binary_wrapper.bzl", "cc_binary")
load("@_builtins//:common/cc/cc_test_wrapper.bzl", cc_test = "cc_test_wrapper")
load("@_builtins//:common/cc/experimental_cc_shared_library.bzl", "CcSharedLibraryInfo", "cc_shared_library", "cc_shared_library_permissions")
load("@_builtins//:common/objc/objc_import.bzl", "objc_import")
load("@_builtins//:common/objc/objc_library.bzl", "objc_library")
load("@_builtins//:common/objc/compilation_support.bzl", "compilation_support")
load("@_builtins//:common/objc/linking_support.bzl", "linking_support")
load("@_builtins//:common/proto/proto_common.bzl", "proto_common_do_not_use")
load("@_builtins//:common/proto/proto_library.bzl", "proto_library")
load("@_builtins//:common/proto/proto_lang_toolchain_wrapper.bzl", "proto_lang_toolchain")
load("@_builtins//:common/python/py_runtime_macro.bzl", "py_runtime")
load("@_builtins//:common/python/py_internal.bzl", "py_internal")
load("@_builtins//:common/python/providers.bzl", "PyInfo", "PyRuntimeInfo")
load("@_builtins//:common/java/proto/java_lite_proto_library.bzl", "java_lite_proto_library")
load("@_builtins//:common/cc/cc_library.bzl", "cc_library")

exported_toplevels = {
    # This dummy symbol is not part of the public API; it is only used to test
    # that builtins injection is working properly. Its built-in value is
    # "original value".
    "_builtins_dummy": "overridden value",
    "CcSharedLibraryInfo": CcSharedLibraryInfo,
    "proto_common_do_not_use": proto_common_do_not_use,
    "-PyRuntimeInfo": PyRuntimeInfo,
    "-PyInfo": PyInfo,
    "py_internal": py_internal,
}

# A list of Starlarkified native rules.
#
# * leading `+` means the Starlark rule is used by default, but can be overridden
#   on the Bazel command line
# * no leading symbol means the Starlark rule is used and can't be overridden
# * leading `-` means the Starlark rule exists, but is not used by default
exported_rules = {
    "+cc_import": cc_import,
    "java_lite_proto_library": java_lite_proto_library,
    "objc_import": objc_import,
    "objc_library": objc_library,
    "proto_library": proto_library,
    "+cc_shared_library": cc_shared_library,
    "+cc_shared_library_permissions": cc_shared_library_permissions,
    "+cc_binary": cc_binary,
    "+cc_test": cc_test,
    "+cc_library": cc_library,
    "proto_lang_toolchain": proto_lang_toolchain,
    "+py_runtime": py_runtime,
}

# A list of Starlark functions callable from native rules implementation.
exported_to_java = {
    "register_compile_and_archive_actions_for_j2objc": compilation_support.register_compile_and_archive_actions_for_j2objc,
    "proto_common_compile": proto_common_do_not_use.compile,
    "proto_common_declare_generated_files": proto_common_do_not_use.declare_generated_files,
    "proto_common_experimental_should_generate_code": proto_common_do_not_use.experimental_should_generate_code,
    "proto_common_experimental_filter_sources": proto_common_do_not_use.experimental_filter_sources,
    "link_multi_arch_static_library": linking_support.link_multi_arch_static_library,
}
<|endoftext|>


<commit_before>from __future__ import print_function

import json
import optparse
import sqlite3

version = "0.2.0"

def create_tables(conn):
    cur = conn.cursor()
    cur.execute('PRAGMA foreign_keys = ON')
    cur.execute('''CREATE TABLE gene_family (
        gene_family_id INTEGER PRIMARY KEY,
        gene_tree VARCHAR NOT NULL)''')

    cur.execute('''CREATE TABLE gene (
        gene_id VARCHAR PRIMARY KEY NOT NULL,
        gene_symbol VARCHAR,
        gene_json VARCHAR NOT NULL)''')
    cur.execute('CREATE INDEX gene_symbol_index ON gene (gene_symbol)')

    cur.execute('''CREATE TABLE transcript (
        transcript_id VARCHAR PRIMARY KEY NOT NULL,
        protein_id VARCHAR UNIQUE,
        gene_id VARCHAR NOT NULL REFERENCES gene(gene_id))''')

    cur.execute('''CREATE TABLE gene_family_member (
        gene_family_id INTEGER NOT NULL REFERENCES gene_family(gene_family_id),
        protein_id VARCHAR KEY NOT NULL REFERENCES transcript(protein_id),
        alignment VARCHAR NOT NULL,
        PRIMARY KEY (gene_family_id, protein_id))''')
    conn.commit()

def cigar_to_db(conn, i, fname):
    cur = conn.cursor()
    with open(fname) as f:
        for element in f.readlines():
            seq_id, cigar = element.rstrip('\n').split('\t')
            # Trim seq_id by removing everything from the first underscore
            seq_id.split('_', 1)[0]

            cur.execute('SELECT transcript_id, protein_id FROM transcript WHERE transcript_id=? OR protein_id=?',
                        (seq_id, seq_id))
            results = cur.fetchall()
            if len(results) == 0:
                raise Exception("Sequence id '%s' could not be found among the transcript and protein ids" % seq_id)
            elif len(results) > 1:
                raise Exception("Searching sequence id '%s' among the transcript and protein ids returned multiple results" % seq_id)
            transcript_id, protein_id = results[0]
            if protein_id is None:
                print("Skipping transcript '%s' with no protein id" % transcript_id)
            else:
                cur.execute('INSERT INTO gene_family_member (gene_family_id, protein_id, alignment) VALUES (?, ?, ?)',
                            (i, protein_id, cigar))
                conn.commit()

def newicktree_to_db(conn, i, fname):
    with open(fname) as f:
        tree = f.read().replace('\n', '')

    cur = conn.cursor()
    cur.execute('INSERT INTO gene_family (gene_family_id, gene_tree) VALUES (?, ?)',
                (i, tree))
    conn.commit()

def gene_json_to_db(conn, fname):
    with open(fname) as f:
        all_genes_dict = json.load(f)

    cur = conn.cursor()
    for gene_dict in all_genes_dict.values():
        gene_id = gene_dict['id']
        gene_symbol = gene_dict.get('display_name', None)
        cur.execute("INSERT INTO gene (gene_id, gene_symbol, gene_json) VALUES (?, ?, ?)",
                    (gene_id, gene_symbol, json.dumps(gene_dict)))

        if "Transcript" in gene_dict:
            for transcript in gene_dict["Transcript"]:
                transcript_id = transcript['id']
                if 'Translation' in transcript and 'id' in transcript['Translation']:
                    protein_id = transcript["Translation"]["id"]
                else:
                    protein_id = None
                cur.execute("INSERT INTO transcript (transcript_id, protein_id, gene_id) VALUES (?, ?, ?)",
                            (transcript_id, protein_id, gene_id))
    conn.commit()

def __main__():
    parser = optparse.OptionParser()
    parser.add_option('-t', '--tree', action='append', help='Gene tree files')
    parser.add_option('-c', '--cigar', action='append', help='CIGAR alignments of CDS files in tabular format')
    parser.add_option('-g', '--gene', help='Gene features file in JSON format')
    parser.add_option('-o', '--output', help='Path of the output file')
    options, args = parser.parse_args()
    if args:
        raise Exception('Use options to provide inputs')

    conn = sqlite3.connect(options.output)
    create_tables(conn)

    gene_json_to_db(conn, options.gene)

    for i, (tree, cigar) in enumerate(zip(options.tree, options.cigar), start=1):
        newicktree_to_db(conn, i, tree)
        cigar_to_db(conn, i, cigar)

if __name__ == '__main__':
    __main__()
<commit_msg>Fix stupid error<commit_after>from __future__ import print_function

import json
import optparse
import sqlite3

version = "0.2.0"

def create_tables(conn):
    cur = conn.cursor()
    cur.execute('PRAGMA foreign_keys = ON')
    cur.execute('''CREATE TABLE gene_family (
        gene_family_id INTEGER PRIMARY KEY,
        gene_tree VARCHAR NOT NULL)''')

    cur.execute('''CREATE TABLE gene (
        gene_id VARCHAR PRIMARY KEY NOT NULL,
        gene_symbol VARCHAR,
        gene_json VARCHAR NOT NULL)''')
    cur.execute('CREATE INDEX gene_symbol_index ON gene (gene_symbol)')

    cur.execute('''CREATE TABLE transcript (
        transcript_id VARCHAR PRIMARY KEY NOT NULL,
        protein_id VARCHAR UNIQUE,
        gene_id VARCHAR NOT NULL REFERENCES gene(gene_id))''')

    cur.execute('''CREATE TABLE gene_family_member (
        gene_family_id INTEGER NOT NULL REFERENCES gene_family(gene_family_id),
        protein_id VARCHAR KEY NOT NULL REFERENCES transcript(protein_id),
        alignment VARCHAR NOT NULL,
        PRIMARY KEY (gene_family_id, protein_id))''')
    conn.commit()

def cigar_to_db(conn, i, fname):
    cur = conn.cursor()
    with open(fname) as f:
        for element in f.readlines():
            seq_id, cigar = element.rstrip('\n').split('\t')
            # Trim seq_id by removing everything from the first underscore
            seq_id = seq_id.split('_', 1)[0]

            cur.execute('SELECT transcript_id, protein_id FROM transcript WHERE transcript_id=? OR protein_id=?',
                        (seq_id, seq_id))
            results = cur.fetchall()
            if len(results) == 0:
                raise Exception("Sequence id '%s' could not be found among the transcript and protein ids" % seq_id)
            elif len(results) > 1:
                raise Exception("Searching sequence id '%s' among the transcript and protein ids returned multiple results" % seq_id)
            transcript_id, protein_id = results[0]
            if protein_id is None:
                print("Skipping transcript '%s' with no protein id" % transcript_id)
            else:
                cur.execute('INSERT INTO gene_family_member (gene_family_id, protein_id, alignment) VALUES (?, ?, ?)',
                            (i, protein_id, cigar))
                conn.commit()

def newicktree_to_db(conn, i, fname):
    with open(fname) as f:
        tree = f.read().replace('\n', '')

    cur = conn.cursor()
    cur.execute('INSERT INTO gene_family (gene_family_id, gene_tree) VALUES (?, ?)',
                (i, tree))
    conn.commit()

def gene_json_to_db(conn, fname):
    with open(fname) as f:
        all_genes_dict = json.load(f)

    cur = conn.cursor()
    for gene_dict in all_genes_dict.values():
        gene_id = gene_dict['id']
        gene_symbol = gene_dict.get('display_name', None)
        cur.execute("INSERT INTO gene (gene_id, gene_symbol, gene_json) VALUES (?, ?, ?)",
                    (gene_id, gene_symbol, json.dumps(gene_dict)))

        if "Transcript" in gene_dict:
            for transcript in gene_dict["Transcript"]:
                transcript_id = transcript['id']
                if 'Translation' in transcript and 'id' in transcript['Translation']:
                    protein_id = transcript["Translation"]["id"]
                else:
                    protein_id = None
                cur.execute("INSERT INTO transcript (transcript_id, protein_id, gene_id) VALUES (?, ?, ?)",
                            (transcript_id, protein_id, gene_id))
    conn.commit()

def __main__():
    parser = optparse.OptionParser()
    parser.add_option('-t', '--tree', action='append', help='Gene tree files')
    parser.add_option('-c', '--cigar', action='append', help='CIGAR alignments of CDS files in tabular format')
    parser.add_option('-g', '--gene', help='Gene features file in JSON format')
    parser.add_option('-o', '--output', help='Path of the output file')
    options, args = parser.parse_args()
    if args:
        raise Exception('Use options to provide inputs')

    conn = sqlite3.connect(options.output)
    create_tables(conn)

    gene_json_to_db(conn, options.gene)

    for i, (tree, cigar) in enumerate(zip(options.tree, options.cigar), start=1):
        newicktree_to_db(conn, i, tree)
        cigar_to_db(conn, i, cigar)

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


<commit_before>import pytest
import copy
import mock

from website.models import ApiOAuth2Application, User
from website.util import api_v2_url
from website.util import sanitize
from tests.base import ApiTestCase
from osf_tests.factories import ApiOAuth2ApplicationFactory, AuthUserFactory

def _get_application_detail_route(app):
    path = 'applications/{}/'.format(app.client_id)
    return api_v2_url(path, base_route='/')

def _get_application_list_url():
    path = 'applications/'
    return api_v2_url(path, base_route='/')

@pytest.fixture()
def user():
    return AuthUserFactory()

@pytest.mark.django_db
class TestApplicationList:

    @pytest.fixture()
    def user_app(self, user):
        return ApiOAuth2ApplicationFactory(owner=user)

    @pytest.fixture()
    def url(self):
        return _get_application_list_url()

    @pytest.fixture()
    def sample_data(self):
        return {
            'data': {
                'type': 'applications',
                'attributes': {
                    'name': 'A shiny new application',
                    'description': 'It\'s really quite shiny',
                    'home_url': 'http://osf.io',
                    'callback_url': 'https://cos.io',
                    'owner': 'Value discarded',
                    'client_id': 'Value discarded',
                    'client_secret': 'Value discarded',
                }
            }
        }

    def test_user_should_see_only_their_applications(self, app, user, user_app, url):
        res = app.get(url, auth=user.auth)
        assert len(res.json['data']) == len([user_app])

    def test_other_user_should_see_only_their_applications(self, app, url):
        other_user = AuthUserFactory()
        other_user_apps = [ApiOAuth2ApplicationFactory(owner=other_user) for i in xrange(2)]

        res = app.get(url, auth=other_user.auth)
        assert len(res.json['data']) == len(other_user_apps)

    @mock.patch('framework.auth.cas.CasClient.revoke_application_tokens')
    def test_deleting_application_should_hide_it_from_api_list(self, mock_method, app, user, user_app, url):
        mock_method.return_value(True)
        api_app = user_app
        delete_url = _get_application_detail_route(api_app)

        res = app.delete(delete_url, auth=user.auth)
        assert res.status_code == 204

        res = app.get(url, auth=user.auth)
        assert res.status_code == 200
        assert len(res.json['data']) == ApiOAuth2Application.objects.count() - 1

    def test_created_applications_are_tied_to_request_user_with_data_specified(self, app, user, url, sample_data):
        res = app.post_json_api(url, sample_data, auth=user.auth, expect_errors=True)
        assert res.status_code == 201

        assert res.json['data']['attributes']['owner'] == user._id
        # Some fields aren't writable; make sure user can't set these
        assert res.json['data']['attributes']['client_id'] != sample_data['data']['attributes']['client_id']
        assert res.json['data']['attributes']['client_secret'] != sample_data['data']['attributes']['client_secret']

    def test_creating_application_fails_if_callbackurl_fails_validation(self, app, user, url, sample_data):
        data = copy.copy(sample_data)
        data['data']['attributes']['callback_url'] = 'itunes:///invalid_url_of_doom'
        res = app.post_json_api(url, data,
                            auth=user.auth, expect_errors=True)
        assert res.status_code == 400

    def test_field_content_is_sanitized_upon_submission(self, app, user, url, sample_data):
        bad_text = 'User_text'
        cleaned_text = sanitize.strip_html(bad_text)

        payload = copy.copy(sample_data)
        payload['data']['attributes']['name'] = bad_text
        payload['data']['attributes']['description'] = bad_text

        res = app.post_json_api(url, payload, auth=user.auth)
        assert res.status_code == 201
        assert res.json['data']['attributes']['name'] == cleaned_text

    def test_created_applications_show_up_in_api_list(self, app, user, user_app, url, sample_data):
        res = app.post_json_api(url, sample_data, auth=user.auth)
        assert res.status_code == 201

        res = app.get(url, auth=user.auth)
        assert len(res.json['data']) == ApiOAuth2Application.objects.count()

    def test_returns_401_when_not_logged_in(self, app, url):
        res = app.get(url, expect_errors=True)
        assert res.status_code == 401
<commit_msg>Improve test in test_application_list.py<commit_after>import pytest
import copy
import mock

from website.models import ApiOAuth2Application, User
from website.util import api_v2_url
from website.util import sanitize
from tests.base import ApiTestCase
from osf_tests.factories import ApiOAuth2ApplicationFactory, AuthUserFactory

def _get_application_detail_route(app):
    path = 'applications/{}/'.format(app.client_id)
    return api_v2_url(path, base_route='/')

def _get_application_list_url():
    path = 'applications/'
    return api_v2_url(path, base_route='/')

@pytest.fixture()
def user():
    return AuthUserFactory()

@pytest.mark.django_db
class TestApplicationList:

    @pytest.fixture()
    def user_app(self, user):
        return ApiOAuth2ApplicationFactory(owner=user)

    @pytest.fixture()
    def url(self):
        return _get_application_list_url()

    @pytest.fixture()
    def sample_data(self):
        return {
            'data': {
                'type': 'applications',
                'attributes': {
                    'name': 'A shiny new application',
                    'description': 'It\'s really quite shiny',
                    'home_url': 'http://osf.io',
                    'callback_url': 'https://cos.io',
                    'owner': 'Value discarded',
                    'client_id': 'Value discarded',
                    'client_secret': 'Value discarded',
                }
            }
        }

    def test_user_should_see_only_their_applications(self, app, user, user_app, url):
        res = app.get(url, auth=user.auth)
        assert len(res.json['data']) == ApiOAuth2Application.objects.filter(owner=user).count()

    def test_other_user_should_see_only_their_applications(self, app, url):
        other_user = AuthUserFactory()
        other_user_apps = [ApiOAuth2ApplicationFactory(owner=other_user) for i in xrange(2)]

        res = app.get(url, auth=other_user.auth)
        assert len(res.json['data']) == len(other_user_apps)

    @mock.patch('framework.auth.cas.CasClient.revoke_application_tokens')
    def test_deleting_application_should_hide_it_from_api_list(self, mock_method, app, user, user_app, url):
        mock_method.return_value(True)
        api_app = user_app
        delete_url = _get_application_detail_route(api_app)

        res = app.delete(delete_url, auth=user.auth)
        assert res.status_code == 204

        res = app.get(url, auth=user.auth)
        assert res.status_code == 200
        assert len(res.json['data']) == ApiOAuth2Application.objects.count() - 1

    def test_created_applications_are_tied_to_request_user_with_data_specified(self, app, user, url, sample_data):
        res = app.post_json_api(url, sample_data, auth=user.auth, expect_errors=True)
        assert res.status_code == 201

        assert res.json['data']['attributes']['owner'] == user._id
        # Some fields aren't writable; make sure user can't set these
        assert res.json['data']['attributes']['client_id'] != sample_data['data']['attributes']['client_id']
        assert res.json['data']['attributes']['client_secret'] != sample_data['data']['attributes']['client_secret']

    def test_creating_application_fails_if_callbackurl_fails_validation(self, app, user, url, sample_data):
        data = copy.copy(sample_data)
        data['data']['attributes']['callback_url'] = 'itunes:///invalid_url_of_doom'
        res = app.post_json_api(url, data,
                            auth=user.auth, expect_errors=True)
        assert res.status_code == 400

    def test_field_content_is_sanitized_upon_submission(self, app, user, url, sample_data):
        bad_text = 'User_text'
        cleaned_text = sanitize.strip_html(bad_text)

        payload = copy.copy(sample_data)
        payload['data']['attributes']['name'] = bad_text
        payload['data']['attributes']['description'] = bad_text

        res = app.post_json_api(url, payload, auth=user.auth)
        assert res.status_code == 201
        assert res.json['data']['attributes']['name'] == cleaned_text

    def test_created_applications_show_up_in_api_list(self, app, user, user_app, url, sample_data):
        res = app.post_json_api(url, sample_data, auth=user.auth)
        assert res.status_code == 201

        res = app.get(url, auth=user.auth)
        assert len(res.json['data']) == ApiOAuth2Application.objects.count()

    def test_returns_401_when_not_logged_in(self, app, url):
        res = app.get(url, expect_errors=True)
        assert res.status_code == 401
<|endoftext|>


<commit_before>"""Main implementation."""

import argparse
import os

from livereload import Server

from . import __version__
from .ignore import IgnoreHandler
from .sphinx import SPHINX_BUILD_OPTIONS, SphinxBuilder
from .utils import find_free_port
from .watcher import LivereloadWatchdogWatcher

def get_build_args(args):
    build_args = []
    for arg, meta in SPHINX_BUILD_OPTIONS:
        val = getattr(args, arg)
        if not val:
            continue
        opt = "-{0}".format(arg)
        if meta is None:
            build_args.extend([opt] * val)
        else:
            for v in val:
                build_args.extend([opt, v])

    build_args.extend([os.path.realpath(args.sourcedir), os.path.realpath(args.outdir)])
    build_args.extend(args.filenames)
    return build_args

def get_ignore_handler(args):
    """Create an IgnoreHandler from CLI arguments."""
    regular = args.ignore[:]
    regular.append(os.path.realpath(args.outdir))  # output directory
    if args.w:  # Logfile
        regular.append(os.path.realpath(args.w[0]))
    if args.d:  # Doctrees
        regular.append(os.path.realpath(args.d[0]))

    regex_based = args.re_ignore + [r"\.pyc$"]  # ignore .pyc files

    return IgnoreHandler(regular, regex_based)

def get_parser():
    """Get the application's argument parser.

    Note: this also handles SPHINX_BUILD_OPTIONS, which later get forwarded to
    sphinx-build as-is.
    """
    parser = argparse.ArgumentParser()
    parser.add_argument("-p", "--port", type=int, default=8000)
    parser.add_argument("-H", "--host", type=str, default="127.0.0.1")
    parser.add_argument("-r", "--re-ignore", action="append", default=[])
    parser.add_argument("-i", "--ignore", action="append", default=[])
    parser.add_argument(
        "--poll", dest="use_polling", action="store_true", default=False
    )
    parser.add_argument(
        "--no-initial", dest="initial_build", action="store_false", default=True
    )
    parser.add_argument(
        "-B", "--open-browser", dest="openbrowser", action="store_true", default=False
    )
    parser.add_argument("-s", "--delay", dest="delay", type=int, default=5)
    parser.add_argument(
        "-z",
        "--watch",
        action="append",
        metavar="DIR",
        default=[],
        help="Specify additional directories to watch. May be used multiple times.",
        dest="additional_watched_dirs",
    )
    parser.add_argument(
        "--version", action="version", version="sphinx-autobuild {}".format(__version__)
    )

    for opt, meta in SPHINX_BUILD_OPTIONS:
        if meta is None:
            parser.add_argument(
                "-{0}".format(opt), action="count", help="See `sphinx-build -h`"
            )
        else:
            parser.add_argument(
                "-{0}".format(opt),
                action="append",
                metavar=meta,
                help="See `sphinx-build -h`",
            )

    parser.add_argument("sourcedir")
    parser.add_argument("outdir")
    parser.add_argument("filenames", nargs="*", help="See `sphinx-build -h`")
    return parser

def main():
    """Actual application logic."""
    parser = get_parser()
    args = parser.parse_args()

    srcdir = os.path.realpath(args.sourcedir)
    outdir = os.path.realpath(args.outdir)
    if not os.path.exists(outdir):
        os.makedirs(outdir)

    ignore_handler = get_ignore_handler(args)
    build_args = get_build_args(args)

    builder = SphinxBuilder(build_args, ignore_handler)
    server = Server(watcher=LivereloadWatchdogWatcher(use_polling=args.use_polling),)

    server.watch(srcdir, builder)
    for dirpath in args.additional_watched_dirs:
        dirpath = os.path.realpath(dirpath)
        server.watch(dirpath, builder)
    server.watch(outdir)

    if args.initial_build:
        builder.build()

    # Find the free port
    portn = args.port or find_free_port()
    if args.openbrowser is True:
        server.serve(port=portn, host=args.host, root=outdir, open_url_delay=args.delay)
    else:
        server.serve(port=portn, host=args.host, root=outdir)
<commit_msg>Factor out logic for creating the watcher<commit_after>"""Main implementation."""

import argparse
import os

from livereload import Server

from . import __version__
from .ignore import IgnoreHandler
from .sphinx import SPHINX_BUILD_OPTIONS, SphinxBuilder
from .utils import find_free_port
from .watcher import LivereloadWatchdogWatcher

def get_build_args(args):
    build_args = []
    for arg, meta in SPHINX_BUILD_OPTIONS:
        val = getattr(args, arg)
        if not val:
            continue
        opt = "-{0}".format(arg)
        if meta is None:
            build_args.extend([opt] * val)
        else:
            for v in val:
                build_args.extend([opt, v])

    build_args.extend([os.path.realpath(args.sourcedir), os.path.realpath(args.outdir)])
    build_args.extend(args.filenames)
    return build_args

def get_ignore_handler(args):
    """Create an IgnoreHandler from CLI arguments."""
    regular = args.ignore[:]
    regular.append(os.path.realpath(args.outdir))  # output directory
    if args.w:  # Logfile
        regular.append(os.path.realpath(args.w[0]))
    if args.d:  # Doctrees
        regular.append(os.path.realpath(args.d[0]))

    regex_based = args.re_ignore + [r"\.pyc$"]  # ignore .pyc files

    return IgnoreHandler(regular, regex_based)

def get_watcher(args):
    return LivereloadWatchdogWatcher(use_polling=args.use_polling)

def get_parser():
    """Get the application's argument parser.

    Note: this also handles SPHINX_BUILD_OPTIONS, which later get forwarded to
    sphinx-build as-is.
    """
    parser = argparse.ArgumentParser()
    parser.add_argument("-p", "--port", type=int, default=8000)
    parser.add_argument("-H", "--host", type=str, default="127.0.0.1")
    parser.add_argument("-r", "--re-ignore", action="append", default=[])
    parser.add_argument("-i", "--ignore", action="append", default=[])
    parser.add_argument(
        "--poll", dest="use_polling", action="store_true", default=False
    )
    parser.add_argument(
        "--no-initial", dest="initial_build", action="store_false", default=True
    )
    parser.add_argument(
        "-B", "--open-browser", dest="openbrowser", action="store_true", default=False
    )
    parser.add_argument("-s", "--delay", dest="delay", type=int, default=5)
    parser.add_argument(
        "-z",
        "--watch",
        action="append",
        metavar="DIR",
        default=[],
        help="Specify additional directories to watch. May be used multiple times.",
        dest="additional_watched_dirs",
    )
    parser.add_argument(
        "--version", action="version", version="sphinx-autobuild {}".format(__version__)
    )

    for opt, meta in SPHINX_BUILD_OPTIONS:
        if meta is None:
            parser.add_argument(
                "-{0}".format(opt), action="count", help="See `sphinx-build -h`"
            )
        else:
            parser.add_argument(
                "-{0}".format(opt),
                action="append",
                metavar=meta,
                help="See `sphinx-build -h`",
            )

    parser.add_argument("sourcedir")
    parser.add_argument("outdir")
    parser.add_argument("filenames", nargs="*", help="See `sphinx-build -h`")
    return parser

def main():
    """Actual application logic."""
    parser = get_parser()
    args = parser.parse_args()

    srcdir = os.path.realpath(args.sourcedir)
    outdir = os.path.realpath(args.outdir)
    if not os.path.exists(outdir):
        os.makedirs(outdir)

    ignore_handler = get_ignore_handler(args)
    build_args = get_build_args(args)
    watcher = get_watcher(args)

    builder = SphinxBuilder(build_args, ignore_handler)
    server = Server(watcher=watcher)

    server.watch(srcdir, builder)
    for dirpath in args.additional_watched_dirs:
        dirpath = os.path.realpath(dirpath)
        server.watch(dirpath, builder)
    server.watch(outdir)

    if args.initial_build:
        builder.build()

    # Find the free port
    portn = args.port or find_free_port()
    if args.openbrowser is True:
        server.serve(port=portn, host=args.host, root=outdir, open_url_delay=args.delay)
    else:
        server.serve(port=portn, host=args.host, root=outdir)
<|endoftext|>