<commit_before>from django.contrib.staticfiles.testing import StaticLiveServerTestCase
from selenium.webdriver.firefox.webdriver import WebDriver

from django.test import TestCase
from django.conf import settings

class AnimalTestCase(TestCase):
    # def setUp(self):
    #     Animal.objects.create(name="lion", sound="roar")
    #     Animal.objects.create(name="cat", sound="meow")

    def test_animals_can_speak(self):
        print('foo')

class ModelTests(TestCase):
    """
    Queries on each model in the module
        Queries return correct data
        Queries that should return no data get no data
    """
    # How to work with GEOS API in Django:
    #       https://docs.djangoproject.com/en/2.2/ref/contrib/gis/geos/
    def test_models(self):
        print("Models!")

    def setUp(self):
        from django.contrib.auth.models import User
        # from landmapper.models import Taxlot
        # from django.contrib.gis.geos import GEOSGeometry
        ### Create user
        User.objects.get_or_create(username='admin')

    def test_taxlot(self):
        from django.contrib.auth.models import User
        from landmapper.models import Taxlot
        from django.contrib.gis.geos import GEOSGeometry

        admin = User.objects.get(username='admin')

        ### Create Taxlots
        # ZOOM TO: 44.085, -122.900
        # Taxlot NE of Eugene:
        poly_1 = GEOSGeometry('SRID=3857;MULTIPOLYGON (((-13681279.3108 5478566.238799997, -13680721.1384 5478574.5858, -13680722.0809 5478015.218999997, -13681279.9385 5478006.679099999, -13681838.8572 5477998.089199997, -13681837.4829 5478557.857699998, -13681279.3108 5478566.238799997)))', srid=3857)
        # Adjacent taxlot to the note
        poly_2 = GEOSGeometry('SRID=3857;MULTIPOLYGON (((-13681278.5741 5479125.020800002, -13680719.8309 5479133.516500004, -13680721.1384 5478574.5858, -13681279.3108 5478566.238799997, -13681837.4829 5478557.857699998, -13681837.3172 5479116.491499998, -13681278.5741 5479125.020800002)))', srid=3857)
        # Nearby, non-adjacent taxlot
        poly_3 = GEOSGeometry('SRID=3857;MULTIPOLYGON (((-13679606.0781 5478590.317100003, -13679607.5092 5478031.919799998, -13680164.0094 5478023.597900003, -13680163.6087 5478582.451800004, -13679606.0781 5478590.317100003)))', srid=3857)
        # transform polies from 3857 to 4326
        poly_1.transform(4326)
        poly_2.transform(4326)
        poly_3.transform(4326)

        #Create taxlot instances
        tl1 = Taxlot.objects.create(user=admin, geometry_orig=poly_1)
        tl2 = Taxlot.objects.create(user=admin, geometry_orig=poly_2)
        tl3 = Taxlot.objects.create(user=admin, geometry_orig=poly_3)

        click_1 = 'SRID=4326;POINT( -122.903 44.083 )'          #Note, it doesn't appear to matter if we give GEOSGeoms or just WKT.
        click_2 = GEOSGeometry('SRID=4326;POINT( -122.902 44.087 )')
        click_3 = GEOSGeometry('SRID=4326;POINT( -122.888 44.083 )')
        click_4 = GEOSGeometry('SRID=4326;POINT( -123 45 )')

        # Test intersection
        taxlot_1 = Taxlot.objects.get(geometry_orig__contains=click_1)
        taxlot_2 = Taxlot.objects.get(geometry_orig__contains=click_2)
        taxlot_3 = Taxlot.objects.get(geometry_orig__contains=click_3)
        self.assertEqual(taxlot_1.pk, tl1.pk)
        self.assertEqual(taxlot_2.pk, tl2.pk)
        self.assertEqual(taxlot_3.pk, tl3.pk)
        self.assertNotEqual(taxlot_1.pk, tl2.pk)
        self.assertEqual(len(Taxlot.objects.filter(geometry_orig__contains=click_4)), 0)

        #TODO: test any model methods for attributes and types returned

    def test_menu_page(self):
        from landmapper.models import MenuPage

        menu_title = "Menu Item"
        # Courtesy of rikeripsum.com
        menu_text = "The game's not big enough unless it scares you a little. \
        Your head is not an artifact! Our neural pathways have become \
        accustomed to your sensory input patterns. Commander William Riker of \
        the Starship Enterprise. What? We're not at all alike! What's a \
        knock-out like you doing in a computer-generated gin joint like this? \
        Not if I weaken first. Mr. Worf, you sound like a man who's asking his \
        friend if he can start dating his sister. For an android with no \
        feelings, he sure managed to evoke them in others."
        menu_content = "
%s

%s
" % (menu_title, menu_text)

        MenuPage.objects.create(name='Menu', content=menu_content, order=0)

        hipster_title = "Hipster"
        # courtesy of https://hipsum.co/
        hipster_textP1 = "Fam id messenger bag forage, nisi lomo edison bulb \
        ipsum lo-fi kitsch street art kinfolk sriracha irony nulla. Raclette \
        fanny pack meditation, lomo heirloom farm-to-table wayfarers shaman \
        dolore roof party trust fund disrupt laboris anim kogi. Taxidermy \
        organic nostrud blue bottle activated charcoal minim, gluten-free \
        slow-carb XOXO photo booth cornhole keffiyeh elit. Cold-pressed \
        cornhole waistcoat snackwave hexagon. Banh mi subway tile viral ennui, \
        duis irure poutine proident flexitarian fam direct trade sint roof \
        party. Try-hard artisan pork belly chillwave. Quis activated charcoal \
        mustache cornhole excepteur nostrud godard."
        hipster_textP2 = "Id neutra literally four dollar toast ea, franzen \
        irony food truck venmo. Pour-over copper mug cold-pressed, yr YOLO \
        sartorial tousled pug tacos mustache hashtag. Health goth vinyl \
        chillwave williamsburg cardigan kickstarter tofu normcore duis hoodie \
        shaman neutra cred tumblr church-key. Af authentic craft beer, \
        letterpress deep v intelligentsia slow-carb synth 90's. Activated \
        charcoal organic blue bottle aliqua in dolore."
        hipster_content = "
%s

%s

%s
" % (
            hipster_title,
            hipster_textP1,
            hipster_textP2
        )

        MenuPage.objects.create(name=hipster_title, content=hipster_content, order=1, staff_only=True)

        self.assertEqual(len(MenuPage.objects.all()), 2)
        non_staff = MenuPage.objects.get(staff_only=False)
        self.assertTrue('gin joint' in non_staff.content)
        staff_only = MenuPage.objects.get(staff_only=True)
        self.assertTrue('Banh mi' in staff_only.content)

        # TODO: test this in Front-End

    def test_forest_type(self):
        from landmapper.models import ForestType

        ForestType.objects.create(name='Foo')

        self.assertEqual(len(ForestType.objects.all()), 1)

        # TODO: test everything about ForestType once it's a thing

class ViewTests(TestCase):
    """
    External APIs
        soil data queries
        geocoding
        Pulling map images for server-side .PDF creation
    """
    def test_soils_api(self):
        # TODO: SOILS API
        print('soils')

    def test_geocoding(self):
        # TODO: Geocoding with Geocoder: https://geocoder.readthedocs.io/
        #   How are api keys handled?
        print('geocoder')

    def test_tiles(self):
        # TODO: Tile requests
        #   basemap images
        #   streams?
        #   lots/properties?
        #   forest types?
        #   soils
        print('tiles')

    """
    Templates
        correctly formatted context for rendering templates
        reporting values
        ForestType queries
        legend creation (map, forest type, soil)
        table creation (overview, forest type, soil)
    """

    # Should we break up views into 'gather' and 'render' functions?
    # Perhaps the 'gather' functions are modular children - the parent requests
    #   the context and then uses that to render the template

    def test_header_gather(self):
        # TODO:
        # add menu items (done in models tests?)
        # do branding images exist?
        # is context dict correctly formatted with:
        #   correct keywords
        #   correct value types for each keyword
        #   correct values
        #   correct order (of MenuPage instances)
        print('header view')

    def test_home_view_gather(self):
        # TODO:
        #   ...
        print('home view gather')

    """
    Error Handling
    """
    """
    GIS Manipulation
        convert taxlot selections into features
    """
    """
    File generation/export
        pdf report generation
            all
            forest type
            soil
        Property Shapefile
            zipping
    """
    def test_views(self):
        print("Views!")

# class FrontendTests(StaticLiveServerTestCase):
#     """
#     state changes
#         address found
#             map zoomed
#                 Test if specific map tiles were pulled
#             state advanced
#         1st taxlot selected
#             state advanced
#             url updated
#         2nd taxlot selected
#             state retained
#             url updated
#         property name entered
#             'next' enabled
#             url updated
#         property name deleted
#             'next' disabled
#             url updated
#         2nd taxlot unselected
#             url updated
#             state retained
#         1st taxlot unselected
#             url updated
#             state regressed
#         address cleared
#             url updated
#             state regressed
#             map zoomed back to default
#         valid input and clicking 'next' brings us to a report
#     Error handling
#         unknown address
#         non-contiguous taxlots
#     validation
#         validate address prior to geocode query
#         valid property names?
#             1+ spaces?
#             Maximum characters
#             Foreign accented characters (Latin1, umlauts, etc…)
#     popups
#         From the header menu
#         from the download button(s)
#         From 'get help'
#     downloads?
#     """
#     @classmethod
#     def setUpClass(cls):
#         super().setUpClass()
#         cls.selenium = WebDriver()
#         cls.selenium.implicitly_wait(2)
#
#     @classmethod
#     def tearDownClass(cls):
#         cls.selenium.quit()
#         super().tearDownClass()
#
#    def test_home(self):
#        # TODOS:
#        #   Header placement
#        #   Header branding
#        #   Header Menu Items
#        #   ...
#
#     # def test_login(self):
#     def test_browser(self):
#         print("Front End!")
#
# class MySeleniumTests(StaticLiveServerTestCase):
#     # fixtures = ['user-data.json']
#     #
#     @classmethod
#     def setUpClass(cls):
#         super().setUpClass()
#         cls.selenium = WebDriver()
#         cls.selenium.implicitly_wait(2)
#
#     @classmethod
#     def tearDownClass(cls):
#         cls.selenium.quit()
#         super().tearDownClass()
#
#     # def test_login(self):
#     def test_browser(self):
#         # import ipdb; ipdb.set_trace()
#         print('get server')
#         print('URL: ""%s"' % self.live_server_url)
#         # foo = self.selenium.get(self.live_server_url)
#         # foo.title
#         # self.selenium.get('%s%s' % (self.live_server_url, '/login/'))
#         # username_input = self.selenium.find_element_by_name("username")
#         # username_input.send_keys('myuser')
#         # password_input = self.selenium.find_element_by_name("password")
#         # password_input.send_keys('secret')
#         # self.selenium.find_element_by_xpath('//input[@value="Log in"]').click()
#

# from django.test import TestCase
#
# from selenium import webdriver
#
# # From stack overflow:
# ### https://stackoverflow.com/a/47785513
# from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
#
# cap = DesiredCapabilities().FIREFOX
# # cap["marionette"] = False
#
# # browser = webdriver.Firefox(capabilities=cap, executable_path="/usr/local/bin/geckodriver")
#
# ### https://stackoverflow.com/questions/45692626/unable-to-load-firefox-in-selenium-webdriver-in-python
# from selenium.webdriver.firefox.firefox_binary import FirefoxBinary
# cap["marionette"] = True
# binary = FirefoxBinary('/usr/bin/firefox')
# print('create browser')
# browser = webdriver.Firefox(firefox_binary=binary, capabilities=cap, executable_path="/usr/local/bin/geckodriver")
#
# # browser = webdriver.Firefox()
# # browser.get('http://127.0.0.1:8000')
# print('google test')
# browser.get('http://www.google.com')
# print('pre')
# browser.get('http://0:8000')
# print(browser.title)
# assert 'Django' in browser.title
<commit_msg>Delete animal test<commit_after>from django.contrib.staticfiles.testing import StaticLiveServerTestCase
from selenium.webdriver.firefox.webdriver import WebDriver

from django.test import TestCase
from django.conf import settings

class ModelTests(TestCase):
    """
    Queries on each model in the module
        Queries return correct data
        Queries that should return no data get no data
    """
    # How to work with GEOS API in Django:
    #       https://docs.djangoproject.com/en/2.2/ref/contrib/gis/geos/
    def test_models(self):
        print("Models!")

    def setUp(self):
        from django.contrib.auth.models import User
        # from landmapper.models import Taxlot
        # from django.contrib.gis.geos import GEOSGeometry
        ### Create user
        User.objects.get_or_create(username='admin')

    def test_taxlot(self):
        from django.contrib.auth.models import User
        from landmapper.models import Taxlot
        from django.contrib.gis.geos import GEOSGeometry

        admin = User.objects.get(username='admin')

        ### Create Taxlots
        # ZOOM TO: 44.085, -122.900
        # Taxlot NE of Eugene:
        poly_1 = GEOSGeometry('SRID=3857;MULTIPOLYGON (((-13681279.3108 5478566.238799997, -13680721.1384 5478574.5858, -13680722.0809 5478015.218999997, -13681279.9385 5478006.679099999, -13681838.8572 5477998.089199997, -13681837.4829 5478557.857699998, -13681279.3108 5478566.238799997)))', srid=3857)
        # Adjacent taxlot to the note
        poly_2 = GEOSGeometry('SRID=3857;MULTIPOLYGON (((-13681278.5741 5479125.020800002, -13680719.8309 5479133.516500004, -13680721.1384 5478574.5858, -13681279.3108 5478566.238799997, -13681837.4829 5478557.857699998, -13681837.3172 5479116.491499998, -13681278.5741 5479125.020800002)))', srid=3857)
        # Nearby, non-adjacent taxlot
        poly_3 = GEOSGeometry('SRID=3857;MULTIPOLYGON (((-13679606.0781 5478590.317100003, -13679607.5092 5478031.919799998, -13680164.0094 5478023.597900003, -13680163.6087 5478582.451800004, -13679606.0781 5478590.317100003)))', srid=3857)
        # transform polies from 3857 to 4326
        poly_1.transform(4326)
        poly_2.transform(4326)
        poly_3.transform(4326)

        #Create taxlot instances
        tl1 = Taxlot.objects.create(user=admin, geometry_orig=poly_1)
        tl2 = Taxlot.objects.create(user=admin, geometry_orig=poly_2)
        tl3 = Taxlot.objects.create(user=admin, geometry_orig=poly_3)

        click_1 = 'SRID=4326;POINT( -122.903 44.083 )'          #Note, it doesn't appear to matter if we give GEOSGeoms or just WKT.
        click_2 = GEOSGeometry('SRID=4326;POINT( -122.902 44.087 )')
        click_3 = GEOSGeometry('SRID=4326;POINT( -122.888 44.083 )')
        click_4 = GEOSGeometry('SRID=4326;POINT( -123 45 )')

        # Test intersection
        taxlot_1 = Taxlot.objects.get(geometry_orig__contains=click_1)
        taxlot_2 = Taxlot.objects.get(geometry_orig__contains=click_2)
        taxlot_3 = Taxlot.objects.get(geometry_orig__contains=click_3)
        self.assertEqual(taxlot_1.pk, tl1.pk)
        self.assertEqual(taxlot_2.pk, tl2.pk)
        self.assertEqual(taxlot_3.pk, tl3.pk)
        self.assertNotEqual(taxlot_1.pk, tl2.pk)
        self.assertEqual(len(Taxlot.objects.filter(geometry_orig__contains=click_4)), 0)

        #TODO: test any model methods for attributes and types returned

    def test_menu_page(self):
        from landmapper.models import MenuPage

        menu_title = "Menu Item"
        # Courtesy of rikeripsum.com
        menu_text = "The game's not big enough unless it scares you a little. \
        Your head is not an artifact! Our neural pathways have become \
        accustomed to your sensory input patterns. Commander William Riker of \
        the Starship Enterprise. What? We're not at all alike! What's a \
        knock-out like you doing in a computer-generated gin joint like this? \
        Not if I weaken first. Mr. Worf, you sound like a man who's asking his \
        friend if he can start dating his sister. For an android with no \
        feelings, he sure managed to evoke them in others."
        menu_content = "
%s

%s
" % (menu_title, menu_text)

        MenuPage.objects.create(name='Menu', content=menu_content, order=0)

        hipster_title = "Hipster"
        # courtesy of https://hipsum.co/
        hipster_textP1 = "Fam id messenger bag forage, nisi lomo edison bulb \
        ipsum lo-fi kitsch street art kinfolk sriracha irony nulla. Raclette \
        fanny pack meditation, lomo heirloom farm-to-table wayfarers shaman \
        dolore roof party trust fund disrupt laboris anim kogi. Taxidermy \
        organic nostrud blue bottle activated charcoal minim, gluten-free \
        slow-carb XOXO photo booth cornhole keffiyeh elit. Cold-pressed \
        cornhole waistcoat snackwave hexagon. Banh mi subway tile viral ennui, \
        duis irure poutine proident flexitarian fam direct trade sint roof \
        party. Try-hard artisan pork belly chillwave. Quis activated charcoal \
        mustache cornhole excepteur nostrud godard."
        hipster_textP2 = "Id neutra literally four dollar toast ea, franzen \
        irony food truck venmo. Pour-over copper mug cold-pressed, yr YOLO \
        sartorial tousled pug tacos mustache hashtag. Health goth vinyl \
        chillwave williamsburg cardigan kickstarter tofu normcore duis hoodie \
        shaman neutra cred tumblr church-key. Af authentic craft beer, \
        letterpress deep v intelligentsia slow-carb synth 90's. Activated \
        charcoal organic blue bottle aliqua in dolore."
        hipster_content = "
%s

%s

%s
" % (
            hipster_title,
            hipster_textP1,
            hipster_textP2
        )

        MenuPage.objects.create(name=hipster_title, content=hipster_content, order=1, staff_only=True)

        self.assertEqual(len(MenuPage.objects.all()), 2)
        non_staff = MenuPage.objects.get(staff_only=False)
        self.assertTrue('gin joint' in non_staff.content)
        staff_only = MenuPage.objects.get(staff_only=True)
        self.assertTrue('Banh mi' in staff_only.content)

        # TODO: test this in Front-End

    def test_forest_type(self):
        from landmapper.models import ForestType

        ForestType.objects.create(name='Foo')

        self.assertEqual(len(ForestType.objects.all()), 1)

        # TODO: test everything about ForestType once it's a thing

class ViewTests(TestCase):
    """
    External APIs
        soil data queries
        geocoding
        Pulling map images for server-side .PDF creation
    """
    def test_soils_api(self):
        # TODO: SOILS API
        print('soils')

    def test_geocoding(self):
        # TODO: Geocoding with Geocoder: https://geocoder.readthedocs.io/
        #   How are api keys handled?
        print('geocoder')

    def test_tiles(self):
        # TODO: Tile requests
        #   basemap images
        #   streams?
        #   lots/properties?
        #   forest types?
        #   soils
        print('tiles')

    """
    Templates
        correctly formatted context for rendering templates
        reporting values
        ForestType queries
        legend creation (map, forest type, soil)
        table creation (overview, forest type, soil)
    """

    # Should we break up views into 'gather' and 'render' functions?
    # Perhaps the 'gather' functions are modular children - the parent requests
    #   the context and then uses that to render the template

    def test_header_gather(self):
        # TODO:
        # add menu items (done in models tests?)
        # do branding images exist?
        # is context dict correctly formatted with:
        #   correct keywords
        #   correct value types for each keyword
        #   correct values
        #   correct order (of MenuPage instances)
        print('header view')

    def test_home_view_gather(self):
        # TODO:
        #   ...
        print('home view gather')

    """
    Error Handling
    """
    """
    GIS Manipulation
        convert taxlot selections into features
    """
    """
    File generation/export
        pdf report generation
            all
            forest type
            soil
        Property Shapefile
            zipping
    """
    def test_views(self):
        print("Views!")

# class FrontendTests(StaticLiveServerTestCase):
#     """
#     state changes
#         address found
#             map zoomed
#                 Test if specific map tiles were pulled
#             state advanced
#         1st taxlot selected
#             state advanced
#             url updated
#         2nd taxlot selected
#             state retained
#             url updated
#         property name entered
#             'next' enabled
#             url updated
#         property name deleted
#             'next' disabled
#             url updated
#         2nd taxlot unselected
#             url updated
#             state retained
#         1st taxlot unselected
#             url updated
#             state regressed
#         address cleared
#             url updated
#             state regressed
#             map zoomed back to default
#         valid input and clicking 'next' brings us to a report
#     Error handling
#         unknown address
#         non-contiguous taxlots
#     validation
#         validate address prior to geocode query
#         valid property names?
#             1+ spaces?
#             Maximum characters
#             Foreign accented characters (Latin1, umlauts, etc…)
#     popups
#         From the header menu
#         from the download button(s)
#         From 'get help'
#     downloads?
#     """
#     @classmethod
#     def setUpClass(cls):
#         super().setUpClass()
#         cls.selenium = WebDriver()
#         cls.selenium.implicitly_wait(2)
#
#     @classmethod
#     def tearDownClass(cls):
#         cls.selenium.quit()
#         super().tearDownClass()
#
#    def test_home(self):
#        # TODOS:
#        #   Header placement
#        #   Header branding
#        #   Header Menu Items
#        #   ...
#
#     # def test_login(self):
#     def test_browser(self):
#         print("Front End!")
#
# class MySeleniumTests(StaticLiveServerTestCase):
#     # fixtures = ['user-data.json']
#     #
#     @classmethod
#     def setUpClass(cls):
#         super().setUpClass()
#         cls.selenium = WebDriver()
#         cls.selenium.implicitly_wait(2)
#
#     @classmethod
#     def tearDownClass(cls):
#         cls.selenium.quit()
#         super().tearDownClass()
#
#     # def test_login(self):
#     def test_browser(self):
#         # import ipdb; ipdb.set_trace()
#         print('get server')
#         print('URL: ""%s"' % self.live_server_url)
#         # foo = self.selenium.get(self.live_server_url)
#         # foo.title
#         # self.selenium.get('%s%s' % (self.live_server_url, '/login/'))
#         # username_input = self.selenium.find_element_by_name("username")
#         # username_input.send_keys('myuser')
#         # password_input = self.selenium.find_element_by_name("password")
#         # password_input.send_keys('secret')
#         # self.selenium.find_element_by_xpath('//input[@value="Log in"]').click()
#

# from django.test import TestCase
#
# from selenium import webdriver
#
# # From stack overflow:
# ### https://stackoverflow.com/a/47785513
# from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
#
# cap = DesiredCapabilities().FIREFOX
# # cap["marionette"] = False
#
# # browser = webdriver.Firefox(capabilities=cap, executable_path="/usr/local/bin/geckodriver")
#
# ### https://stackoverflow.com/questions/45692626/unable-to-load-firefox-in-selenium-webdriver-in-python
# from selenium.webdriver.firefox.firefox_binary import FirefoxBinary
# cap["marionette"] = True
# binary = FirefoxBinary('/usr/bin/firefox')
# print('create browser')
# browser = webdriver.Firefox(firefox_binary=binary, capabilities=cap, executable_path="/usr/local/bin/geckodriver")
#
# # browser = webdriver.Firefox()
# # browser.get('http://127.0.0.1:8000')
# print('google test')
# browser.get('http://www.google.com')
# print('pre')
# browser.get('http://0:8000')
# print(browser.title)
# assert 'Django' in browser.title
<|endoftext|>


<commit_before># Copyright 2019 gRPC authors.
#
# 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.
"""Invocation-side implementation of gRPC Asyncio Python."""

import asyncio
import sys
from typing import Any, AsyncIterable, Iterable, Optional, Sequence

import grpc
from grpc import _common, _compression, _grpcio_metadata
from grpc._cython import cygrpc

from . import _base_call, _base_channel
from ._call import (StreamStreamCall, StreamUnaryCall, UnaryStreamCall,
                    UnaryUnaryCall)
from ._interceptor import (InterceptedUnaryUnaryCall,
                           UnaryUnaryClientInterceptor)
from ._typing import (ChannelArgumentType, DeserializingFunction, MetadataType,
                      SerializingFunction)
from ._utils import _timeout_to_deadline

_IMMUTABLE_EMPTY_TUPLE = tuple()
_USER_AGENT = 'grpc-python-asyncio/{}'.format(_grpcio_metadata.__version__)

if sys.version_info[1] < 7:

    def _all_tasks() -> Iterable[asyncio.Task]:
        return asyncio.Task.all_tasks()
else:

    def _all_tasks() -> Iterable[asyncio.Task]:
        return asyncio.all_tasks()

def _augment_channel_arguments(base_options: ChannelArgumentType,
                               compression: Optional[grpc.Compression]):
    compression_channel_argument = _compression.create_channel_option(
        compression)
    user_agent_channel_argument = ((
        cygrpc.ChannelArgKey.primary_user_agent_string,
        _USER_AGENT,
    ),)
    return tuple(base_options
                ) + compression_channel_argument + user_agent_channel_argument

class _BaseMultiCallable:
    """Base class of all multi callable objects.

    Handles the initialization logic and stores common attributes.
    """
    _loop: asyncio.AbstractEventLoop
    _channel: cygrpc.AioChannel
    _method: bytes
    _request_serializer: SerializingFunction
    _response_deserializer: DeserializingFunction
    _interceptors: Optional[Sequence[UnaryUnaryClientInterceptor]]
    _loop: asyncio.AbstractEventLoop

    # pylint: disable=too-many-arguments
    def __init__(
            self,
            channel: cygrpc.AioChannel,
            method: bytes,
            request_serializer: SerializingFunction,
            response_deserializer: DeserializingFunction,
            interceptors: Optional[Sequence[UnaryUnaryClientInterceptor]],
            loop: asyncio.AbstractEventLoop,
    ) -> None:
        self._loop = loop
        self._channel = channel
        self._method = method
        self._request_serializer = request_serializer
        self._response_deserializer = response_deserializer
        self._interceptors = interceptors

class UnaryUnaryMultiCallable(_BaseMultiCallable,
                              _base_channel.UnaryUnaryMultiCallable):

    def __call__(self,
                 request: Any,
                 *,
                 timeout: Optional[float] = None,
                 metadata: Optional[MetadataType] = _IMMUTABLE_EMPTY_TUPLE,
                 credentials: Optional[grpc.CallCredentials] = None,
                 wait_for_ready: Optional[bool] = None,
                 compression: Optional[grpc.Compression] = None
                ) -> _base_call.UnaryUnaryCall:
        if compression:
            metadata = _compression.augment_metadata(metadata, compression)

        if not self._interceptors:
            call = UnaryUnaryCall(request, _timeout_to_deadline(timeout),
                                  metadata, credentials, wait_for_ready,
                                  self._channel, self._method,
                                  self._request_serializer,
                                  self._response_deserializer, self._loop)
        else:
            call = InterceptedUnaryUnaryCall(
                self._interceptors, request, timeout, metadata, credentials,
                wait_for_ready, self._channel, self._method,
                self._request_serializer, self._response_deserializer,
                self._loop)

        return call

class UnaryStreamMultiCallable(_BaseMultiCallable,
                               _base_channel.UnaryStreamMultiCallable):

    def __call__(self,
                 request: Any,
                 *,
                 timeout: Optional[float] = None,
                 metadata: Optional[MetadataType] = _IMMUTABLE_EMPTY_TUPLE,
                 credentials: Optional[grpc.CallCredentials] = None,
                 wait_for_ready: Optional[bool] = None,
                 compression: Optional[grpc.Compression] = None
                ) -> _base_call.UnaryStreamCall:
        if compression:
            metadata = _compression.augment_metadata(metadata, compression)

        deadline = _timeout_to_deadline(timeout)

        call = UnaryStreamCall(request, deadline, metadata, credentials,
                               wait_for_ready, self._channel, self._method,
                               self._request_serializer,
                               self._response_deserializer, self._loop)

        return call

class StreamUnaryMultiCallable(_BaseMultiCallable,
                               _base_channel.StreamUnaryMultiCallable):

    def __call__(self,
                 request_async_iterator: Optional[AsyncIterable[Any]] = None,
                 timeout: Optional[float] = None,
                 metadata: Optional[MetadataType] = _IMMUTABLE_EMPTY_TUPLE,
                 credentials: Optional[grpc.CallCredentials] = None,
                 wait_for_ready: Optional[bool] = None,
                 compression: Optional[grpc.Compression] = None
                ) -> _base_call.StreamUnaryCall:
        if compression:
            metadata = _compression.augment_metadata(metadata, compression)

        deadline = _timeout_to_deadline(timeout)

        call = StreamUnaryCall(request_async_iterator, deadline, metadata,
                               credentials, wait_for_ready, self._channel,
                               self._method, self._request_serializer,
                               self._response_deserializer, self._loop)

        return call

class StreamStreamMultiCallable(_BaseMultiCallable,
                                _base_channel.StreamStreamMultiCallable):

    def __call__(self,
                 request_async_iterator: Optional[AsyncIterable[Any]] = None,
                 timeout: Optional[float] = None,
                 metadata: Optional[MetadataType] = _IMMUTABLE_EMPTY_TUPLE,
                 credentials: Optional[grpc.CallCredentials] = None,
                 wait_for_ready: Optional[bool] = None,
                 compression: Optional[grpc.Compression] = None
                ) -> _base_call.StreamStreamCall:
        if compression:
            metadata = _compression.augment_metadata(metadata, compression)

        deadline = _timeout_to_deadline(timeout)

        call = StreamStreamCall(request_async_iterator, deadline, metadata,
                                credentials, wait_for_ready, self._channel,
                                self._method, self._request_serializer,
                                self._response_deserializer, self._loop)

        return call

class Channel(_base_channel.Channel):
    _loop: asyncio.AbstractEventLoop
    _channel: cygrpc.AioChannel
    _unary_unary_interceptors: Optional[Sequence[UnaryUnaryClientInterceptor]]

    def __init__(self, target: str, options: ChannelArgumentType,
                 credentials: Optional[grpc.ChannelCredentials],
                 compression: Optional[grpc.Compression],
                 interceptors: Optional[Sequence[UnaryUnaryClientInterceptor]]):
        """Constructor.

        Args:
          target: The target to which to connect.
          options: Configuration options for the channel.
          credentials: A cygrpc.ChannelCredentials or None.
          compression: An optional value indicating the compression method to be
            used over the lifetime of the channel.
          interceptors: An optional list of interceptors that would be used for
            intercepting any RPC executed with that channel.
        """
        if interceptors is None:
            self._unary_unary_interceptors = None
        else:
            self._unary_unary_interceptors = list(
                filter(
                    lambda interceptor: isinstance(interceptor,
                                                   UnaryUnaryClientInterceptor),
                    interceptors))

            invalid_interceptors = set(interceptors) - set(
                self._unary_unary_interceptors)

            if invalid_interceptors:
                raise ValueError(
                    "Interceptor must be "+\
                    "UnaryUnaryClientInterceptors, the following are invalid: {}"\
                    .format(invalid_interceptors))

        self._loop = asyncio.get_event_loop()
        self._channel = cygrpc.AioChannel(
            _common.encode(target),
            _augment_channel_arguments(options, compression), credentials,
            self._loop)

    async def __aenter__(self):
        return self

    async def __aexit__(self, exc_type, exc_val, exc_tb):
        await self._close(None)

    async def _close(self, grace):
        if self._channel.closed():
            return

        # No new calls will be accepted by the Cython channel.
        self._channel.closing()

        # Iterate through running tasks
        tasks = _all_tasks()
        calls = []
        call_tasks = []
        for task in tasks:
            try:
                stack = task.get_stack(limit=1)
            except AttributeError as attribute_error:
                # NOTE(lidiz) tl;dr: If the Task is created with a CPython
                # object, it will trigger AttributeError.
                #
                # In the global finalizer, the event loop schedules
                # a CPython PyAsyncGenAThrow object.
                # https://github.com/python/cpython/blob/00e45877e33d32bb61aa13a2033e3bba370bda4d/Lib/asyncio/base_events.py#L484
                #
                # However, the PyAsyncGenAThrow object is written in C and
                # failed to include the normal Python frame objects. Hence,
                # this exception is a false negative, and it is safe to ignore
                # the failure. It is fixed by https://github.com/python/cpython/pull/18669,
                # but not available until 3.9 or 3.8.3. So, we have to keep it
                # for a while.
                if 'frame' in str(attribute_error):
                    continue
                else:
                    raise

            # If the Task is created by a C-extension, the stack will be empty.
            if not stack:
                continue

            # Locate ones created by `aio.Call`.
            frame = stack[0]
            candidate = frame.f_locals.get('self')
            if candidate:
                if isinstance(candidate, _base_call.Call):
                    if hasattr(candidate, '_channel'):
                        # For intercepted Call object
                        if candidate._channel is not self._channel:
                            continue
                    elif hasattr(candidate, '_cython_call'):
                        # For normal Call object
                        if candidate._cython_call._channel is not self._channel:
                            continue
                    else:
                        # Unidentified Call object
                        raise cygrpc.InternalError(
                            f'Unrecognized call object: {candidate}')

                    calls.append(candidate)
                    call_tasks.append(task)

        # If needed, try to wait for them to finish.
        # Call objects are not always awaitables.
        if grace and call_tasks:
            await asyncio.wait(call_tasks, timeout=grace, loop=self._loop)

        # Time to cancel existing calls.
        for call in calls:
            call.cancel()

        # Destroy the channel
        self._channel.close()

    async def close(self, grace: Optional[float] = None):
        await self._close(grace)

    def get_state(self,
                  try_to_connect: bool = False) -> grpc.ChannelConnectivity:
        result = self._channel.check_connectivity_state(try_to_connect)
        return _common.CYGRPC_CONNECTIVITY_STATE_TO_CHANNEL_CONNECTIVITY[result]

    async def wait_for_state_change(
            self,
            last_observed_state: grpc.ChannelConnectivity,
    ) -> None:
        assert await self._channel.watch_connectivity_state(
            last_observed_state.value[0], None)

    async def channel_ready(self) -> None:
        state = self.get_state(try_to_connect=True)
        while state != grpc.ChannelConnectivity.READY:
            await self.wait_for_state_change(state)
            state = self.get_state(try_to_connect=True)

    def unary_unary(
            self,
            method: str,
            request_serializer: Optional[SerializingFunction] = None,
            response_deserializer: Optional[DeserializingFunction] = None
    ) -> UnaryUnaryMultiCallable:
        return UnaryUnaryMultiCallable(self._channel, _common.encode(method),
                                       request_serializer,
                                       response_deserializer,
                                       self._unary_unary_interceptors,
                                       self._loop)

    def unary_stream(
            self,
            method: str,
            request_serializer: Optional[SerializingFunction] = None,
            response_deserializer: Optional[DeserializingFunction] = None
    ) -> UnaryStreamMultiCallable:
        return UnaryStreamMultiCallable(self._channel, _common.encode(method),
                                        request_serializer,
                                        response_deserializer, None, self._loop)

    def stream_unary(
            self,
            method: str,
            request_serializer: Optional[SerializingFunction] = None,
            response_deserializer: Optional[DeserializingFunction] = None
    ) -> StreamUnaryMultiCallable:
        return StreamUnaryMultiCallable(self._channel, _common.encode(method),
                                        request_serializer,
                                        response_deserializer, None, self._loop)

    def stream_stream(
            self,
            method: str,
            request_serializer: Optional[SerializingFunction] = None,
            response_deserializer: Optional[DeserializingFunction] = None
    ) -> StreamStreamMultiCallable:
        return StreamStreamMultiCallable(self._channel, _common.encode(method),
                                         request_serializer,
                                         response_deserializer, None,
                                         self._loop)

def insecure_channel(
        target: str,
        options: Optional[ChannelArgumentType] = None,
        compression: Optional[grpc.Compression] = None,
        interceptors: Optional[Sequence[UnaryUnaryClientInterceptor]] = None):
    """Creates an insecure asynchronous Channel to a server.

    Args:
      target: The server address
      options: An optional list of key-value pairs (channel args
        in gRPC Core runtime) to configure the channel.
      compression: An optional value indicating the compression method to be
        used over the lifetime of the channel. This is an EXPERIMENTAL option.
      interceptors: An optional sequence of interceptors that will be executed for
        any call executed with this channel.

    Returns:
      A Channel.
    """
    return Channel(target, () if options is None else options, None,
                   compression, interceptors)

def secure_channel(
        target: str,
        credentials: grpc.ChannelCredentials,
        options: Optional[ChannelArgumentType] = None,
        compression: Optional[grpc.Compression] = None,
        interceptors: Optional[Sequence[UnaryUnaryClientInterceptor]] = None):
    """Creates a secure asynchronous Channel to a server.

    Args:
      target: The server address.
      credentials: A ChannelCredentials instance.
      options: An optional list of key-value pairs (channel args
        in gRPC Core runtime) to configure the channel.
      compression: An optional value indicating the compression method to be
        used over the lifetime of the channel. This is an EXPERIMENTAL option.
      interceptors: An optional sequence of interceptors that will be executed for
        any call executed with this channel.

    Returns:
      An aio.Channel.
    """
    return Channel(target, () if options is None else options,
                   credentials._credentials, compression, interceptors)
<commit_msg>Mark it correctly with a TODO<commit_after># Copyright 2019 gRPC authors.
#
# 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.
"""Invocation-side implementation of gRPC Asyncio Python."""

import asyncio
import sys
from typing import Any, AsyncIterable, Iterable, Optional, Sequence

import grpc
from grpc import _common, _compression, _grpcio_metadata
from grpc._cython import cygrpc

from . import _base_call, _base_channel
from ._call import (StreamStreamCall, StreamUnaryCall, UnaryStreamCall,
                    UnaryUnaryCall)
from ._interceptor import (InterceptedUnaryUnaryCall,
                           UnaryUnaryClientInterceptor)
from ._typing import (ChannelArgumentType, DeserializingFunction, MetadataType,
                      SerializingFunction)
from ._utils import _timeout_to_deadline

_IMMUTABLE_EMPTY_TUPLE = tuple()
_USER_AGENT = 'grpc-python-asyncio/{}'.format(_grpcio_metadata.__version__)

if sys.version_info[1] < 7:

    def _all_tasks() -> Iterable[asyncio.Task]:
        return asyncio.Task.all_tasks()
else:

    def _all_tasks() -> Iterable[asyncio.Task]:
        return asyncio.all_tasks()

def _augment_channel_arguments(base_options: ChannelArgumentType,
                               compression: Optional[grpc.Compression]):
    compression_channel_argument = _compression.create_channel_option(
        compression)
    user_agent_channel_argument = ((
        cygrpc.ChannelArgKey.primary_user_agent_string,
        _USER_AGENT,
    ),)
    return tuple(base_options
                ) + compression_channel_argument + user_agent_channel_argument

class _BaseMultiCallable:
    """Base class of all multi callable objects.

    Handles the initialization logic and stores common attributes.
    """
    _loop: asyncio.AbstractEventLoop
    _channel: cygrpc.AioChannel
    _method: bytes
    _request_serializer: SerializingFunction
    _response_deserializer: DeserializingFunction
    _interceptors: Optional[Sequence[UnaryUnaryClientInterceptor]]
    _loop: asyncio.AbstractEventLoop

    # pylint: disable=too-many-arguments
    def __init__(
            self,
            channel: cygrpc.AioChannel,
            method: bytes,
            request_serializer: SerializingFunction,
            response_deserializer: DeserializingFunction,
            interceptors: Optional[Sequence[UnaryUnaryClientInterceptor]],
            loop: asyncio.AbstractEventLoop,
    ) -> None:
        self._loop = loop
        self._channel = channel
        self._method = method
        self._request_serializer = request_serializer
        self._response_deserializer = response_deserializer
        self._interceptors = interceptors

class UnaryUnaryMultiCallable(_BaseMultiCallable,
                              _base_channel.UnaryUnaryMultiCallable):

    def __call__(self,
                 request: Any,
                 *,
                 timeout: Optional[float] = None,
                 metadata: Optional[MetadataType] = _IMMUTABLE_EMPTY_TUPLE,
                 credentials: Optional[grpc.CallCredentials] = None,
                 wait_for_ready: Optional[bool] = None,
                 compression: Optional[grpc.Compression] = None
                ) -> _base_call.UnaryUnaryCall:
        if compression:
            metadata = _compression.augment_metadata(metadata, compression)

        if not self._interceptors:
            call = UnaryUnaryCall(request, _timeout_to_deadline(timeout),
                                  metadata, credentials, wait_for_ready,
                                  self._channel, self._method,
                                  self._request_serializer,
                                  self._response_deserializer, self._loop)
        else:
            call = InterceptedUnaryUnaryCall(
                self._interceptors, request, timeout, metadata, credentials,
                wait_for_ready, self._channel, self._method,
                self._request_serializer, self._response_deserializer,
                self._loop)

        return call

class UnaryStreamMultiCallable(_BaseMultiCallable,
                               _base_channel.UnaryStreamMultiCallable):

    def __call__(self,
                 request: Any,
                 *,
                 timeout: Optional[float] = None,
                 metadata: Optional[MetadataType] = _IMMUTABLE_EMPTY_TUPLE,
                 credentials: Optional[grpc.CallCredentials] = None,
                 wait_for_ready: Optional[bool] = None,
                 compression: Optional[grpc.Compression] = None
                ) -> _base_call.UnaryStreamCall:
        if compression:
            metadata = _compression.augment_metadata(metadata, compression)

        deadline = _timeout_to_deadline(timeout)

        call = UnaryStreamCall(request, deadline, metadata, credentials,
                               wait_for_ready, self._channel, self._method,
                               self._request_serializer,
                               self._response_deserializer, self._loop)

        return call

class StreamUnaryMultiCallable(_BaseMultiCallable,
                               _base_channel.StreamUnaryMultiCallable):

    def __call__(self,
                 request_async_iterator: Optional[AsyncIterable[Any]] = None,
                 timeout: Optional[float] = None,
                 metadata: Optional[MetadataType] = _IMMUTABLE_EMPTY_TUPLE,
                 credentials: Optional[grpc.CallCredentials] = None,
                 wait_for_ready: Optional[bool] = None,
                 compression: Optional[grpc.Compression] = None
                ) -> _base_call.StreamUnaryCall:
        if compression:
            metadata = _compression.augment_metadata(metadata, compression)

        deadline = _timeout_to_deadline(timeout)

        call = StreamUnaryCall(request_async_iterator, deadline, metadata,
                               credentials, wait_for_ready, self._channel,
                               self._method, self._request_serializer,
                               self._response_deserializer, self._loop)

        return call

class StreamStreamMultiCallable(_BaseMultiCallable,
                                _base_channel.StreamStreamMultiCallable):

    def __call__(self,
                 request_async_iterator: Optional[AsyncIterable[Any]] = None,
                 timeout: Optional[float] = None,
                 metadata: Optional[MetadataType] = _IMMUTABLE_EMPTY_TUPLE,
                 credentials: Optional[grpc.CallCredentials] = None,
                 wait_for_ready: Optional[bool] = None,
                 compression: Optional[grpc.Compression] = None
                ) -> _base_call.StreamStreamCall:
        if compression:
            metadata = _compression.augment_metadata(metadata, compression)

        deadline = _timeout_to_deadline(timeout)

        call = StreamStreamCall(request_async_iterator, deadline, metadata,
                                credentials, wait_for_ready, self._channel,
                                self._method, self._request_serializer,
                                self._response_deserializer, self._loop)

        return call

class Channel(_base_channel.Channel):
    _loop: asyncio.AbstractEventLoop
    _channel: cygrpc.AioChannel
    _unary_unary_interceptors: Optional[Sequence[UnaryUnaryClientInterceptor]]

    def __init__(self, target: str, options: ChannelArgumentType,
                 credentials: Optional[grpc.ChannelCredentials],
                 compression: Optional[grpc.Compression],
                 interceptors: Optional[Sequence[UnaryUnaryClientInterceptor]]):
        """Constructor.

        Args:
          target: The target to which to connect.
          options: Configuration options for the channel.
          credentials: A cygrpc.ChannelCredentials or None.
          compression: An optional value indicating the compression method to be
            used over the lifetime of the channel.
          interceptors: An optional list of interceptors that would be used for
            intercepting any RPC executed with that channel.
        """
        if interceptors is None:
            self._unary_unary_interceptors = None
        else:
            self._unary_unary_interceptors = list(
                filter(
                    lambda interceptor: isinstance(interceptor,
                                                   UnaryUnaryClientInterceptor),
                    interceptors))

            invalid_interceptors = set(interceptors) - set(
                self._unary_unary_interceptors)

            if invalid_interceptors:
                raise ValueError(
                    "Interceptor must be "+\
                    "UnaryUnaryClientInterceptors, the following are invalid: {}"\
                    .format(invalid_interceptors))

        self._loop = asyncio.get_event_loop()
        self._channel = cygrpc.AioChannel(
            _common.encode(target),
            _augment_channel_arguments(options, compression), credentials,
            self._loop)

    async def __aenter__(self):
        return self

    async def __aexit__(self, exc_type, exc_val, exc_tb):
        await self._close(None)

    async def _close(self, grace):  # pylint: disable=too-many-branches
        if self._channel.closed():
            return

        # No new calls will be accepted by the Cython channel.
        self._channel.closing()

        # Iterate through running tasks
        tasks = _all_tasks()
        calls = []
        call_tasks = []
        for task in tasks:
            try:
                stack = task.get_stack(limit=1)
            except AttributeError as attribute_error:
                # NOTE(lidiz) tl;dr: If the Task is created with a CPython
                # object, it will trigger AttributeError.
                #
                # In the global finalizer, the event loop schedules
                # a CPython PyAsyncGenAThrow object.
                # https://github.com/python/cpython/blob/00e45877e33d32bb61aa13a2033e3bba370bda4d/Lib/asyncio/base_events.py#L484
                #
                # However, the PyAsyncGenAThrow object is written in C and
                # failed to include the normal Python frame objects. Hence,
                # this exception is a false negative, and it is safe to ignore
                # the failure. It is fixed by https://github.com/python/cpython/pull/18669,
                # but not available until 3.9 or 3.8.3. So, we have to keep it
                # for a while.
                # TODO(lidiz) drop this hack after 3.8 deprecation
                if 'frame' in str(attribute_error):
                    continue
                else:
                    raise

            # If the Task is created by a C-extension, the stack will be empty.
            if not stack:
                continue

            # Locate ones created by `aio.Call`.
            frame = stack[0]
            candidate = frame.f_locals.get('self')
            if candidate:
                if isinstance(candidate, _base_call.Call):
                    if hasattr(candidate, '_channel'):
                        # For intercepted Call object
                        if candidate._channel is not self._channel:
                            continue
                    elif hasattr(candidate, '_cython_call'):
                        # For normal Call object
                        if candidate._cython_call._channel is not self._channel:
                            continue
                    else:
                        # Unidentified Call object
                        raise cygrpc.InternalError(
                            f'Unrecognized call object: {candidate}')

                    calls.append(candidate)
                    call_tasks.append(task)

        # If needed, try to wait for them to finish.
        # Call objects are not always awaitables.
        if grace and call_tasks:
            await asyncio.wait(call_tasks, timeout=grace, loop=self._loop)

        # Time to cancel existing calls.
        for call in calls:
            call.cancel()

        # Destroy the channel
        self._channel.close()

    async def close(self, grace: Optional[float] = None):
        await self._close(grace)

    def get_state(self,
                  try_to_connect: bool = False) -> grpc.ChannelConnectivity:
        result = self._channel.check_connectivity_state(try_to_connect)
        return _common.CYGRPC_CONNECTIVITY_STATE_TO_CHANNEL_CONNECTIVITY[result]

    async def wait_for_state_change(
            self,
            last_observed_state: grpc.ChannelConnectivity,
    ) -> None:
        assert await self._channel.watch_connectivity_state(
            last_observed_state.value[0], None)

    async def channel_ready(self) -> None:
        state = self.get_state(try_to_connect=True)
        while state != grpc.ChannelConnectivity.READY:
            await self.wait_for_state_change(state)
            state = self.get_state(try_to_connect=True)

    def unary_unary(
            self,
            method: str,
            request_serializer: Optional[SerializingFunction] = None,
            response_deserializer: Optional[DeserializingFunction] = None
    ) -> UnaryUnaryMultiCallable:
        return UnaryUnaryMultiCallable(self._channel, _common.encode(method),
                                       request_serializer,
                                       response_deserializer,
                                       self._unary_unary_interceptors,
                                       self._loop)

    def unary_stream(
            self,
            method: str,
            request_serializer: Optional[SerializingFunction] = None,
            response_deserializer: Optional[DeserializingFunction] = None
    ) -> UnaryStreamMultiCallable:
        return UnaryStreamMultiCallable(self._channel, _common.encode(method),
                                        request_serializer,
                                        response_deserializer, None, self._loop)

    def stream_unary(
            self,
            method: str,
            request_serializer: Optional[SerializingFunction] = None,
            response_deserializer: Optional[DeserializingFunction] = None
    ) -> StreamUnaryMultiCallable:
        return StreamUnaryMultiCallable(self._channel, _common.encode(method),
                                        request_serializer,
                                        response_deserializer, None, self._loop)

    def stream_stream(
            self,
            method: str,
            request_serializer: Optional[SerializingFunction] = None,
            response_deserializer: Optional[DeserializingFunction] = None
    ) -> StreamStreamMultiCallable:
        return StreamStreamMultiCallable(self._channel, _common.encode(method),
                                         request_serializer,
                                         response_deserializer, None,
                                         self._loop)

def insecure_channel(
        target: str,
        options: Optional[ChannelArgumentType] = None,
        compression: Optional[grpc.Compression] = None,
        interceptors: Optional[Sequence[UnaryUnaryClientInterceptor]] = None):
    """Creates an insecure asynchronous Channel to a server.

    Args:
      target: The server address
      options: An optional list of key-value pairs (channel args
        in gRPC Core runtime) to configure the channel.
      compression: An optional value indicating the compression method to be
        used over the lifetime of the channel. This is an EXPERIMENTAL option.
      interceptors: An optional sequence of interceptors that will be executed for
        any call executed with this channel.

    Returns:
      A Channel.
    """
    return Channel(target, () if options is None else options, None,
                   compression, interceptors)

def secure_channel(
        target: str,
        credentials: grpc.ChannelCredentials,
        options: Optional[ChannelArgumentType] = None,
        compression: Optional[grpc.Compression] = None,
        interceptors: Optional[Sequence[UnaryUnaryClientInterceptor]] = None):
    """Creates a secure asynchronous Channel to a server.

    Args:
      target: The server address.
      credentials: A ChannelCredentials instance.
      options: An optional list of key-value pairs (channel args
        in gRPC Core runtime) to configure the channel.
      compression: An optional value indicating the compression method to be
        used over the lifetime of the channel. This is an EXPERIMENTAL option.
      interceptors: An optional sequence of interceptors that will be executed for
        any call executed with this channel.

    Returns:
      An aio.Channel.
    """
    return Channel(target, () if options is None else options,
                   credentials._credentials, compression, interceptors)
<|endoftext|>


<commit_before>import os
import math
from director import robotsystem
from director.consoleapp import ConsoleApp
from director import ioUtils
from director import segmentation
from director import applogic
from director import visualization as vis
from director import continuouswalkingdemo
from director import objectmodel as om
from director import ikplanner
from director import navigationpanel
from director import cameraview
from director import playbackpanel
from director import drcargs

import drc as lcmdrc

app = ConsoleApp()
dataDir = app.getTestingDataDirectory()
# create a view
view = app.createView()
segmentation._defaultSegmentationView = view

#footstepsPanel = footstepsdriverpanel.init(footstepsDriver, robotStateModel, robotStateJointController, mapServerSource)
footstepsPanel = None
robotsystem.create(view, globals())

def processSingleBlock(robotStateModel, whichFile=0):

    if (whichFile == 0):
        polyData = ioUtils.readPolyData(os.path.join(dataDir, 'terrain/terrain_simple_ihmc.vtp'))
        vis.updatePolyData( polyData, 'terrain_simple_ihmc.vtp', parent='continuous')
    else:
        polyData = ioUtils.readPolyData(os.path.join(dataDir, 'terrain/terrain_stairs_ihmc.vtp'))
        cwdemo.chosenTerrain = 'stairs'
        cwdemo.supportContact = lcmdrc.footstep_params_t.SUPPORT_GROUPS_MIDFOOT_TOE
        vis.updatePolyData( polyData, 'terrain_stairs_ihmc.vtp', parent='continuous')

    if drcargs.args().directorConfigFile.find('atlas') != -1:
    	standingFootName = 'l_foot'
    else:
        standingFootName = 'leftFoot'

    standingFootFrame = robotStateModel.getLinkFrame(standingFootName)
    vis.updateFrame(standingFootFrame, standingFootName, parent='continuous', visible=False)

    # Step 1: filter the data down to a box in front of the robot:
    polyData = cwdemo.getRecedingTerrainRegion(polyData, footstepsDriver.getFeetMidPoint(robotStateModel))

    # Step 2: find all the surfaces in front of the robot (about 0.75sec)
    clusters = segmentation.findHorizontalSurfaces(polyData)
    if (clusters is None):
        print "No cluster found, stop walking now!"
        return

    # Step 3: find the corners of the minimum bounding rectangles
    blocks,match_idx,groundPlane = cwdemo.extractBlocksFromSurfaces(clusters, standingFootFrame)

    footsteps = cwdemo.placeStepsOnBlocks(blocks, groundPlane, standingFootName, standingFootFrame)

    cwdemo.drawFittedSteps(footsteps)

def processSnippet():

    obj = om.getOrCreateContainer('continuous')
    om.getOrCreateContainer('cont debug', obj)

    if (continuouswalkingDemo.processContinuousStereo):
        polyData = ioUtils.readPolyData(os.path.join(dataDir, 'terrain/block_snippet_stereo.vtp'))
        polyData = segmentation.applyVoxelGrid(polyData, leafSize=0.01)
    else:
        polyData = ioUtils.readPolyData(os.path.join(dataDir, 'terrain/block_snippet.vtp'))

    vis.updatePolyData( polyData, 'walking snapshot trimmed', parent='continuous')
    if drcargs.args().directorConfigFile.find('atlas') != -1:
    	standingFootName = 'l_foot'
    else:
        standingFootName = 'leftFoot'

    standingFootFrame = robotStateModel.getLinkFrame(standingFootName)
    vis.updateFrame(standingFootFrame, standingFootName, parent='continuous', visible=False)

    # Step 2: find all the surfaces in front of the robot (about 0.75sec)
    clusters = segmentation.findHorizontalSurfaces(polyData)
    if (clusters is None):
        print "No cluster found, stop walking now!"
        return

    # Step 3: find the corners of the minimum bounding rectangles
    blocks,match_idx,groundPlane = cwdemo.extractBlocksFromSurfaces(clusters, standingFootFrame)

    footsteps = cwdemo.placeStepsOnBlocks(blocks, groundPlane, standingFootName, standingFootFrame)

    cwdemo.drawFittedSteps(footsteps)
    # cwdemo.sendPlanningRequest(footsteps)

#navigationPanel = navigationpanel.init(robotStateJointController, footstepsDriver)
navigationPanel = None
continuouswalkingDemo = continuouswalkingdemo.ContinousWalkingDemo(robotStateModel, footstepsPanel, footstepsDriver, playbackpanel, robotStateJointController, ikPlanner,
                                                                       teleopJointController, navigationPanel, cameraview, jointLimitChecker=None)

cwdemo = continuouswalkingDemo

# test 1 - Simple:
#processSingleBlock(robotStateModel, 0)
# test 2 - Staircase:
processSingleBlock(robotStateModel, 1)

'''
# test 3
processSnippet()

# test 4
continuouswalkingDemo.processContinuousStereo = True
processSnippet()
'''

if app.getTestingInteractiveEnabled():
    view.show()
    app.showObjectModel()
    app.start()

<commit_msg>Fix testContinuousWalking_staircase.py<commit_after>import os
import math
from director import robotsystem
from director.consoleapp import ConsoleApp
from director import ioUtils
from director import segmentation
from director import applogic
from director import visualization as vis
from director import continuouswalkingdemo
from director import objectmodel as om
from director import ikplanner
from director import navigationpanel
from director import cameraview
from director import playbackpanel
from director import drcargs

import drc as lcmdrc

app = ConsoleApp()
dataDir = app.getTestingDataDirectory()
# create a view
view = app.createView()
segmentation._defaultSegmentationView = view

#footstepsPanel = footstepsdriverpanel.init(footstepsDriver, robotStateModel, robotStateJointController, mapServerSource)
footstepsPanel = None
robotsystem.create(view, globals())

def processSingleBlock(robotStateModel, whichFile=0):

    if (whichFile == 0):
        polyData = ioUtils.readPolyData(os.path.join(dataDir, 'terrain/terrain_simple_ihmc.vtp'))
        vis.updatePolyData( polyData, 'terrain_simple_ihmc.vtp', parent='continuous')
    else:
        polyData = ioUtils.readPolyData(os.path.join(dataDir, 'terrain/terrain_flagstones_ihmc.vtp'))
        cwdemo.chosenTerrain = 'stairs'
        cwdemo.supportContact = lcmdrc.footstep_params_t.SUPPORT_GROUPS_MIDFOOT_TOE
        vis.updatePolyData( polyData, 'terrain_stairs_ihmc.vtp', parent='continuous')

    if drcargs.args().directorConfigFile.find('atlas') != -1:
    	standingFootName = 'l_foot'
    else:
        standingFootName = 'leftFoot'

    standingFootFrame = robotStateModel.getLinkFrame(standingFootName)
    vis.updateFrame(standingFootFrame, standingFootName, parent='continuous', visible=False)

    # Step 1: filter the data down to a box in front of the robot:
    polyData = cwdemo.getRecedingTerrainRegion(polyData, footstepsDriver.getFeetMidPoint(robotStateModel))

    # Step 2: find all the surfaces in front of the robot (about 0.75sec)
    clusters = segmentation.findHorizontalSurfaces(polyData)
    if (clusters is None):
        print "No cluster found, stop walking now!"
        return

    # Step 3: find the corners of the minimum bounding rectangles
    blocks,match_idx,groundPlane = cwdemo.extractBlocksFromSurfaces(clusters, standingFootFrame)

    footsteps = cwdemo.placeStepsOnBlocks(blocks, groundPlane, standingFootName, standingFootFrame)

    cwdemo.drawFittedSteps(footsteps)

def processSnippet():

    obj = om.getOrCreateContainer('continuous')
    om.getOrCreateContainer('cont debug', obj)

    if (continuouswalkingDemo.processContinuousStereo):
        polyData = ioUtils.readPolyData(os.path.join(dataDir, 'terrain/block_snippet_stereo.vtp'))
        polyData = segmentation.applyVoxelGrid(polyData, leafSize=0.01)
    else:
        polyData = ioUtils.readPolyData(os.path.join(dataDir, 'terrain/block_snippet.vtp'))

    vis.updatePolyData( polyData, 'walking snapshot trimmed', parent='continuous')
    if drcargs.args().directorConfigFile.find('atlas') != -1:
    	standingFootName = 'l_foot'
    else:
        standingFootName = 'leftFoot'

    standingFootFrame = robotStateModel.getLinkFrame(standingFootName)
    vis.updateFrame(standingFootFrame, standingFootName, parent='continuous', visible=False)

    # Step 2: find all the surfaces in front of the robot (about 0.75sec)
    clusters = segmentation.findHorizontalSurfaces(polyData)
    if (clusters is None):
        print "No cluster found, stop walking now!"
        return

    # Step 3: find the corners of the minimum bounding rectangles
    blocks,match_idx,groundPlane = cwdemo.extractBlocksFromSurfaces(clusters, standingFootFrame)

    footsteps = cwdemo.placeStepsOnBlocks(blocks, groundPlane, standingFootName, standingFootFrame)

    cwdemo.drawFittedSteps(footsteps)
    # cwdemo.sendPlanningRequest(footsteps)

#navigationPanel = navigationpanel.init(robotStateJointController, footstepsDriver)
navigationPanel = None
continuouswalkingDemo = continuouswalkingdemo.ContinousWalkingDemo(robotStateModel, footstepsPanel, footstepsDriver, playbackpanel, robotStateJointController, ikPlanner,
                                                                       teleopJointController, navigationPanel, cameraview)

cwdemo = continuouswalkingDemo

# test 1 - Simple:
#processSingleBlock(robotStateModel, 0)
# test 2 - Staircase:
processSingleBlock(robotStateModel, 1)

'''
# test 3
processSnippet()

# test 4
continuouswalkingDemo.processContinuousStereo = True
processSnippet()
'''

if app.getTestingInteractiveEnabled():
    view.show()
    app.showObjectModel()
    app.start()

<|endoftext|>


<commit_before>from lrrbot.main import bot
from lrrbot import twitch
from lrrbot import storage
from lrrbot import googlecalendar
from common import utils
from common.config import config
import asyncio
import json
import urllib.parse
import urllib.error

@utils.cache(24 * 60 * 60)
@asyncio.coroutine
def extract_new_channels(loop):
	data = yield from utils.http_request_coro(googlecalendar.EVENTS_URL % urllib.parse.quote(googlecalendar.CALENDAR_FAN), {
		"key": config["google_key"],
		"maxResults": 25000,
	})
	data = json.loads(data)

	channels = set()

	for event in data["items"]:
		if "location" in event:
			for token in event["location"].split():
				url = urllib.parse.urlparse(token)
				if url.scheme == "":
					url = urllib.parse.urlparse("https://" + token)
				if url.netloc in {"www.twitch.tv", "twitch.tv"}:
					try:
						channel = url.path.split("/")[1].lower()
					except IndexError:
						continue
					channels.add(channel)

	storage.data.setdefault("fan_channels", [])
	new_channels = list(channels.difference(storage.data["fan_channels"]))
	channels_data = yield from asyncio.gather(*[twitch.get_stream_info(channel) for channel in new_channels], loop=loop, return_exceptions=True)
	for channel, data in zip(new_channels, channels_data):
		if isinstance(data, dict) and "error" not in data:
			storage.data["fan_channels"].append(channel)
	storage.save()

@bot.command("live")
@utils.throttle()
@asyncio.coroutine
def live(lrrbot, conn, event, respond_to):
	"""
	Command: !live

	Post the currenly live fanstreamers.
	"""

	try:
		yield from extract_new_channels(lrrbot.loop)
	except urllib.error.HTTPError:
		pass

	streams = yield from asyncio.gather(*[
		twitch.get_stream_info(channel)
		for channel in storage.data.get("fan_channels", [])
	], loop=lrrbot.loop)
	streams = [data for data in streams if data.get("stream") is not None]
	if streams == []:
		return conn.privmsg(respond_to, "No fanstreamers currently live.")

	tag = "Currently live fanstreamers: "

	# Full message
	message = tag + ", ".join([
		"%s (%s) is playing %s (%s)" % (
			data["stream"]["channel"]["display_name"],
			data["stream"]["channel"]["url"],
			data["stream"]["game"],
			data["stream"]["channel"]["status"]
		) for data in streams
	])
	if len(message) <= 450:
		return conn.privmsg(respond_to, message)

	# Shorter message
	message = tag + ", ".join([
		"%s (%s) is playing %s" % (
			data["stream"]["channel"]["display_name"],
			data["stream"]["channel"]["url"],
			data["stream"]["game"],
		) for data in streams
	])
	if len(message) <= 450:
		return conn.privmsg(respond_to, message)

	# Shortest message
	message = tag + ", ".join([
		"%s (%s)" % (
			data["stream"]["channel"]["display_name"],
			data["stream"]["channel"]["url"]
		) for data in streams
	])
	return conn.privmsg(respond_to, utils.shorten(message, 450))
<commit_msg>!live register [CHANNEL]: Register a channel as a fan channel<commit_after>from lrrbot.main import bot
from lrrbot import twitch
from lrrbot import storage
from lrrbot import googlecalendar
from common import utils
from common.config import config
import asyncio
import json
import urllib.parse
import urllib.error
import irc.client

@utils.cache(24 * 60 * 60)
@asyncio.coroutine
def extract_new_channels(loop):
	data = yield from utils.http_request_coro(googlecalendar.EVENTS_URL % urllib.parse.quote(googlecalendar.CALENDAR_FAN), {
		"key": config["google_key"],
		"maxResults": 25000,
	})
	data = json.loads(data)

	channels = set()

	for event in data["items"]:
		if "location" in event:
			for token in event["location"].split():
				url = urllib.parse.urlparse(token)
				if url.scheme == "":
					url = urllib.parse.urlparse("https://" + token)
				if url.netloc in {"www.twitch.tv", "twitch.tv"}:
					try:
						channel = url.path.split("/")[1].lower()
					except IndexError:
						continue
					channels.add(channel)

	storage.data.setdefault("fan_channels", [])
	new_channels = list(channels.difference(storage.data["fan_channels"]))
	channels_data = yield from asyncio.gather(*[twitch.get_stream_info(channel) for channel in new_channels], loop=loop, return_exceptions=True)
	for channel, data in zip(new_channels, channels_data):
		if isinstance(data, dict) and "error" not in data:
			storage.data["fan_channels"].append(channel)
	storage.save()

@bot.command("live")
@utils.throttle()
@asyncio.coroutine
def live(lrrbot, conn, event, respond_to):
	"""
	Command: !live

	Post the currenly live fanstreamers.
	"""

	try:
		yield from extract_new_channels(lrrbot.loop)
	except urllib.error.HTTPError:
		pass

	streams = yield from asyncio.gather(*[
		twitch.get_stream_info(channel)
		for channel in storage.data.get("fan_channels", [])
	], loop=lrrbot.loop)
	streams = [data for data in streams if data.get("stream") is not None]
	if streams == []:
		return conn.privmsg(respond_to, "No fanstreamers currently live.")

	tag = "Currently live fanstreamers: "

	# Full message
	message = tag + ", ".join([
		"%s (%s) is playing %s (%s)" % (
			data["stream"]["channel"]["display_name"],
			data["stream"]["channel"]["url"],
			data["stream"]["game"],
			data["stream"]["channel"]["status"]
		) for data in streams
	])
	if len(message) <= 450:
		return conn.privmsg(respond_to, message)

	# Shorter message
	message = tag + ", ".join([
		"%s (%s) is playing %s" % (
			data["stream"]["channel"]["display_name"],
			data["stream"]["channel"]["url"],
			data["stream"]["game"],
		) for data in streams
	])
	if len(message) <= 450:
		return conn.privmsg(respond_to, message)

	# Shortest message
	message = tag + ", ".join([
		"%s (%s)" % (
			data["stream"]["channel"]["display_name"],
			data["stream"]["channel"]["url"]
		) for data in streams
	])
	return conn.privmsg(respond_to, utils.shorten(message, 450))

@bot.command("live register")
def register_self(lrrbot, conn, event, respond_to):
	"""
	Command: !live register

	Register your channel as a fanstreamer channel.
	"""
	channel = irc.client.NickMask(event.source).nick.lower()
	storage.data["fan_channels"] = list(set(storage.data.get("fan_channels", []) + [channel]))
	conn.privmsg(respond_to, "Channel '%s' added to the fanstreamer list." % channel)

@bot.command("live register (.*)")
@utils.mod_only
def register(lrrbot, conn, event, respond_to, channel):
	"""
	Command: !live register CHANNEL

	Register CHANNEL as a fanstreamer channel.
	"""
	storage.data["fan_channels"] = list(set(storage.data.get("fan_channels", []) + [channel]))
	conn.privmsg(respond_to, "Channel '%s' added to the fanstreamer list." % channel)
<|endoftext|>


<commit_before>#  Copyright 2015 Cisco Systems.
#
#    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.

from __future__ import absolute_import
import logging

from django.conf import settings
from magnumclient.v1 import client as magnum_client

from horizon import exceptions
from horizon.utils.memoized import memoized
from openstack_dashboard.api import base

LOG = logging.getLogger(__name__)

CLUSTER_TEMPLATE_CREATE_ATTRS = ['name', 'image_id', 'flavor_id',
                                 'master_flavor_id', 'keypair_id',
                                 'external_network_id', 'fixed_network',
                                 'dns_nameserver', 'docker_volume_size',
                                 'labels', 'coe', 'http_proxy', 'https_proxy',
                                 'no_proxy', 'network_driver', 'volume_driver',
                                 'public', 'registry_enabled', 'tls_disabled',
                                 'docker_storage_driver', 'fixed_subnet',
                                 'floating_ip_enabled', 'master_lb_enabled',
                                 'insecure_registry']

CLUSTER_CREATE_ATTRS = ['name', 'baymodel_id', 'node_count',
                        'discovery_url', 'cluster_create_timeout',
                        'master_count']

@memoized
def magnumclient(request):
    magnum_url = ""
    try:
        magnum_url = base.url_for(request, 'container-infra')
    except exceptions.ServiceCatalogException:
        LOG.debug('No Container Infrastructure Management service is '
                  'configured.')
        return None

    LOG.debug('magnumclient connection created using the token "%s" and url'
              '"%s"' % (request.user.token.id, magnum_url))

    insecure = getattr(settings, 'OPENSTACK_SSL_NO_VERIFY', False)
    cacert = getattr(settings, 'OPENSTACK_SSL_CACERT', None)

    c = magnum_client.Client(username=request.user.username,
                             project_id=request.user.tenant_id,
                             input_auth_token=request.user.token.id,
                             magnum_url=magnum_url,
                             insecure=insecure,
                             cacert=cacert)
    return c

def cluster_template_create(request, **kwargs):
    args = {}
    for (key, value) in kwargs.items():
        if key in CLUSTER_TEMPLATE_CREATE_ATTRS:
            args[str(key)] = str(value)
        else:
            raise exceptions.InvalidAttribute(
                "Key must be in %s" % ",".join(CLUSTER_TEMPLATE_CREATE_ATTRS))
        if key == "labels":
            labels = {}
            vals = value.split(",")
            for v in vals:
                kv = v.split("=", 1)
                labels[kv[0]] = kv[1]
            args["labels"] = labels
    return magnumclient(request).baymodels.create(**args)

def cluster_template_delete(request, id):
    return magnumclient(request).baymodels.delete(id)

def cluster_template_list(request, limit=None, marker=None, sort_key=None,
                          sort_dir=None, detail=True):
    return magnumclient(request).baymodels.list(limit, marker, sort_key,
                                                sort_dir, detail)

def cluster_template_show(request, id):
    return magnumclient(request).baymodels.get(id)

def cluster_create(request, **kwargs):
    args = {}
    for (key, value) in kwargs.items():
        if key in CLUSTER_CREATE_ATTRS:
            args[key] = value
        else:
            raise exceptions.InvalidAttribute(
                "Key must be in %s" % ",".join(CLUSTER_CREATE_ATTRS))
    return magnumclient(request).bays.create(**args)

def cluster_update(request, id, patch):
    return magnumclient(request).bays.update(id, patch)

def cluster_delete(request, id):
    return magnumclient(request).bays.delete(id)

def cluster_list(request, limit=None, marker=None, sort_key=None,
                 sort_dir=None, detail=True):
    return magnumclient(request).bays.list(limit, marker, sort_key,
                                           sort_dir, detail)

def cluster_show(request, id):
    return magnumclient(request).bays.get(id)
<commit_msg>Use BadRequest in REST API<commit_after>#  Copyright 2015 Cisco Systems.
#
#    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.

from __future__ import absolute_import
import logging

from django.conf import settings
from magnumclient.v1 import client as magnum_client

from horizon import exceptions
from horizon.utils.memoized import memoized
from openstack_dashboard.api import base

LOG = logging.getLogger(__name__)

CLUSTER_TEMPLATE_CREATE_ATTRS = ['name', 'image_id', 'flavor_id',
                                 'master_flavor_id', 'keypair_id',
                                 'external_network_id', 'fixed_network',
                                 'dns_nameserver', 'docker_volume_size',
                                 'labels', 'coe', 'http_proxy', 'https_proxy',
                                 'no_proxy', 'network_driver', 'volume_driver',
                                 'public', 'registry_enabled', 'tls_disabled',
                                 'docker_storage_driver', 'fixed_subnet',
                                 'floating_ip_enabled', 'master_lb_enabled',
                                 'insecure_registry']

CLUSTER_CREATE_ATTRS = ['name', 'baymodel_id', 'node_count',
                        'discovery_url', 'cluster_create_timeout',
                        'master_count']

@memoized
def magnumclient(request):
    magnum_url = ""
    try:
        magnum_url = base.url_for(request, 'container-infra')
    except exceptions.ServiceCatalogException:
        LOG.debug('No Container Infrastructure Management service is '
                  'configured.')
        return None

    LOG.debug('magnumclient connection created using the token "%s" and url'
              '"%s"' % (request.user.token.id, magnum_url))

    insecure = getattr(settings, 'OPENSTACK_SSL_NO_VERIFY', False)
    cacert = getattr(settings, 'OPENSTACK_SSL_CACERT', None)

    c = magnum_client.Client(username=request.user.username,
                             project_id=request.user.tenant_id,
                             input_auth_token=request.user.token.id,
                             magnum_url=magnum_url,
                             insecure=insecure,
                             cacert=cacert)
    return c

def cluster_template_create(request, **kwargs):
    args = {}
    for (key, value) in kwargs.items():
        if key in CLUSTER_TEMPLATE_CREATE_ATTRS:
            args[str(key)] = str(value)
        else:
            raise exceptions.BadRequest(
                "Key must be in %s" % ",".join(CLUSTER_TEMPLATE_CREATE_ATTRS))
        if key == "labels":
            labels = {}
            vals = value.split(",")
            for v in vals:
                kv = v.split("=", 1)
                labels[kv[0]] = kv[1]
            args["labels"] = labels
    return magnumclient(request).baymodels.create(**args)

def cluster_template_delete(request, id):
    return magnumclient(request).baymodels.delete(id)

def cluster_template_list(request, limit=None, marker=None, sort_key=None,
                          sort_dir=None, detail=True):
    return magnumclient(request).baymodels.list(limit, marker, sort_key,
                                                sort_dir, detail)

def cluster_template_show(request, id):
    return magnumclient(request).baymodels.get(id)

def cluster_create(request, **kwargs):
    args = {}
    for (key, value) in kwargs.items():
        if key in CLUSTER_CREATE_ATTRS:
            args[key] = value
        else:
            raise exceptions.BadRequest(
                "Key must be in %s" % ",".join(CLUSTER_CREATE_ATTRS))
    return magnumclient(request).bays.create(**args)

def cluster_update(request, id, patch):
    return magnumclient(request).bays.update(id, patch)

def cluster_delete(request, id):
    return magnumclient(request).bays.delete(id)

def cluster_list(request, limit=None, marker=None, sort_key=None,
                 sort_dir=None, detail=True):
    return magnumclient(request).bays.list(limit, marker, sort_key,
                                           sort_dir, detail)

def cluster_show(request, id):
    return magnumclient(request).bays.get(id)
<|endoftext|>


<commit_before># Copyright (c) 2012-2014, GPy authors (see AUTHORS.txt).
# Licensed under the BSD 3-clause license (see LICENSE.txt)

import numpy as np
from .gp import GP
from .parameterization.param import Param
from ..inference.latent_function_inference import var_dtc
from .. import likelihoods
from GPy.core.parameterization.variational import VariationalPosterior

import logging
logger = logging.getLogger("sparse gp")

class SparseGP(GP):
    """
    A general purpose Sparse GP model

    This model allows (approximate) inference using variational DTC or FITC
    (Gaussian likelihoods) as well as non-conjugate sparse methods based on
    these.

    This is not for missing data, as the implementation for missing data involves
    some inefficient optimization routine decisions.
    See missing data SparseGP implementation in py:class:'~GPy.models.sparse_gp_minibatch.SparseGPMiniBatch'.

    :param X: inputs
    :type X: np.ndarray (num_data x input_dim)
    :param likelihood: a likelihood instance, containing the observed data
    :type likelihood: GPy.likelihood.(Gaussian | EP | Laplace)
    :param kernel: the kernel (covariance function). See link kernels
    :type kernel: a GPy.kern.kern instance
    :param X_variance: The uncertainty in the measurements of X (Gaussian variance)
    :type X_variance: np.ndarray (num_data x input_dim) | None
    :param Z: inducing inputs
    :type Z: np.ndarray (num_inducing x input_dim)
    :param num_inducing: Number of inducing points (optional, default 10. Ignored if Z is not None)
    :type num_inducing: int

    """

    def __init__(self, X, Y, Z, kernel, likelihood, mean_function=None, X_variance=None, inference_method=None,
                 name='sparse gp', Y_metadata=None, normalizer=False):

        #pick a sensible inference method
        if inference_method is None:
            if isinstance(likelihood, likelihoods.Gaussian):
                inference_method = var_dtc.VarDTC(limit=3)
            else:
                #inference_method = ??
                raise NotImplementedError("what to do what to do?")
            print(("defaulting to ", inference_method, "for latent function inference"))

        self.Z = Param('inducing inputs', Z)
        self.num_inducing = Z.shape[0]

        GP.__init__(self, X, Y, kernel, likelihood, mean_function, inference_method=inference_method, name=name, Y_metadata=Y_metadata, normalizer=normalizer)

        logger.info("Adding Z as parameter")
        self.link_parameter(self.Z, index=0)
        self.posterior = None

    @property
    def _predictive_variable(self):
        return self.Z

    def has_uncertain_inputs(self):
        return isinstance(self.X, VariationalPosterior)

    def set_Z(self, Z, trigger_update=True):
        if trigger_update: self.update_model(False)
        self.unlink_parameter(self.Z)
        self.Z = Param('inducing inputs',Z)
        self.link_parameter(self.Z, index=0)
        if trigger_update: self.update_model(True)

    def parameters_changed(self):
        self.posterior, self._log_marginal_likelihood, self.grad_dict = \
        self.inference_method.inference(self.kern, self.X, self.Z, self.likelihood,
                                        self.Y, Y_metadata=self.Y_metadata,
                                        mean_function=self.mean_function)
        self._update_gradients()

    def _update_gradients(self):
        self.likelihood.update_gradients(self.grad_dict['dL_dthetaL'])
        if self.mean_function is not None:
            self.mean_function.update_gradients(self.grad_dict['dL_dm'], self.X)

        if isinstance(self.X, VariationalPosterior):
            #gradients wrt kernel
            dL_dKmm = self.grad_dict['dL_dKmm']
            self.kern.update_gradients_full(dL_dKmm, self.Z, None)
            kerngrad = self.kern.gradient.copy()
            self.kern.update_gradients_expectations(variational_posterior=self.X,
                                                    Z=self.Z,
                                                    dL_dpsi0=self.grad_dict['dL_dpsi0'],
                                                    dL_dpsi1=self.grad_dict['dL_dpsi1'],
                                                    dL_dpsi2=self.grad_dict['dL_dpsi2'])
            self.kern.gradient += kerngrad

            #gradients wrt Z
            self.Z.gradient = self.kern.gradients_X(dL_dKmm, self.Z)
            self.Z.gradient += self.kern.gradients_Z_expectations(
                               self.grad_dict['dL_dpsi0'],
                               self.grad_dict['dL_dpsi1'],
                               self.grad_dict['dL_dpsi2'],
                               Z=self.Z,
                               variational_posterior=self.X)
        else:
            #gradients wrt kernel
            self.kern.update_gradients_diag(self.grad_dict['dL_dKdiag'], self.X)
            kerngrad = self.kern.gradient.copy()
            self.kern.update_gradients_full(self.grad_dict['dL_dKnm'], self.X, self.Z)
            kerngrad += self.kern.gradient
            self.kern.update_gradients_full(self.grad_dict['dL_dKmm'], self.Z, None)
            self.kern.gradient += kerngrad
            #gradients wrt Z
            self.Z.gradient = self.kern.gradients_X(self.grad_dict['dL_dKmm'], self.Z)
            self.Z.gradient += self.kern.gradients_X(self.grad_dict['dL_dKnm'].T, self.Z, self.X)
        self._Zgrad = self.Z.gradient.copy()
<commit_msg>fix: #590<commit_after># Copyright (c) 2012-2014, GPy authors (see AUTHORS.txt).
# Licensed under the BSD 3-clause license (see LICENSE.txt)

import numpy as np
from .gp import GP
from .parameterization.param import Param
from ..inference.latent_function_inference import var_dtc
from .. import likelihoods
from GPy.core.parameterization.variational import VariationalPosterior

import logging
logger = logging.getLogger("sparse gp")

class SparseGP(GP):
    """
    A general purpose Sparse GP model

    This model allows (approximate) inference using variational DTC or FITC
    (Gaussian likelihoods) as well as non-conjugate sparse methods based on
    these.

    This is not for missing data, as the implementation for missing data involves
    some inefficient optimization routine decisions.
    See missing data SparseGP implementation in py:class:'~GPy.models.sparse_gp_minibatch.SparseGPMiniBatch'.

    :param X: inputs
    :type X: np.ndarray (num_data x input_dim)
    :param likelihood: a likelihood instance, containing the observed data
    :type likelihood: GPy.likelihood.(Gaussian | EP | Laplace)
    :param kernel: the kernel (covariance function). See link kernels
    :type kernel: a GPy.kern.kern instance
    :param X_variance: The uncertainty in the measurements of X (Gaussian variance)
    :type X_variance: np.ndarray (num_data x input_dim) | None
    :param Z: inducing inputs
    :type Z: np.ndarray (num_inducing x input_dim)
    :param num_inducing: Number of inducing points (optional, default 10. Ignored if Z is not None)
    :type num_inducing: int

    """

    def __init__(self, X, Y, Z, kernel, likelihood, mean_function=None, X_variance=None, inference_method=None,
                 name='sparse gp', Y_metadata=None, normalizer=False):

        #pick a sensible inference method
        if inference_method is None:
            if isinstance(likelihood, likelihoods.Gaussian):
                inference_method = var_dtc.VarDTC(limit=3)
            else:
                #inference_method = ??
                raise NotImplementedError("what to do what to do?")
            print(("defaulting to ", inference_method, "for latent function inference"))

        self.Z = Param('inducing inputs', Z)
        self.num_inducing = Z.shape[0]

        GP.__init__(self, X, Y, kernel, likelihood, mean_function, inference_method=inference_method, name=name, Y_metadata=Y_metadata, normalizer=normalizer)

        logger.info("Adding Z as parameter")
        self.link_parameter(self.Z, index=0)
        self.posterior = None

    @property
    def _predictive_variable(self):
        return self.Z

    def has_uncertain_inputs(self):
        return isinstance(self.X, VariationalPosterior)

    def set_Z(self, Z, trigger_update=True):
        if trigger_update: self.update_model(False)
        self.unlink_parameter(self.Z)
        self.Z = Param('inducing inputs',Z)
        self.link_parameter(self.Z, index=0)
        if trigger_update: self.update_model(True)

    def parameters_changed(self):
        self.posterior, self._log_marginal_likelihood, self.grad_dict = \
        self.inference_method.inference(self.kern, self.X, self.Z, self.likelihood,
                                        self.Y_normalized, Y_metadata=self.Y_metadata,
                                        mean_function=self.mean_function)
        self._update_gradients()

    def _update_gradients(self):
        self.likelihood.update_gradients(self.grad_dict['dL_dthetaL'])
        if self.mean_function is not None:
            self.mean_function.update_gradients(self.grad_dict['dL_dm'], self.X)

        if isinstance(self.X, VariationalPosterior):
            #gradients wrt kernel
            dL_dKmm = self.grad_dict['dL_dKmm']
            self.kern.update_gradients_full(dL_dKmm, self.Z, None)
            kerngrad = self.kern.gradient.copy()
            self.kern.update_gradients_expectations(variational_posterior=self.X,
                                                    Z=self.Z,
                                                    dL_dpsi0=self.grad_dict['dL_dpsi0'],
                                                    dL_dpsi1=self.grad_dict['dL_dpsi1'],
                                                    dL_dpsi2=self.grad_dict['dL_dpsi2'])
            self.kern.gradient += kerngrad

            #gradients wrt Z
            self.Z.gradient = self.kern.gradients_X(dL_dKmm, self.Z)
            self.Z.gradient += self.kern.gradients_Z_expectations(
                               self.grad_dict['dL_dpsi0'],
                               self.grad_dict['dL_dpsi1'],
                               self.grad_dict['dL_dpsi2'],
                               Z=self.Z,
                               variational_posterior=self.X)
        else:
            #gradients wrt kernel
            self.kern.update_gradients_diag(self.grad_dict['dL_dKdiag'], self.X)
            kerngrad = self.kern.gradient.copy()
            self.kern.update_gradients_full(self.grad_dict['dL_dKnm'], self.X, self.Z)
            kerngrad += self.kern.gradient
            self.kern.update_gradients_full(self.grad_dict['dL_dKmm'], self.Z, None)
            self.kern.gradient += kerngrad
            #gradients wrt Z
            self.Z.gradient = self.kern.gradients_X(self.grad_dict['dL_dKmm'], self.Z)
            self.Z.gradient += self.kern.gradients_X(self.grad_dict['dL_dKnm'].T, self.Z, self.X)
        self._Zgrad = self.Z.gradient.copy()
<|endoftext|>