#
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements.  See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You 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.

import sys
import unittest

import pandas as pd

from apache_beam.dataframe import doctests
from apache_beam.dataframe.frames import PD_VERSION
from apache_beam.dataframe.pandas_top_level_functions import _is_top_level_function

@unittest.skipIf(sys.platform == 'win32', '[BEAM-10626]')
class DoctestTest(unittest.TestCase):
  def test_ndframe_tests(self):
    # IO methods are tested in io_test.py
    skip_writes = {
        f'pandas.core.generic.NDFrame.{name}': ['*']
        for name in dir(pd.core.generic.NDFrame) if name.startswith('to_')
    }

    result = doctests.testmod(
        pd.core.generic,
        use_beam=False,
        report=True,
        wont_implement_ok={
            'pandas.core.generic.NDFrame.head': ['*'],
            'pandas.core.generic.NDFrame.shift': [
                'df.shift(periods=3)',
                'df.shift(periods=3, fill_value=0)',
            ],
            'pandas.core.generic.NDFrame.tail': ['*'],
            'pandas.core.generic.NDFrame.take': ['*'],
            'pandas.core.generic.NDFrame.values': ['*'],
            'pandas.core.generic.NDFrame.tz_localize': [
                "s.tz_localize('CET', ambiguous='infer')",
                # np.array is not a deferred object. This use-case is possible
                # with a deferred Series though, which is tested in
                # frames_test.py
                "s.tz_localize('CET', ambiguous=np.array([True, True, False]))",
            ],
            'pandas.core.generic.NDFrame.truncate': [
                # These inputs rely on tail (wont implement, order
                # sensitive) for verification
                "df.tail()",
                "df.truncate(before=pd.Timestamp('2016-01-05'),\n"
                "            after=pd.Timestamp('2016-01-10')).tail()",
                "df.truncate('2016-01-05', '2016-01-10').tail()",
                "df.loc['2016-01-05':'2016-01-10', :].tail()"
            ],
            'pandas.core.generic.NDFrame.replace': [
                "s.replace([1, 2], method='bfill')",
                # Relies on method='pad'
                "s.replace('a')",
                # Relies on method='pad'
                # value=None is not valid for pandas < 1.4
                "s.replace('a', None)",
                # Implicitly uses method='pad', but output doesn't rely on that
                # behavior. Verified indepently in
                # frames_test.py::DeferredFrameTest::test_replace
                "df.replace(regex={r'^ba.$': 'new', 'foo': 'xyz'})"
            ],
            'pandas.core.generic.NDFrame.fillna': [
                'df.fillna(method=\'ffill\')',
                'df.fillna(method="ffill")',
                'df.fillna(value=values, limit=1)',
            ],
            'pandas.core.generic.NDFrame.sort_values': ['*'],
            'pandas.core.generic.NDFrame.mask': [
                'df.where(m, -df) == np.where(m, df, -df)'
            ],
            'pandas.core.generic.NDFrame.where': [
                'df.where(m, -df) == np.where(m, df, -df)'
            ],
            'pandas.core.generic.NDFrame.interpolate': ['*'],
            'pandas.core.generic.NDFrame.resample': ['*'],
            'pandas.core.generic.NDFrame.rolling': ['*'],
            # argsort wont implement
            'pandas.core.generic.NDFrame.abs': [
                'df.loc[(df.c - 43).abs().argsort()]',
            ],
            'pandas.core.generic.NDFrame.reindex': ['*'],
            'pandas.core.generic.NDFrame.pct_change': ['*'],
            'pandas.core.generic.NDFrame.asof': ['*'],
            'pandas.core.generic.NDFrame.infer_objects': ['*'],
            'pandas.core.generic.NDFrame.ewm': ['*'],
            'pandas.core.generic.NDFrame.expanding': ['*'],
            'pandas.core.generic.NDFrame.get': ['*'],
        },
        not_implemented_ok={
            'pandas.core.generic.NDFrame.asof': ['*'],
            'pandas.core.generic.NDFrame.at_time': ['*'],
            'pandas.core.generic.NDFrame.between_time': ['*'],
            'pandas.core.generic.NDFrame.ewm': ['*'],
            'pandas.core.generic.NDFrame.expanding': ['*'],
            'pandas.core.generic.NDFrame.flags': ['*'],
            'pandas.core.generic.NDFrame.rank': ['*'],
            'pandas.core.generic.NDFrame.reindex_like': ['*'],
            'pandas.core.generic.NDFrame.replace': ['*'],
            'pandas.core.generic.NDFrame.sample': ['*'],
            'pandas.core.generic.NDFrame.set_flags': ['*'],
            'pandas.core.generic.NDFrame.squeeze': ['*'],
            'pandas.core.generic.NDFrame.truncate': ['*'],
        },
        skip={
            # Internal test
            'pandas.core.generic.NDFrame._set_axis_name': ['*'],
            # Fails to construct test series. asfreq is not implemented anyway.
            'pandas.core.generic.NDFrame.asfreq': ['*'],
            'pandas.core.generic.NDFrame.astype': ['*'],
            'pandas.core.generic.NDFrame.convert_dtypes': ['*'],
            'pandas.core.generic.NDFrame.copy': ['*'],
            'pandas.core.generic.NDFrame.droplevel': ['*'],
            'pandas.core.generic.NDFrame.get': ['*'],
            'pandas.core.generic.NDFrame.rank': [
                # Modified dataframe
                'df'
            ],
            'pandas.core.generic.NDFrame.rename': [
                # Seems to be an upstream bug. The actual error has a different
                # message:
                #   TypeError: Index(...) must be called with a collection of
                #   some kind, 2 was passed
                # pandas doctests only verify the type of exception
                'df.rename(2)'
            ],
            # For pandas >= 1.4, rename is changed to _rename
            'pandas.core.generic.NDFrame._rename': [
                # Seems to be an upstream bug. The actual error has a different
                # message:
                #   TypeError: Index(...) must be called with a collection of
                #   some kind, 2 was passed
                # pandas doctests only verify the type of exception
                'df.rename(2)'
            ],
            # Tests rely on setting index
            'pandas.core.generic.NDFrame.rename_axis': ['*'],
            # Raises right exception, but testing framework has matching issues.
            'pandas.core.generic.NDFrame.replace': [
                "df.replace({'a string': 'new value', True: False})  # raises"
            ],
            'pandas.core.generic.NDFrame.squeeze': ['*'],

            # NameError
            'pandas.core.generic.NDFrame.resample': ['df'],

            # Skipped so we don't need to install natsort
            'pandas.core.generic.NDFrame.sort_values': [
                'from natsort import index_natsorted',
                'df.sort_values(\n'
                '   by="time",\n'
                '   key=lambda x: np.argsort(index_natsorted(df["time"]))\n'
                ')'
            ],
            **skip_writes
        })
    self.assertEqual(result.failed, 0)

  def test_dataframe_tests(self):
    result = doctests.testmod(
        pd.core.frame,
        use_beam=False,
        report=True,
        wont_implement_ok={
            'pandas.core.frame.DataFrame.T': ['*'],
            'pandas.core.frame.DataFrame.cummax': ['*'],
            'pandas.core.frame.DataFrame.cummin': ['*'],
            'pandas.core.frame.DataFrame.cumsum': ['*'],
            'pandas.core.frame.DataFrame.cumprod': ['*'],
            'pandas.core.frame.DataFrame.diff': ['*'],
            'pandas.core.frame.DataFrame.fillna': [
                'df.fillna(method=\'ffill\')',
                'df.fillna(method="ffill")',
                'df.fillna(value=values, limit=1)',
            ],
            'pandas.core.frame.DataFrame.items': ['*'],
            'pandas.core.frame.DataFrame.itertuples': ['*'],
            'pandas.core.frame.DataFrame.iterrows': ['*'],
            'pandas.core.frame.DataFrame.iteritems': ['*'],
            # default keep is 'first'
            'pandas.core.frame.DataFrame.nlargest': [
                "df.nlargest(3, 'population')",
                "df.nlargest(3, ['population', 'GDP'])",
                "df.nlargest(3, 'population', keep='last')"
            ],
            'pandas.core.frame.DataFrame.nsmallest': [
                "df.nsmallest(3, 'population')",
                "df.nsmallest(3, ['population', 'GDP'])",
                "df.nsmallest(3, 'population', keep='last')",
            ],
            'pandas.core.frame.DataFrame.replace': [
                "s.replace([1, 2], method='bfill')",
                # Relies on method='pad'
                "s.replace('a')",
                # Relies on method='pad'
                # value=None is not valid for pandas < 1.4
                "s.replace('a', None)",
                # Implicitly uses method='pad', but output doesn't rely on that
                # behavior. Verified indepently in
                # frames_test.py::DeferredFrameTest::test_replace
                "df.replace(regex={r'^ba.$': 'new', 'foo': 'xyz'})"
            ],
            'pandas.core.frame.DataFrame.to_records': ['*'],
            'pandas.core.frame.DataFrame.to_dict': ['*'],
            'pandas.core.frame.DataFrame.to_numpy': ['*'],
            'pandas.core.frame.DataFrame.to_string': ['*'],
            'pandas.core.frame.DataFrame.transpose': ['*'],
            'pandas.core.frame.DataFrame.shape': ['*'],
            'pandas.core.frame.DataFrame.shift': [
                'df.shift(periods=3)',
                'df.shift(periods=3, fill_value=0)',
            ],
            'pandas.core.frame.DataFrame.unstack': ['*'],
            'pandas.core.frame.DataFrame.memory_usage': ['*'],
            'pandas.core.frame.DataFrame.info': ['*'],
            # Not equal to df.agg('mode', axis='columns', numeric_only=True)
            # because there can be multiple columns if a row has more than one
            # mode
            'pandas.core.frame.DataFrame.mode': [
                "df.mode(axis='columns', numeric_only=True)"
            ],
            'pandas.core.frame.DataFrame.append': [
                'df.append(df2, ignore_index=True)',
                "for i in range(5):\n" +
                "    df = df.append({'A': i}, ignore_index=True)",
            ],
            'pandas.core.frame.DataFrame.sort_index': ['*'],
            'pandas.core.frame.DataFrame.sort_values': ['*'],
            'pandas.core.frame.DataFrame.melt': [
                "df.melt(id_vars=['A'], value_vars=['B'])",
                "df.melt(id_vars=['A'], value_vars=['B', 'C'])",
                "df.melt(col_level=0, id_vars=['A'], value_vars=['B'])",
                "df.melt(id_vars=[('A', 'D')], value_vars=[('B', 'E')])",
                "df.melt(id_vars=['A'], value_vars=['B'],\n" +
                "        var_name='myVarname', value_name='myValname')"
            ],
            # Most keep= options are order-sensitive
            'pandas.core.frame.DataFrame.drop_duplicates': ['*'],
            'pandas.core.frame.DataFrame.duplicated': [
                'df.duplicated()',
                "df.duplicated(keep='last')",
                "df.duplicated(subset=['brand'])",
            ],
            'pandas.core.frame.DataFrame.reindex': ['*'],
            'pandas.core.frame.DataFrame.dot': [
                # reindex not supported
                's2 = s.reindex([1, 0, 2, 3])',
            ],
            'pandas.core.frame.DataFrame.resample': ['*'],
            'pandas.core.frame.DataFrame.values': ['*'],
        },
        not_implemented_ok={
            'pandas.core.frame.DataFrame.transform': [
                # str arg not supported. Tested with np.sum in
                # frames_test.py::DeferredFrameTest::test_groupby_transform_sum
                "df.groupby('Date')['Data'].transform('sum')",
            ],
            'pandas.core.frame.DataFrame.swaplevel': ['*'],
            'pandas.core.frame.DataFrame.melt': ['*'],
            'pandas.core.frame.DataFrame.reindex_axis': ['*'],
            'pandas.core.frame.DataFrame.round': [
                'df.round(decimals)',
            ],

            # We should be able to support pivot and pivot_table for categorical
            # columns
            'pandas.core.frame.DataFrame.pivot': ['*'],

            # Trivially elementwise for axis=columns. Relies on global indexing
            # for axis=rows.
            # Difficult to determine proxy, need to inspect function
            'pandas.core.frame.DataFrame.apply': ['*'],

            # Cross-join not implemented
            'pandas.core.frame.DataFrame.merge': [
                "df1.merge(df2, how='cross')"
            ],

            # TODO(BEAM-11711)
            'pandas.core.frame.DataFrame.set_index': [
                "df.set_index([s, s**2])",
            ],

            'pandas.core.frame.DataFrame.set_axis': [
                "df.set_axis(range(0,2), axis='index')",
            ],

            # TODO(BEAM-12495)
            'pandas.core.frame.DataFrame.value_counts': [
              'df.value_counts(dropna=False)'
            ],
        },
        skip={
            # DataFrame construction from a dictionary and
            # Series requires using the len() function, which
            # is a non-deferred operation that we do not allow
            'pandas.core.frame.DataFrame': [
                'pd.DataFrame(data=d, index=[0, 1, 2, 3])',
            ],
            # s2 created with reindex
            'pandas.core.frame.DataFrame.dot': [
                'df.dot(s2)',
            ],

            'pandas.core.frame.DataFrame.resample': ['df'],
            'pandas.core.frame.DataFrame.asfreq': ['*'],
            # Throws NotImplementedError when modifying df
            'pandas.core.frame.DataFrame.axes': [
                # Returns deferred index.
                'df.axes',
            ],
            # Skipped because the relies on loc to set cells in df2
            'pandas.core.frame.DataFrame.compare': ['*'],
            'pandas.core.frame.DataFrame.cov': [
                # Relies on setting entries ahead of time.
                "df.loc[df.index[:5], 'a'] = np.nan",
                "df.loc[df.index[5:10], 'b'] = np.nan",
                'df.cov(min_periods=12)',
            ],
            'pandas.core.frame.DataFrame.rename': [
                # Returns deferred index.
                'df.index',
                'df.rename(index=str).index',
            ],
            'pandas.core.frame.DataFrame.set_index': [
                # TODO(BEAM-11711): This could pass in the index as
                # a DeferredIndex, and we should fail it as order-sensitive.
                "df.set_index([pd.Index([1, 2, 3, 4]), 'year'])",
            ],
            'pandas.core.frame.DataFrame.set_axis': [
                # This should pass as set_axis(axis='columns')
                # and fail with set_axis(axis='index')
                "df.set_axis(['a', 'b', 'c'], axis='index')"
            ],
            'pandas.core.frame.DataFrame.to_markdown': ['*'],
            'pandas.core.frame.DataFrame.to_parquet': ['*'],

            # Raises right exception, but testing framework has matching issues.
            # Tested in `frames_test.py`.
            'pandas.core.frame.DataFrame.insert': [
                'df',
                'df.insert(1, "newcol", [99, 99])',
                'df.insert(0, "col1", [100, 100], allow_duplicates=True)'
            ],

            'pandas.core.frame.DataFrame.to_records': [
                'df.index = df.index.rename("I")',
                'index_dtypes = f"<S{df.index.str.len().max()}"', # 1.x
                'index_dtypes = "<S{}".format(df.index.str.len().max())', #0.x
                'df.to_records(index_dtypes=index_dtypes)',
            ],
            # These tests use the static method pd.pivot_table, which doesn't
            # actually raise NotImplementedError
            'pandas.core.frame.DataFrame.pivot_table': ['*'],
            # Expected to raise a ValueError, but we raise NotImplementedError
            'pandas.core.frame.DataFrame.pivot': [
                "df.pivot(index='foo', columns='bar', values='baz')"
            ],
            'pandas.core.frame.DataFrame.append': [
                'df',
                # pylint: disable=line-too-long
                "pd.concat([pd.DataFrame([i], columns=['A']) for i in range(5)],\n"
                "          ignore_index=True)"
            ],
            'pandas.core.frame.DataFrame.eval': ['df'],
            'pandas.core.frame.DataFrame.melt': [
                "df.columns = [list('ABC'), list('DEF')]", "df"
            ],
            'pandas.core.frame.DataFrame.merge': [
                # Order-sensitive index, checked in frames_test.py.
                "df1.merge(df2, left_on='lkey', right_on='rkey')",
                "df1.merge(df2, left_on='lkey', right_on='rkey',\n"
                "          suffixes=('_left', '_right'))",
                "df1.merge(df2, how='left', on='a')",
            ],
            # Raises right exception, but testing framework has matching issues.
            'pandas.core.frame.DataFrame.replace': [
                "df.replace({'a string': 'new value', True: False})  # raises"
            ],
            'pandas.core.frame.DataFrame.to_sparse': ['type(df)'],

            # Skipped because "seen_wont_implement" is reset before getting to
            # these calls, so the NameError they raise is not ignored.
            'pandas.core.frame.DataFrame.T': [
                'df1_transposed.dtypes', 'df2_transposed.dtypes'
            ],
            'pandas.core.frame.DataFrame.transpose': [
                'df1_transposed.dtypes', 'df2_transposed.dtypes'
            ],
            # Skipped because the relies on iloc to set a cell to NA. Test is
            # replicated in frames_test::DeferredFrameTest::test_applymap.
            'pandas.core.frame.DataFrame.applymap': [
                'df_copy.iloc[0, 0] = pd.NA',
                "df_copy.applymap(lambda x: len(str(x)), na_action='ignore')",
            ],
            # Skipped so we don't need to install natsort
            'pandas.core.frame.DataFrame.sort_values': [
                'from natsort import index_natsorted',
                'df.sort_values(\n'
                '   by="time",\n'
                '   key=lambda x: np.argsort(index_natsorted(df["time"]))\n'
                ')'
            ],
            # Mode that we don't yet support, documentation added in pandas
            # 1.2.0 (https://github.com/pandas-dev/pandas/issues/35912)
            'pandas.core.frame.DataFrame.aggregate': [
                "df.agg(x=('A', max), y=('B', 'min'), z=('C', np.mean))"
            ],
        })
    self.assertEqual(result.failed, 0)

  def test_series_tests(self):
    result = doctests.testmod(
        pd.core.series,
        use_beam=False,
        report=True,
        wont_implement_ok={
            'pandas.core.series.Series.__array__': ['*'],
            'pandas.core.series.Series.array': ['*'],
            'pandas.core.series.Series.cummax': ['*'],
            'pandas.core.series.Series.cummin': ['*'],
            'pandas.core.series.Series.cumsum': ['*'],
            'pandas.core.series.Series.cumprod': ['*'],
            'pandas.core.series.Series.diff': ['*'],
            'pandas.core.series.Series.dot': [
                's.dot(arr)',  # non-deferred result
            ],
            'pandas.core.series.Series.fillna': [
                'df.fillna(method=\'ffill\')',
                'df.fillna(method="ffill")',
                'df.fillna(value=values, limit=1)',
            ],
            'pandas.core.series.Series.info': ['*'],
            'pandas.core.series.Series.items': ['*'],
            'pandas.core.series.Series.iteritems': ['*'],
            # default keep is 'first'
            'pandas.core.series.Series.nlargest': [
                "s.nlargest()",
                "s.nlargest(3)",
                "s.nlargest(3, keep='last')",
            ],
            'pandas.core.series.Series.memory_usage': ['*'],
            'pandas.core.series.Series.nsmallest': [
                "s.nsmallest()",
                "s.nsmallest(3)",
                "s.nsmallest(3, keep='last')",
            ],
            'pandas.core.series.Series.pop': ['*'],
            'pandas.core.series.Series.searchsorted': ['*'],
            'pandas.core.series.Series.shift': [
                'df.shift(periods=3)',
                'df.shift(periods=3, fill_value=0)',
            ],
            'pandas.core.series.Series.take': ['*'],
            'pandas.core.series.Series.to_dict': ['*'],
            'pandas.core.series.Series.unique': ['*'],
            'pandas.core.series.Series.unstack': ['*'],
            'pandas.core.series.Series.values': ['*'],
            'pandas.core.series.Series.view': ['*'],
            'pandas.core.series.Series.append': [
                's1.append(s2, ignore_index=True)',
            ],
            'pandas.core.series.Series.replace': [
                "s.replace([1, 2], method='bfill')",
                # Relies on method='pad'
                "s.replace('a')",
                # Relies on method='pad'
                # value=None is not valid for pandas < 1.4
                "s.replace('a', None)",
                # Implicitly uses method='pad', but output doesn't rely on that
                # behavior. Verified indepently in
                # frames_test.py::DeferredFrameTest::test_replace
                "df.replace(regex={r'^ba.$': 'new', 'foo': 'xyz'})"
            ],
            'pandas.core.series.Series.sort_index': ['*'],
            'pandas.core.series.Series.sort_values': ['*'],
            'pandas.core.series.Series.argmax': ['*'],
            'pandas.core.series.Series.argmin': ['*'],
            'pandas.core.series.Series.drop_duplicates': [
                's.drop_duplicates()',
                "s.drop_duplicates(keep='last')",
            ],
            'pandas.core.series.Series.reindex': ['*'],
            'pandas.core.series.Series.autocorr': ['*'],
            'pandas.core.series.Series.repeat': ['s.repeat([1, 2, 3])'],
            'pandas.core.series.Series.resample': ['*'],
            'pandas.core.series.Series': ['ser.iloc[0] = 999'],
        },
        not_implemented_ok={
            'pandas.core.series.Series.transform': [
                # str arg not supported. Tested with np.sum in
                # frames_test.py::DeferredFrameTest::test_groupby_transform_sum
                "df.groupby('Date')['Data'].transform('sum')",
            ],
            'pandas.core.series.Series.groupby': [
                'ser.groupby(["a", "b", "a", "b"]).mean()',
                'ser.groupby(["a", "b", "a", np.nan]).mean()',
                'ser.groupby(["a", "b", "a", np.nan], dropna=False).mean()',
            ],
            'pandas.core.series.Series.swaplevel' :['*']
        },
        skip={
            # Relies on setting values with iloc
            'pandas.core.series.Series': ['ser', 'r'],
            'pandas.core.series.Series.groupby': [
                # TODO(BEAM-11393): This example requires aligning two series
                # with non-unique indexes. It only works in pandas because
                # pandas can recognize the indexes are identical and elide the
                # alignment.
                'ser.groupby(ser > 100).mean()',
            ],
            'pandas.core.series.Series.asfreq': ['*'],
            # error formatting
            'pandas.core.series.Series.append': [
                's1.append(s2, verify_integrity=True)',
            ],
            'pandas.core.series.Series.cov': [
                # Differs in LSB on jenkins.
                "s1.cov(s2)",
            ],
            # Skipped idxmax/idxmin due an issue with the test framework
            'pandas.core.series.Series.idxmin': ['s.idxmin()'],
            'pandas.core.series.Series.idxmax': ['s.idxmax()'],
            'pandas.core.series.Series.duplicated': ['*'],
            'pandas.core.series.Series.set_axis': ['*'],
            'pandas.core.series.Series.nonzero': ['*'],
            'pandas.core.series.Series.pop': ['ser'],  # testing side effect
            # Raises right exception, but testing framework has matching issues.
            'pandas.core.series.Series.replace': [
                "df.replace({'a string': 'new value', True: False})  # raises"
            ],
            'pandas.core.series.Series.searchsorted': [
                # This doctest seems to be incorrectly parsed.
                "x = pd.Categorical(['apple', 'bread', 'bread',"
            ],
            'pandas.core.series.Series.to_csv': ['*'],
            'pandas.core.series.Series.to_markdown': ['*'],
            'pandas.core.series.Series.update': ['*'],
            'pandas.core.series.Series.view': [
                # Inspection after modification.
                's'
            ],
            'pandas.core.series.Series.resample': ['df'],
        })
    self.assertEqual(result.failed, 0)

  def test_string_tests(self):
    if PD_VERSION < (1, 2):
      module = pd.core.strings
    else:
      # Definitions were moved to accessor in pandas 1.2.0
      module = pd.core.strings.accessor

    module_name = module.__name__

    result = doctests.testmod(
        module,
        use_beam=False,
        wont_implement_ok={
            # These methods can accept deferred series objects, but not lists
            f'{module_name}.StringMethods.cat': [
                "s.str.cat(['A', 'B', 'C', 'D'], sep=',')",
                "s.str.cat(['A', 'B', 'C', 'D'], sep=',', na_rep='-')",
                "s.str.cat(['A', 'B', 'C', 'D'], na_rep='-')"
            ],
            f'{module_name}.StringMethods.repeat': [
                's.str.repeat(repeats=[1, 2, 3])'
            ],
            f'{module_name}.str_repeat': ['s.str.repeat(repeats=[1, 2, 3])'],
            # get_dummies pandas examples are not casted to CategoricalDtype
            # Must be CategoricalDtype to work in Beam
            f'{module_name}.StringMethods.get_dummies': ['*'],
            f'{module_name}.str_get_dummies': ['*'],
            f'{module_name}.StringMethods': ['s.str.split("_")'],
            f'{module_name}.StringMethods.rsplit': ['*'],
            f'{module_name}.StringMethods.split': ['*'],
        },
        skip={
            # count() on Series with a NaN produces mismatched type if we
            # have a NaN-only partition.
            f'{module_name}.StringMethods.count': ["s.str.count('a')"],
            f'{module_name}.str_count': ["s.str.count('a')"],

            # Bad test strings in pandas 1.1.x
            f'{module_name}.str_replace': [
                "pd.Series(['foo', 'fuz', np.nan]).str.replace('f', repr)"
            ],
            f'{module_name}.StringMethods.replace': [
                "pd.Series(['foo', 'fuz', np.nan]).str.replace('f', repr)"
            ],

            # output has incorrect formatting in 1.2.x
            f'{module_name}.StringMethods.extractall': ['*']
        })
    self.assertEqual(result.failed, 0)

  def test_datetime_tests(self):
    # TODO(BEAM-10721)
    indexes_accessors_result = doctests.testmod(
        pd.core.indexes.accessors,
        use_beam=False,
        skip={
            'pandas.core.indexes.accessors.TimedeltaProperties': [
                # Seems like an upstream bug. The property is 'second'
                'seconds_series.dt.seconds'
            ],

            # TODO(BEAM-12530): Test data creation fails for these
            #   s = pd.Series(pd.to_timedelta(np.arange(5), unit="d"))
            # pylint: disable=line-too-long
            'pandas.core.indexes.accessors.DatetimeProperties.to_pydatetime': [
                '*'
            ],
            'pandas.core.indexes.accessors.TimedeltaProperties.components': [
                '*'
            ],
            'pandas.core.indexes.accessors.TimedeltaProperties.to_pytimedelta': [
                '*'
            ],
            # pylint: enable=line-too-long
        })
    datetimelike_result = doctests.testmod(
        pd.core.arrays.datetimelike, use_beam=False)

    datetime_result = doctests.testmod(
        pd.core.arrays.datetimes,
        use_beam=False,
        wont_implement_ok={
            'pandas.core.arrays.datetimes.DatetimeArray.to_period': ['*'],
            # All tz_localize tests use unsupported values for ambiguous=
            # Verified seperately in
            # frames_test.py::DeferredFrameTest::test_dt_tz_localize_*
            'pandas.core.arrays.datetimes.DatetimeArray.tz_localize': ['*'],
        },
        not_implemented_ok={
            # Verifies index version of this method
            'pandas.core.arrays.datetimes.DatetimeArray.to_period': [
                'df.index.to_period("M")'
            ],
        })

    self.assertEqual(indexes_accessors_result.failed, 0)
    self.assertEqual(datetimelike_result.failed, 0)
    self.assertEqual(datetime_result.failed, 0)

  def test_indexing_tests(self):
    result = doctests.testmod(
        pd.core.indexing,
        use_beam=False,
        skip={
            'pandas.core.indexing._IndexSlice': ['*'],
            'pandas.core.indexing.IndexingMixin.at': ['*'],
            'pandas.core.indexing.IndexingMixin.iat': ['*'],
            'pandas.core.indexing.IndexingMixin.iloc': ['*'],
            'pandas.core.indexing.IndexingMixin.loc': ['*'],
            'pandas.core.indexing._AtIndexer': ['*'],
            'pandas.core.indexing._LocIndexer': ['*'],
            'pandas.core.indexing._iAtIndexer': ['*'],
            'pandas.core.indexing._iLocIndexer': ['*'],
        })
    self.assertEqual(result.failed, 0)

  def test_groupby_tests(self):
    result = doctests.testmod(
        pd.core.groupby.groupby,
        use_beam=False,
        wont_implement_ok={
            'pandas.core.groupby.groupby.GroupBy.head': ['*'],
            'pandas.core.groupby.groupby.GroupBy.tail': ['*'],
            'pandas.core.groupby.groupby.GroupBy.nth': ['*'],
            'pandas.core.groupby.groupby.GroupBy.cumcount': ['*'],
            'pandas.core.groupby.groupby.GroupBy.resample': ['*'],
        },
        not_implemented_ok={
            'pandas.core.groupby.groupby.GroupBy.ngroup': ['*'],
            'pandas.core.groupby.groupby.GroupBy.sample': ['*'],
            'pandas.core.groupby.groupby.GroupBy.rank': ['*'],
            'pandas.core.groupby.groupby.GroupBy.nth': [
                "df.groupby('A', as_index=False).nth(1)",
            ],
        },
        skip={
            # Uses iloc to mutate a DataFrame
            'pandas.core.groupby.groupby.GroupBy.resample': [
                'df.iloc[2, 0] = 5',
                'df',
            ],
            # df is reassigned
            'pandas.core.groupby.groupby.GroupBy.rank': ['df'],
            # TODO: Raise wont implement for list passed as a grouping column
            # Currently raises unhashable type: list
            'pandas.core.groupby.groupby.GroupBy.ngroup': [
                'df.groupby(["A", [1,1,2,3,2,1]]).ngroup()'
            ],
        })
    self.assertEqual(result.failed, 0)

    result = doctests.testmod(
        pd.core.groupby.generic,
        use_beam=False,
        wont_implement_ok={
            # Returns an array by default, not a Series. WontImplement
            # (non-deferred)
            'pandas.core.groupby.generic.SeriesGroupBy.unique': ['*'],
            # TODO: Is take actually deprecated?
            'pandas.core.groupby.generic.DataFrameGroupBy.take': ['*'],
            'pandas.core.groupby.generic.SeriesGroupBy.take': ['*'],
            'pandas.core.groupby.generic.SeriesGroupBy.nsmallest': [
                "s.nsmallest(3, keep='last')",
                "s.nsmallest(3)",
                "s.nsmallest()",
            ],
            'pandas.core.groupby.generic.SeriesGroupBy.nlargest': [
                "s.nlargest(3, keep='last')",
                "s.nlargest(3)",
                "s.nlargest()",
            ],
            'pandas.core.groupby.generic.DataFrameGroupBy.diff': ['*'],
            'pandas.core.groupby.generic.SeriesGroupBy.diff': ['*'],
            'pandas.core.groupby.generic.DataFrameGroupBy.hist': ['*'],
            'pandas.core.groupby.generic.DataFrameGroupBy.fillna': [
                'df.fillna(method=\'ffill\')',
                'df.fillna(method="ffill")',
                'df.fillna(value=values, limit=1)',
            ],
            'pandas.core.groupby.generic.SeriesGroupBy.fillna': [
                'df.fillna(method=\'ffill\')',
                'df.fillna(method="ffill")',
                'df.fillna(value=values, limit=1)',
            ],
        },
        not_implemented_ok={
            'pandas.core.groupby.generic.DataFrameGroupBy.idxmax': ['*'],
            'pandas.core.groupby.generic.DataFrameGroupBy.idxmin': ['*'],
            'pandas.core.groupby.generic.SeriesGroupBy.transform': ['*'],
            'pandas.core.groupby.generic.SeriesGroupBy.idxmax': ['*'],
            'pandas.core.groupby.generic.SeriesGroupBy.idxmin': ['*'],
            'pandas.core.groupby.generic.SeriesGroupBy.apply': ['*'],
        },
        skip={
            'pandas.core.groupby.generic.SeriesGroupBy.cov': [
                # Floating point comparison fails
                's1.cov(s2)',
            ],
            'pandas.core.groupby.generic.DataFrameGroupBy.cov': [
                # Mutates input DataFrame with loc
                # TODO: Replicate in frames_test.py
                "df.loc[df.index[:5], 'a'] = np.nan",
                "df.loc[df.index[5:10], 'b'] = np.nan",
                "df.cov(min_periods=12)",
            ],
            # These examples rely on grouping by a list
            'pandas.core.groupby.generic.SeriesGroupBy.aggregate': ['*'],
            'pandas.core.groupby.generic.DataFrameGroupBy.aggregate': ['*'],
            'pandas.core.groupby.generic.SeriesGroupBy.transform': [
                # Dropping invalid columns during a transform is unsupported.
                'grouped.transform(lambda x: (x - x.mean()) / x.std())'
            ],
            'pandas.core.groupby.generic.DataFrameGroupBy.transform': [
                # Dropping invalid columns during a transform is unsupported.
                'grouped.transform(lambda x: (x - x.mean()) / x.std())'
            ],
            # Skipped idxmax/idxmin due an issue with the test framework
            'pandas.core.groupby.generic.SeriesGroupBy.idxmin': ['s.idxmin()'],
            'pandas.core.groupby.generic.SeriesGroupBy.idxmax': ['s.idxmax()'],
            # Uses as_index, which is currently not_implemented
            'pandas.core.groupby.generic.DataFrameGroupBy.value_counts': [
                "df.groupby('gender', as_index=False).value_counts()",
                # pylint: disable=line-too-long
                "df.groupby('gender', as_index=False).value_counts(normalize=True)",
            ],
        })
    self.assertEqual(result.failed, 0)

  def test_top_level(self):
    tests = {
        name: func.__doc__
        for (name, func) in pd.__dict__.items()
        if _is_top_level_function(func) and getattr(func, '__doc__', None)
    }

    # IO methods are tested in io_test.py
    skip_reads = {name: ['*'] for name in dir(pd) if name.startswith('read_')}

    result = doctests.teststrings(
        tests,
        use_beam=False,
        report=True,
        not_implemented_ok={
            'concat': ['pd.concat([s1, s2], ignore_index=True)'],
            'crosstab': ['*'],
            'cut': ['*'],
            'eval': ['*'],
            'get_dummies': ['*'],
            'infer_freq': ['*'],
            'lreshape': ['*'],
            'melt': ['*'],
            'merge': ["df1.merge(df2, how='cross')"],
            'merge_asof': ['*'],
            'pivot': ['*'],
            'pivot_table': ['*'],
            'qcut': ['*'],
            'reset_option': ['*'],
            'set_eng_float_format': ['*'],
            'set_option': ['*'],
            'to_numeric': ['*'],
            'to_timedelta': ['*'],
            'unique': ['*'],
            'wide_to_long': ['*'],
        },
        wont_implement_ok={
            'factorize': ['*'],
            'to_datetime': ['s.head()'],
            'to_pickle': ['*'],
            'melt': [
                "pd.melt(df, id_vars=['A'], value_vars=['B'])",
                "pd.melt(df, id_vars=['A'], value_vars=['B', 'C'])",
                "pd.melt(df, col_level=0, id_vars=['A'], value_vars=['B'])",
                "pd.melt(df, id_vars=[('A', 'D')], value_vars=[('B', 'E')])",
                "pd.melt(df, id_vars=['A'], value_vars=['B'],\n" +
                "        var_name='myVarname', value_name='myValname')"
            ],
        },
        skip={
            # error formatting
            'concat': ['pd.concat([df5, df6], verify_integrity=True)'],
            # doctest DeprecationWarning
            'melt': ['df'],
            # Order-sensitive re-indexing.
            'merge': [
                "df1.merge(df2, left_on='lkey', right_on='rkey')",
                "df1.merge(df2, left_on='lkey', right_on='rkey',\n"
                "          suffixes=('_left', '_right'))",
                "df1.merge(df2, how='left', on='a')",
            ],
            # Not an actual test.
            'option_context': ['*'],
            'factorize': ['codes', 'uniques'],
            # Bad top-level use of un-imported function.
            'merge_ordered': [
                'merge_ordered(df1, df2, fill_method="ffill", left_by="group")'
            ],
            # Expected error.
            'pivot': ["df.pivot(index='foo', columns='bar', values='baz')"],
            # Never written.
            'to_pickle': ['os.remove("./dummy.pkl")'],
            **skip_reads
        })
    self.assertEqual(result.failed, 0)

if __name__ == '__main__':
  unittest.main()


# -*- coding: utf-8 -*-
"""Implements a class to be used for unit testing.
"""
import pathlib
from tlsmate.workers.eval_cipher_suites import ScanCipherSuites
from tlsmate.tlssuite import TlsSuiteTester
from tlsmate.tlssuite import TlsLibrary

ssl2_ck = [
    "SSL_CK_RC4_128_WITH_MD5",
    "SSL_CK_RC2_128_CBC_WITH_MD5",
    "SSL_CK_IDEA_128_CBC_WITH_MD5",
    "SSL_CK_DES_192_EDE3_CBC_WITH_MD5",
]

class TestCase(TlsSuiteTester):
    """Class used for tests with pytest.

    For more information refer to the documentation of the TcRecorder class.
    """

    sp_out_yaml = "profile_basic_ssl2"
    recorder_yaml = "recorder_eval_cipher_suites_ssl2"
    path = pathlib.Path(__file__)
    server_cmd = (
        "utils/start_openssl --version {library} --port {server_port} "
        "--cert1 server-rsa --cert2 server-ecdsa --no-cert-chain "
        "-- -www -cipher ALL -ssl2"
    )
    library = TlsLibrary.openssl1_0_2

    server = "localhost"

    def check_versions(self, versions):
        assert len(versions) == 6

        assert versions[0]["version"]["name"] == "SSL20"
        assert versions[0]["support"] == "TRUE"

        assert versions[1]["version"]["name"] == "SSL30"
        assert versions[1]["support"] == "FALSE"

        assert versions[2]["version"]["name"] == "TLS10"
        assert versions[2]["support"] == "FALSE"

        assert versions[3]["version"]["name"] == "TLS11"
        assert versions[3]["support"] == "FALSE"

        assert versions[4]["version"]["name"] == "TLS12"
        assert versions[4]["support"] == "FALSE"

        assert versions[5]["version"]["name"] == "TLS13"
        assert versions[5]["support"] == "FALSE"

        for a, b in zip(ssl2_ck, versions[0]["cipher_kinds"]):
            assert a == b["name"]

    def check_profile(self, profile):
        self.check_versions(profile["versions"])

    def run(self, tlsmate, is_replaying):
        for vers in ["sslv2", "sslv3", "tls10", "tls11", "tls12", "tls13"]:
            tlsmate.config.set(vers, True)
        server_profile = tlsmate.server_profile
        ScanCipherSuites(tlsmate).run()

        self.check_profile(server_profile.make_serializable())

if __name__ == "__main__":
    TestCase().entry(is_replaying=False)


# -*- coding: utf-8 -*-
#
# Copyright 2017-2021 - Swiss Data Science Center (SDSC)
# A partnership between École Polytechnique Fédérale de Lausanne (EPFL) and
# Eidgenössische Technische Hochschule Zürich (ETHZ).
#
# 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.
"""Renku database dispatcher."""

from renku.core import errors
from renku.core.management.interface.database_dispatcher import IDatabaseDispatcher
from renku.core.metadata.database import Database

class DatabaseDispatcher(IDatabaseDispatcher):
    """Interface for the DatabaseDispatcher.

    Handles getting current database (Database) and entering/exiting the stack for the database.
    """

    def __init__(self):
        self.database_stack = []

    @property
    def current_database(self) -> Database:
        """Get the currently active database."""
        if len(self.database_stack) == 0:
            raise errors.ConfigurationError("No database configured for injection")

        return self.database_stack[-1][0]

    def push_database_to_stack(self, path: str, commit: bool = False) -> None:
        """Create and push a new client to the stack."""
        new_database = Database.from_path(path)
        self.database_stack.append((new_database, commit))

    def pop_database(self) -> None:
        """Remove the current client from the stack."""
        popped_database = self.database_stack.pop()

        if popped_database[1]:
            popped_database[0].commit()

    def finalize_dispatcher(self) -> None:
        """Close all database contexts."""
        while self.database_stack:
            self.pop_database()


import unittest

def suite():
    return unittest.TestLoader().discover("pypobot.tests", pattern="*.py")


# Generated by Django 3.0.6 on 2020-06-12 17:51

from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
import django.utils.timezone

class Migration(migrations.Migration):

    initial = True

    dependencies = [
        migrations.swappable_dependency(settings.AUTH_USER_MODEL),
    ]

    operations = [
        migrations.CreateModel(
            name='Post',
            fields=[
                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                ('title', models.CharField(max_length=256)),
                ('text', models.TextField()),
                ('created_date', models.DateTimeField(default=django.utils.timezone.now)),
                ('published_date', models.DateTimeField(blank=True, null=True)),
                ('author', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
            ],
        ),
        migrations.CreateModel(
            name='Comment',
            fields=[
                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                ('author', models.CharField(max_length=256)),
                ('text', models.TextField()),
                ('created_date', models.DateTimeField(default=django.utils.timezone.now)),
                ('isApproved', models.BooleanField(default=False)),
                ('post', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='comments', to='blog.Post')),
            ],
        ),
    ]


"""Documentation about the dianna module."""

# FIXME: put actual code here
def hello(name):
    """Say hello

    Function docstring using Google docstring style.

    Args:
        name (str): Name to say hello to

    Returns:
        str: Hello message

    Raises:
        ValueError: If `name` is equal to `nobody`

    Example:
        This function can be called with `Jane Smith` as argument using

        >>> from dianna.my_module import hello
        >>> hello('Jane Smith')
        'Hello Jane Smith!'

    """
    if name == 'nobody':
        raise ValueError('Can not say hello to nobody')
    return f'Hello {name}!'


"""
[Python scripts for 3DTracker-FAB (www.3dtracker.org)]
Example 03: Converting 2D position to 3D

This is a script demonstrating how to convert 2D positions in a ROI in a RGB image to 3D.
The type of conversion is useful for using 2D image based object detection/tracking
algorithms to obtain the corresponding 3D object position/trace.

The example plot 3D points in the ROIs surrouding a can in the 2D images

Date last modified: 2018.10.03
"""

import numpy as np
import cv2

import contextlib

import pyqtgraph as pg
import pyqtgraph.opengl as gl

import lib3dtracker as tdt  # 3DTracker-FAB python library

fname_metadata = './example data/dual_d435_01/dual_d435_01.metadata.xml' # metadata file path

with contextlib.closing(tdt.DataReader(fname_metadata)) as d:   # open data using 'with statement'

    i_frame = 10;   # video frame number to process

    # show camera 1 RGB image and ROI
    roi_cam1 = [120, 70, 40, 80] # ROI; left, top, width, height
    [frame_rgb, frame_d] = d.get_rgbd_frame(i_frame, 0)
    cv2.rectangle(frame_rgb, tuple(roi_cam1[0:2]), (roi_cam1[0]+roi_cam1[2], roi_cam1[1]+roi_cam1[3]), (0, 0, 255), 2)
    cv2.imshow('rgb1', frame_rgb)

    # show camera 2 RGB image and ROI
    roi_cam2 = [170, 80, 50, 100] # ROI; left, top, width, height
    [frame_rgb, frame_d] = d.get_rgbd_frame(i_frame, 1)
    cv2.rectangle(frame_rgb, tuple(roi_cam2[0:2]), (roi_cam2[0]+roi_cam2[2], roi_cam2[1]+roi_cam2[3]), (0, 0, 255), 2)
    cv2.imshow('rgb2', frame_rgb)

    # get 3D point cloud in ROI
    pc_roi1 = d.get_pc_from_rgbd(i_frame, 0, roi_cam1)
    pc_roi2 = d.get_pc_from_rgbd(i_frame, 1, roi_cam2)

    # prepare for plotting
    app=pg.QtGui.QApplication([])
    w = gl.GLViewWidget()

    # read and plot merged point cloud
    pc = d.get_mrgpc_frame(i_frame)
    tdt.plot_pc(pc, w, 4)

    # plot point cloud in ROIs
    tdt.plot_pc(pc_roi1, w, 5, (1,0,0,1))
    tdt.plot_pc(pc_roi2, w, 5, (1,0,0,1))

    # plot axis
    g=gl.GLAxisItem()
    w.addItem(g)

    # show the plot
    w.setCameraPosition(distance = 0.5)
    w.show()
    print('Close the window to quit.')
    pg.QtGui.QApplication.exec_()


"""RLBotChoreography

Usage:
    ChoreographyHive [--bot-folder=<folder>]
    ChoreographyHive (-h | --help)

Options:
    -h --help               Shows this help message.
    --bot-folder=<folder>   Searches this folder for bot configs to use for names and appearances [default: .].
"""
import copy
import os
import sys
import inspect
import time

from docopt import docopt
from importlib import reload, import_module
from queue import Queue
from threading import Thread
from os.path import dirname, basename, isfile, join
import glob

from rlbot.matchconfig.conversions import parse_match_config
from rlbot.parsing.agent_config_parser import load_bot_appearance
from rlbot.parsing.directory_scanner import scan_directory_for_bot_configs
from rlbot.parsing.rlbot_config_parser import create_bot_config_layout
from rlbot.setup_manager import SetupManager
from rlbot.utils.structures.start_match_structures import MAX_PLAYERS

import hivemind
from queue_commands import QCommand
from choreography.choreography import Choreography

# TODO:
# - Do bot-folder from inside the GUI
# - Prettify GUI
class RLBotChoreography:

    def __init__(self):
        # Runs GUI and Hivemind on two different threads.
        q = Queue()
        thread1 = Thread(target=self.run_gui, args=(q, ))
        thread1.start()
        thread2 = Thread(target=self.run_RLBotChoreography, args=(q, ))
        thread2.start()
        q.join()

    def setup_match(self):
        # TODO This should be replaced?
        arguments = docopt(__doc__)

        bot_directory = arguments['--bot-folder']
        bundles = scan_directory_for_bot_configs(bot_directory)

        # Set up RLBot.cfg
        framework_config = create_bot_config_layout()
        config_location = os.path.join(os.path.dirname(__file__), 'rlbot.cfg')
        framework_config.parse_file(config_location, max_index=MAX_PLAYERS)
        match_config = parse_match_config(framework_config, config_location, {}, {})

        looks_configs = {idx: bundle.get_looks_config() for idx, bundle in enumerate(bundles)}
        names = [bundle.name for bundle in bundles]

        player_config = match_config.player_configs[0]
        match_config.player_configs.clear()
        for i in range(max(len(bundles), self.min_bots)):
            copied = copy.copy(player_config)
            if i < len(bundles):
                copied.name = names[i]
                # If you want to override bot appearances to get a certain visual effect, e.g. with
                # specific boost colors, this is a good place to do it.
                copied.loadout_config = load_bot_appearance(looks_configs[i], 0)
            match_config.player_configs.append(copied)

        manager = SetupManager()
        manager.load_match_config(match_config, {})
        manager.connect_to_game()
        manager.start_match()

    def run_RLBotChoreography(self, queue):
        """
        If Hivemind breaks out of game_loop it is reloaded and recreated.
        """
        # Waits until a START command is received.
        while queue.get() != QCommand.START:
            continue

        self.setup_match()

        while True:
            my_hivemind = hivemind.Hivemind(queue, self.choreo_obj)
            my_hivemind.start() # Loop only quits on STOP command.

            # Reloads hivemind for new changes to take place.
            # reload(sys.modules[self.choreo_obj.__module__])
            reload(hivemind)

            # Checks what to do after Hivemind died.
            command = queue.get()
            if command == QCommand.ALL:
                self.setup_match()
            elif command == QCommand.EXIT:
                break

        exit() # Clean exit.

    def run_gui(self, queue):
        """
        Runs the simple gui.
        """

        def reload_choreographies():
            """
            Finds and reloads all choreo modules and puts the found choreographies inside a dictionary.
            """
            # Automatically finds all choreo modules.
            modules = glob.glob(join(dirname(__file__), "choreography/choreos/*.py"))
            choreo_modules = [basename(f)[:-3] for f in modules if isfile(f) and not f.endswith('__init__.py')]

            choreographies = {}
            for choreo in choreo_modules:
                module = f'choreography.choreos.{choreo}'

                # Try reloading the module.
                try:
                    reload(sys.modules[module])
                    classes = inspect.getmembers(sys.modules[module], inspect.isclass)

                # If not loaded yet, import it.
                except:
                    print(f'Module not found, importing {module}')
                    import_module(module)
                    classes = inspect.getmembers(sys.modules[module], inspect.isclass)

                # Find all the choreography classes inside.
                finally:
                    for name, obj in classes:
                        # Checks whether the class subclasses Choreography.
                        if issubclass(obj, Choreography) and obj is not Choreography:
                            # FIXME Watch out for name conflicts!
                            choreographies[name] = obj

            return choreographies

        def start():
            num_bots_changed()
            print("[RLBotChoreography]: Starting up!")
            queue.put(QCommand.START)

            # Removes the button so we cannot start again.
            button_start.destroy()

            # Hive reset button.
            button_reload_hive = tk.Button(frame, text="↻ Hivemind", command=reload_hive)
            button_reload_hive.pack()

            # All reset button.
            button_reload_all = tk.Button(frame, text="↻ All", command=reload_all)
            button_reload_all.pack()

        def num_bots_changed():
            """
            Looks at the choreography's requested number of bots and uses that. Otherwise will use the entered number.
            """
            try:
                num_bots = self.choreo_obj.get_num_bots()
            except NotImplementedError:
                num_bots = int(entry_num_bots.get())
            finally:
                self.min_bots = min(int(num_bots), MAX_PLAYERS)
                entry_num_bots.delete(0, last=tk.END)
                entry_num_bots.insert(0, self.min_bots)

        def choreo_selected(var):
            """
            Updates the selected choreography.
            """
            self.choreographies = reload_choreographies()
            self.choreo_obj = self.choreographies[var]
            num_bots_changed()

        def reload_hive():
            num_bots_changed()
            print("[RLBotChoreography]: Stopping Hivemind.")
            queue.put(QCommand.STOP)
            choreo_selected(menuvar.get())
            print("[RLBotChoreography]: Reloading Hivemind.")
            queue.put(QCommand.HIVE)

        def reload_all():
            num_bots_changed()
            print("[RLBotChoreography]: Stopping Hivemind.")
            queue.put(QCommand.STOP)
            choreo_selected(menuvar.get())
            print("[RLBotChoreography]: Reloading all.")
            queue.put(QCommand.ALL)

        # TODO Make GUI look better.
        import tkinter as tk

        root = tk.Tk()
        frame = tk.Frame(root)
        frame.pack()

        # Start button.
        button_start = tk.Button(frame, text="Start", command=start)
        button_start.pack()

        # Dropdown menu.
        self.choreographies = reload_choreographies()
        menuvar = tk.StringVar(root)
        menuvar.set('LightfallChoreography') # Set the default option
        dropMenu = tk.OptionMenu(frame, menuvar, *self.choreographies, command=choreo_selected)
        dropMenu.pack()

        # Label for the entry box.
        label_num_bots = tk.Label(frame, text="Number of bots")
        label_num_bots.pack()

        # Number of bots entry box.
        entry_num_bots = tk.Entry(frame)
        entry_num_bots.insert(0, 10)
        entry_num_bots.pack()

        # This is here just to make sure everything is set up by default.
        choreo_selected(menuvar.get())

        root.mainloop()

        # Clean exit.
        print('[RLBotChoreography]: Shutting down.')
        queue.put(QCommand.STOP)
        queue.put(QCommand.EXIT)
        exit()

if __name__ == '__main__':
    # Starts the show :)
    RLBotChoreography()


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

from __future__ import absolute_import, division, print_function, unicode_literals

import argparse

from web.app import create_app
from dobot.utils import detect_dobot_port, dobot_is_on_port

DEFAULT_BAUDRATE = 115200

parser = argparse.ArgumentParser(description='Run Dobot WebAPI.')
parser.add_argument('--port', type=int, default=18001)
parser.add_argument('--host', type=str, default='0.0.0.0')
parser.add_argument('--dobot-port', type=str, default=None)
parser.add_argument('--tuner-file', type=str, default='/var/tmp/robot_tuner.dat')
parser.add_argument('--instance_path', type=str, default=None)

args = parser.parse_args()

if not args.dobot_port:
    dobot_port = detect_dobot_port(DEFAULT_BAUDRATE)
    if dobot_port is None:
        print('dobot offline')
        exit(1)
else:
    dobot_port = args.dobot_port
    if not dobot_is_on_port(dobot_port, DEFAULT_BAUDRATE):
        print('dobot is not detected on port {}'.format(dobot_port))
        exit(1)

app = create_app(dobot_port, args.tuner_file, args.instance_path)

if __name__ == '__main__':
    app.run(port=args.port, host=args.host)


# coding=utf-8
# Copyright 2018 The Dopamine 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.
"""Library used by example_viz.py to generate visualizations.

This file illustrates the following:
  - How to subclass an existing agent to add visualization functionality.
    - For DQN we visualize the cumulative rewards and the Q-values for each
      action (MyDQNAgent).
    - For Rainbow we visualize the cumulative rewards and the Q-value
      distributions for each action (MyRainbowAgent).
  - How to subclass Runner to run in eval mode, lay out the different subplots,
    generate the visualizations, and compile them into a video (MyRunner).
  - The function `run()` is the main entrypoint for running everything.
"""

from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

import os
import sys

from absl import logging

from dopamine.agents.dqn import dqn_agent
from dopamine.agents.rainbow import rainbow_agent
from dopamine.discrete_domains import atari_lib
from dopamine.discrete_domains import iteration_statistics
from dopamine.discrete_domains import run_experiment
from dopamine.utils import agent_visualizer
from dopamine.utils import atari_plotter
from dopamine.utils import bar_plotter
from dopamine.utils import line_plotter
import gin
import numpy as np
import tensorflow as tf
import tf_slim
import pdb
import matplotlib.pyplot as plt

class MyDQNAgent(dqn_agent.DQNAgent):
    """Sample DQN agent to visualize Q-values and rewards."""

    def __init__(self, sess, num_actions, summary_writer=None):
        super(MyDQNAgent, self).__init__(sess, num_actions,
                                         summary_writer=summary_writer)
        self.q_values = [[] for _ in range(num_actions)]
        self.rewards = []

    def step(self, reward, observation, step_number):
        self.rewards.append(reward)
        return super(MyDQNAgent, self).step(reward, observation, step_number)

    def _select_action(self, step_number):
        action = super(MyDQNAgent, self)._select_action(step_number)
        # print("on selectionne ici")
        q_vals = self._sess.run(self._net_outputs.q_values,
                                {self.state_ph: self.state})[0]
        for i in range(len(q_vals)):
            self.q_values[i].append(q_vals[i])
        return action

    def reload_checkpoint(self, checkpoint_path, use_legacy_checkpoint=False):
        if use_legacy_checkpoint:
            variables_to_restore = atari_lib.maybe_transform_variable_names(
                tf.compat.v1.global_variables(), legacy_checkpoint_load=True)
        else:
            global_vars = set([x.name for x in tf.compat.v1.global_variables()])
            ckpt_vars = [
                '{}:0'.format(name)
                for name, _ in tf.train.list_variables(checkpoint_path)
            ]
            include_vars = list(global_vars.intersection(set(ckpt_vars)))
            variables_to_restore = tf_slim.get_variables_to_restore(
                include=include_vars)
        if variables_to_restore:
            reloader = tf.compat.v1.train.Saver(var_list=variables_to_restore)
            reloader.restore(self._sess, checkpoint_path)
            logging.info('Done restoring from %s', checkpoint_path)
        else:
            logging.info('Nothing to restore!')

    def get_q_values(self):
        return self.q_values

    def get_rewards(self):
        return [np.cumsum(self.rewards)]

class MyRainbowAgent(rainbow_agent.RainbowAgent):
    """Sample Rainbow agent to visualize Q-values and rewards."""

    def __init__(self, sess, num_actions, summary_writer=None):
        super(MyRainbowAgent, self).__init__(sess, num_actions,
                                             summary_writer=summary_writer)
        self.rewards = []

    def step(self, reward, observation, step_number):
        self.rewards.append(reward)
        return super(MyRainbowAgent, self).step(reward, observation, step_number)

    def reload_checkpoint(self, checkpoint_path, use_legacy_checkpoint=False):
        if use_legacy_checkpoint:
            variables_to_restore = atari_lib.maybe_transform_variable_names(
                tf.compat.v1.global_variables(), legacy_checkpoint_load=True)
        else:
            global_vars = set([x.name for x in tf.compat.v1.global_variables()])
            ckpt_vars = [
                '{}:0'.format(name)
                for name, _ in tf.train.list_variables(checkpoint_path)
            ]
            include_vars = list(global_vars.intersection(set(ckpt_vars)))
            variables_to_restore = tf_slim.get_variables_to_restore(
                include=include_vars)
        if variables_to_restore:
            reloader = tf.compat.v1.train.Saver(var_list=variables_to_restore)
            reloader.restore(self._sess, checkpoint_path)
            logging.info('Done restoring from %s', checkpoint_path)
        else:
            logging.info('Nothing to restore!')

    def get_probabilities(self):
        return self._sess.run(tf.squeeze(self._net_outputs.probabilities),
                              {self.state_ph: self.state})

    def get_rewards(self):
        return [np.cumsum(self.rewards)]

class MyRunner(run_experiment.Runner):
    """Sample Runner class to generate visualizations."""

    def __init__(self, base_dir, trained_agent_ckpt_path, create_agent_fn,
                 use_legacy_checkpoint=False):
        self._trained_agent_ckpt_path = trained_agent_ckpt_path
        self._use_legacy_checkpoint = use_legacy_checkpoint
        super(MyRunner, self).__init__(base_dir, create_agent_fn)

    def _initialize_checkpointer_and_maybe_resume(self, checkpoint_file_prefix):
        self._agent.reload_checkpoint(self._trained_agent_ckpt_path,
                                      self._use_legacy_checkpoint)
        self._start_iteration = 0

    def _run_one_iteration(self, iteration):
        statistics = iteration_statistics.IterationStatistics()
        logging.info('Starting iteration %d', iteration)
        _, _ = self._run_eval_phase(statistics)
        return statistics.data_lists

    def _run_one_iteration(self, iteration):
        statistics = iteration_statistics.IterationStatistics()
        logging.info('Starting iteration %d', iteration)

        num_episodes_eval, average_reward_eval = self._run_eval_phase(
            statistics)
        return statistics.data_lists

    def _run_eval_phase(self, statistics):
        # Perform the evaluation phase -- no learning.
        self._agent.eval_mode = True

        _, sum_returns, num_episodes = self._run_one_phase(
            self._evaluation_steps, statistics, 'eval')
        average_return = sum_returns / num_episodes if num_episodes > 0 else 0.0
        logging.info('Average undiscounted return per evaluation episode: %.2f',
                     average_return)
        statistics.append({'eval_average_return': average_return})
        return num_episodes, average_return

    def _run_one_phase(self, min_steps, statistics, run_mode_str):
        step_count = 0
        num_episodes = 0
        sum_returns = 0.
        print("min_steps", min_steps)
        while step_count < min_steps:
          print(">>>>> step_count", step_count)
          episode_length, episode_return = self._run_one_episode()
          statistics.append({
              '{}_episode_lengths'.format(run_mode_str): episode_length,
              '{}_episode_returns'.format(run_mode_str): episode_return
          })
          step_count += episode_length
          sum_returns += episode_return
          num_episodes += 1
          # We use sys.stdout.write instead of logging so as to flush frequently
          # without generating a line break.
          sys.stdout.write('Steps executed: {} '.format(step_count) +
                           'Episode length: {} '.format(episode_length) +
                           'Return: {}\r'.format(episode_return))
          sys.stdout.flush()
        return step_count, sum_returns, num_episodes

    def _run_one_episode(self):
        step_number = 0
        total_reward = 0.

        action = self._initialize_episode()
        is_terminal = False

        # Keep interacting until we reach a terminal state.
        while True:
          observation, reward, is_terminal = self._run_one_step(action, step_number)

          total_reward += reward
          step_number += 1
          print("step_number", step_number)

          if self._clip_rewards:
            # Perform reward clipping.
            reward = np.clip(reward, -1, 1)

          if (self._environment.game_over or
              step_number == self._max_steps_per_episode):
            # Stop the run loop once we reach the true end of episode.
            break
          elif is_terminal:
            # If we lose a life but the episode is not over, signal an artificial
            # end of episode to the agent.
            self._end_episode(reward, is_terminal)
            action = self._agent.begin_episode(observation)
          else:
            action = self._agent.step(reward, observation, step_number)

        self._end_episode(reward, is_terminal)

        return step_number, total_reward

    def _run_one_step(self, action, step_number):
        observation, reward, is_terminal, _ = self._environment.step(action)
        # Saving the render
        if True:
            if step_number > 900 and step_number < 1000:
                image = self._environment.render('rgb_array')
                plt.imshow(image)
                plt.savefig("/home/hugo/saliency_maps/Rainbow-Tennis/render/render"+str(step_number)+".png")
        return observation, reward, is_terminal

def create_dqn_agent(sess, environment, summary_writer=None):
    return MyDQNAgent(sess, num_actions=environment.action_space.n,
                      summary_writer=summary_writer)

def create_rainbow_agent(sess, environment, summary_writer=None):
    return MyRainbowAgent(sess, num_actions=environment.action_space.n,
                          summary_writer=summary_writer)

def create_runner(base_dir, trained_agent_ckpt_path, agent='dqn',
                  use_legacy_checkpoint=False):
    create_agent = create_dqn_agent if agent == 'dqn' else create_rainbow_agent
    return MyRunner(base_dir, trained_agent_ckpt_path, create_agent,
                    use_legacy_checkpoint)

def run(agent, game, num_steps, root_dir, restore_ckpt,
        use_legacy_checkpoint=False):
    """Main entrypoint for running and generating visualizations.

  Args:
    agent: str, agent type to use.
    game: str, Atari 2600 game to run.
    num_steps: int, number of steps to play game.
    root_dir: str, root directory where files will be stored.
    restore_ckpt: str, path to the checkpoint to reload.
    use_legacy_checkpoint: bool, whether to restore from a legacy (pre-Keras)
      checkpoint.
  """
    tf.compat.v1.reset_default_graph()
    config = """
  atari_lib.create_atari_environment.game_name = '{}'
  WrappedReplayBuffer.replay_capacity = 300
  """.format(game)
    base_dir = os.path.join(root_dir, 'agent_viz', game, agent)
    gin.parse_config(config)
    runner = create_runner(base_dir, restore_ckpt, agent, use_legacy_checkpoint)
    iteration = 0
    runner._run_one_iteration(iteration)


# See also: 📖 [Channels - Consumers](https://channels.readthedocs.io/en/latest/topics/consumers.html)
from django.conf.urls import url

# Websock練習１
from webapp1.websocks.websock_practice1.v1.consumer import WebsockPractice1V1Consumer
#    ------- ----------------------------- --------        --------------------------
#    1       2                             3               4
# 1. アプリケーション フォルダー名
# 2. ディレクトリー名
# 3. Python ファイル名。拡張子抜き
# 4. クラス名

# Websock練習２
from webapp1.websocks.websock_practice2.v1.consumer import WebsockPractice2V1Consumer
#                                     ^                                   ^
#    ------- ----------------------------- --------        --------------------------
#    1       2                             3               4
# 1. アプリケーション フォルダー名
# 2. ディレクトリー名
# 3. Python ファイル名。拡張子抜き
# 4. クラス名

# 〇×ゲームの練習１
from webapp1.websocks.tic_tac_toe.v1.consumer import TicTacToeV1Consumer
#    ------- ----------------------- --------        -------------------
#    1       2                       3                4
# 1. アプリケーション フォルダー名
# 2. ディレクトリー名
# 3. Python ファイル名。拡張子抜き
# 4. クラス名

# 〇×ゲームの練習２
from webapp1.websocks.tic_tac_toe.v2.consumer_custom import TicTacToeV2ConsumerCustom
#                                  ^ two                              ^ two
#    ------- ----------------------- ---------------        -------------------------
#    1       2                       3                      4
# 1. アプリケーション フォルダー名
# 2. ディレクトリー名
# 3. Python ファイル名。拡張子抜き
# 4. クラス名

# 〇×ゲームの練習３．１
from webapp1.websocks.tic_tac_toe.v3o1.consumer_custom import TicTacToeV3o1ConsumerCustom
#                                  ^^^ three o one                      ^^^ three o one
#    ------- ------------------------- ---------------        ---------------------------
#    1       2                         3                      4
# 1. アプリケーション フォルダー名
# 2. ディレクトリー名
# 3. Python ファイル名。拡張子抜き
# 4. クラス名

websocket_urlpatterns = [

    # +----
    # | Websock練習１

    # Websock練習１
    url(r'^websock-practice1/v1/$', WebsockPractice1V1Consumer.as_asgi()),
    #     -----------------------   ------------------------------------
    #     1                                      2
    # 1. URLのパスの部分の、Django での正規表現の書き方
    # 2. クラス名とメソッド。 URL を ASGI形式にする

    # | Websock練習１
    # +----

    # +----
    # | Websock練習２

    # Websock練習２
    url(r'^websock-practice2/v1/$', WebsockPractice2V1Consumer.as_asgi()),
    #                      ^                       ^
    #     -----------------------   ------------------------------------
    #     1                                      2
    # 1. URLのパスの部分の、Django での正規表現の書き方
    # 2. クラス名とメソッド。 URL を ASGI形式にする

    # | Websock練習２
    # +----

    # 〇×ゲームの練習１
    url(r'^tic-tac-toe/v1/playing/(?P<room_name>\w+)/$',
        # --------------------------------------------
        # 1
        TicTacToeV1Consumer.as_asgi()),
    #   -----------------------------
    #   2
    # 1. 例えば `http://example.com/tic-tac-toe/v1/playing/Elephant/` のようなURLのパスの部分の、Django での正規表現の書き方。
    #    room_name は変数として渡される
    # 2. クラス名とメソッド。 URL を ASGI形式にする

    # 〇×ゲームの練習２
    url(r'^tic-tac-toe/v2/playing/(?P<kw_room_name>\w+)/$',
        #               ^
        # -----------------------------------------------
        # 1
        TicTacToeV2ConsumerCustom.as_asgi()),
    #             ^
    #   -----------------------------------
    #   2
    # 1. 例えば `http://example.com/tic-tac-toe/v2/playing/Elephant/` のようなURLのパスの部分の、Django での正規表現の書き方。
    #    kw_room_name は変数として渡される
    # 2. クラス名とメソッド。 URL を ASGI形式にする

    # 〇×ゲームの練習３．１
    url(r'^tic-tac-toe/v3o1/playing/(?P<kw_room_name>\w+)/$',
        #               ^^^ three o one
        # -------------------------------------------------
        # 1
        TicTacToeV3o1ConsumerCustom.as_asgi()),
    #             ^^^ three o one
    #   -------------------------------------
    #   2
    # 1. 例えば `http://example.com/tic-tac-toe/v3o1/playing/Elephant/` のようなURLのパスの部分の、Django での正規表現の書き方。
    #                              -----------------------------------
    #    kw_room_name は変数として渡される
    # 2. クラス名とメソッド。 URL を ASGI形式にする
]


from base64 import b64encode
import datetime
from enum import Enum
from typing import Any, Union
import json

class _JsonEncoder(json.JSONEncoder):
    def default(self, o: Any) -> Union[str, float]:
        if isinstance(o, datetime.datetime):
            return o.astimezone(tz=datetime.timezone.utc).isoformat()
        if isinstance(o, datetime.timedelta):
            return o.total_seconds()
        if isinstance(o, bytes):
            return b64encode(o).decode('ascii')
        if isinstance(o, Enum):
            return o.name
        return super().default(o)

def json_dumps(o: Union[dict, list]) -> str:
    if isinstance(o, dict):
        o = {k: v for k, v in o.items() if not k.startswith('_')}
    return json.dumps(o, cls=_JsonEncoder, separators=(',', ':'))

def pagination_header(count: int, page: int, per_page: int) -> dict:
    return {
        'X-Page': page,
        'X-Per-Page': per_page,
        'X-Total': count,
        'X-Total-Pages': (count + (per_page - 1)) // per_page,
    }


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

import maya.cmds

import IECore
import IECoreMaya

__dagMenuCallbacks = []
## Registers a callback to be used when creating the right click dag
# menu for scene shapes. Callbacks should have the following signature :
#
# callback( menu, sceneShape ).
def addDagMenuCallback( callback ) :

	if not callback in __dagMenuCallbacks :
		__dagMenuCallbacks.append( callback )

## Removes a callback previously added with addDagMenuCallback.
def removeDagMenuCallback( callback ) :

	__dagMenuCallbacks.remove( callback )

## This is forwarded to by the ieSceneShapeDagMenuProc function in
# ieSceneShape.mel
def _dagMenu( menu, sceneShape ) :

	sceneShapes = __selectedSceneShapes()
	if not sceneShapes:
		return

	fnScS = []
	for target in sceneShapes:
		fnScS.append( IECoreMaya.FnSceneShape( target ) )

	maya.cmds.setParent( menu, menu=True )

	invalidSceneShapes = __invalidSceneShapes( sceneShapes )

	if invalidSceneShapes:
		maya.cmds.menuItem(
		label = "Invalid Inputs for selected SceneShapes!",
		radialPosition = "N",
		)

	# Component mode
	elif fnScS[0].selectedComponentNames():

			maya.cmds.menuItem(
			label = "Object",
			radialPosition = "N",
			command = IECore.curry( __objectCallback, sceneShapes[0] ),
			)

			maya.cmds.menuItem(
				label = "Print Component Names",
				radialPosition = "NW",
				command = IECore.curry( __printComponents, sceneShapes[0] )
			)

			maya.cmds.menuItem(
				label = "Print Selected Component Names",
				radialPosition = "NE",
				command = IECore.curry( __printSelectedComponents, sceneShapes[0] )
			)

			maya.cmds.menuItem(
				label = "Expand...",
				radialPosition = "SE",
				subMenu = True
			)

			maya.cmds.menuItem(
				label = "Expand to Selected Components",
				radialPosition = "S",
				command = IECore.curry( __expandToSelected, sceneShapes[0] )
			)
			maya.cmds.setParent( "..", menu=True )

			maya.cmds.menuItem(
				label = "Create Locator",
				radialPosition = "SW",
				subMenu = True,
			)

			maya.cmds.menuItem(
				label = "At Bound Min",
				radialPosition = "N",
				command = IECore.curry( __createLocatorAtPoints, sceneShapes[0], [ "Min" ] ),
			)

			maya.cmds.menuItem(
				label = "At Bound Max",
				radialPosition = "NE",
				command = IECore.curry( __createLocatorAtPoints, sceneShapes[0], [ "Max" ] ),
			)

			maya.cmds.menuItem(
				label = "At Bound Min And Max",
				radialPosition = "E",
				command = IECore.curry( __createLocatorAtPoints, sceneShapes[0], [ "Min", "Max" ] ),
			)

			maya.cmds.menuItem(
				label = "At Bound Centre",
				radialPosition = "SE",
				command = IECore.curry( __createLocatorAtPoints, sceneShapes[0], [ "Center" ] ),
			)

			maya.cmds.menuItem(
				label = "At Transform Origin",
				radialPosition = "S",
				command = IECore.curry( __createLocatorWithTransform, sceneShapes[0] ),
			)
			maya.cmds.setParent( "..", menu=True )

	# Object mode
	else:

		if len( sceneShapes ) == 1:
			if maya.cmds.getAttr( sceneShapes[0]+".drawGeometry" ) or maya.cmds.getAttr( sceneShapes[0]+".drawChildBounds" ):
				maya.cmds.menuItem(
					label = "Component",
					radialPosition = "N",
					command = IECore.curry( __componentCallback, sceneShapes[0] )
					)

		maya.cmds.menuItem(
			label = "Preview...",
			radialPosition = "NW",
			subMenu = True
		)

		maya.cmds.menuItem(
				label = "All Geometry On",
				radialPosition = "E",
				command = IECore.curry( __setChildrenPreviewAttributes, sceneShapes, "drawGeometry", True )
			)

		maya.cmds.menuItem(
				label = "All Child Bounds On",
				radialPosition = "SE",
				command = IECore.curry( __setChildrenPreviewAttributes, sceneShapes, "drawChildBounds", True )
			)

		maya.cmds.menuItem(
				label = "All Root Bound On",
				radialPosition = "NE",
				command = IECore.curry( __setChildrenPreviewAttributes, sceneShapes, "drawRootBound", True )
			)

		maya.cmds.menuItem(
				label = "All Geometry Off",
				radialPosition = "W",
				command = IECore.curry( __setChildrenPreviewAttributes, sceneShapes, "drawGeometry", False )
			)

		maya.cmds.menuItem(
				label = "All Child Bounds Off",
				radialPosition = "SW",
				command = IECore.curry( __setChildrenPreviewAttributes, sceneShapes, "drawChildBounds", False )
			)

		maya.cmds.menuItem(
				label = "All Root Bound Off",
				radialPosition = "NW",
				command = IECore.curry( __setChildrenPreviewAttributes, sceneShapes, "drawRootBound", False )
			)

		maya.cmds.setParent( "..", menu=True )

		commonTags = None
		for fn in fnScS:
			scene = fn.sceneInterface()
			tmpTags = scene.readTags(IECore.SceneInterface.EveryTag)
			if commonTags is None:
				commonTags = set( tmpTags )
			else:
				commonTags.intersection_update( set(tmpTags) )

		tagTree = dict()
		if not commonTags is None:
			tags = list(commonTags)
			for tag in tags :
				tag = str(tag)
				parts = tag.split(":")
				leftOverTag = tag[len(parts[0])+1:]
				if not parts[0] in tagTree :
					tagTree[parts[0]] = [ leftOverTag ]
				else :
					tagTree[parts[0]].append( leftOverTag )
		if tagTree :

			tags = tagTree.keys()
			tags.sort()

			def addTagSubMenuItems( command ):

				import copy
				copiedTagTree = copy.deepcopy( tagTree )

				for tag in tags :

					subtags = copiedTagTree[tag]
					subtags.sort()

					if "" in subtags:
						maya.cmds.menuItem(
							label = tag,
							command = IECore.curry( command, sceneShapes, tag )
						)
						subtags.remove("")

					if subtags:
						maya.cmds.menuItem(
							label = tag,
							subMenu = True
						)

						for tagSuffix in subtags :
							maya.cmds.menuItem(
								label = tagSuffix,
								command = IECore.curry( command, sceneShapes, tag + ":" + tagSuffix )
							)
						maya.cmds.setParent( "..", menu=True )

			maya.cmds.menuItem(
				label = "Tags filter...",
				radialPosition = "S",
				subMenu = True
			)

			maya.cmds.menuItem(
				label = "Display All",
				command = IECore.curry( __setTagsFilterPreviewAttributes, sceneShapes, "" )
			)

			addTagSubMenuItems( __setTagsFilterPreviewAttributes )

			maya.cmds.setParent( "..", menu=True )

		maya.cmds.menuItem(
			label = "Expand...",
			radialPosition = "SE",
			subMenu = True
		)

		maya.cmds.menuItem(
				label = "Recursive Expand As Geometry",
				radialPosition = "W",
				command = IECore.curry( __expandAsGeometry, sceneShapes )
			)

		if any( map(lambda x: x.canBeExpanded(), fnScS) ):

			maya.cmds.menuItem(
				label = "Expand One Level",
				radialPosition = "E",
				command = IECore.curry( __expandOnce, sceneShapes )
			)

			maya.cmds.menuItem(
				label = "Recursive Expand",
				radialPosition = "N",
				command = IECore.curry( __expandAll, sceneShapes )
			)

			if len( sceneShapes ) == 1:
				if fnScS[0].selectedComponentNames() :
					maya.cmds.menuItem(
						label = "Expand to Selected Components",
						radialPosition = "S",
						command = IECore.curry( __expandToSelected, sceneShapes[0] )
					)

		if tagTree :
			maya.cmds.menuItem(
				label = "Expand by Tag...",
				radialPosition = "S",
				subMenu = True
			)

			addTagSubMenuItems( __expandAll )

			maya.cmds.setParent( "..", menu=True )

		maya.cmds.setParent( "..", menu=True )

		parentSceneShape = __parentSceneShape( sceneShapes )

		if any( map(lambda x: x.canBeCollapsed(), fnScS) ) or ( parentSceneShape and IECoreMaya.FnSceneShape( parentSceneShape ).canBeCollapsed() ):

			maya.cmds.menuItem(
					label = "Collapse...",
					radialPosition = "SW",
					subMenu = True
				)

			if parentSceneShape and IECoreMaya.FnSceneShape( parentSceneShape ).canBeCollapsed():

				parentName = maya.cmds.listRelatives( parentSceneShape, p=True )[0]
				maya.cmds.menuItem(
						label = "Collapse to Parent: "+parentName,
						radialPosition = "N",
						command = IECore.curry( __collapseChildren, [parentSceneShape] )
					)

			if any( map(lambda x: x.canBeCollapsed(), fnScS) ):
				maya.cmds.menuItem(
						label = "Collapse Children",
						radialPosition = "W",
						command = IECore.curry( __collapseChildren, sceneShapes )
					)

			maya.cmds.setParent( "..", menu=True )

	for c in __dagMenuCallbacks :

		c( menu, sceneShape )

## Returns all the sceneShapes that do not have a valid scene interface
def __invalidSceneShapes( sceneShapes ):

	invalid = []
	for sceneShape in sceneShapes:
		fn = IECoreMaya.FnSceneShape( sceneShape )
		if fn.sceneInterface() is None:
			invalid.append( sceneShape )
	return invalid

## Returns all the selected scene shapes
def __selectedSceneShapes() :

	allSceneShapes = []

	selectedSceneShapes = maya.cmds.ls( sl=True, l=True )
	for shape in selectedSceneShapes:
		# Make sure we have the shape name, it could be a component
		shapeName = shape.split(".f[")[0]
		if maya.cmds.nodeType( shapeName ) == "ieSceneShape" and not shapeName in allSceneShapes:
			allSceneShapes.append( shapeName )
		else:
			children = maya.cmds.listRelatives( shapeName, children=True, type="ieSceneShape", fullPath=True ) or []
			for child in children:
				if not child in allSceneShapes:
					allSceneShapes.append( child )
	return allSceneShapes

## Turns on child bounds and switches to component mode
def __componentCallback( sceneShape, *unused ) :

	parent = maya.cmds.listRelatives( sceneShape, parent=True, fullPath=True )[0]
	maya.cmds.selectType( ocm=True, alc=False, facet=True )
	maya.cmds.hilite( parent )

## Switches to object mode
def __objectCallback( sceneShape, *unused ) :

	parent = maya.cmds.listRelatives( sceneShape, parent=True, fullPath=True )[0]
	maya.cmds.hilite( parent, unHilite=True )
	selection = maya.cmds.ls( selection=True )
	maya.cmds.selectMode( object=True )
	if selection :
		maya.cmds.select( selection, replace=True )
	else :
		maya.cmds.select( clear=True )

## Print the existing component names for the scene shape
def __printComponents( sceneShape, *unused ) :

	fnS = IECoreMaya.FnSceneShape( sceneShape )
	names = fnS.componentNames()
	names.sort()
	print "\n"
	print " ".join( names ) ,
	print "\n"

## Print the selected component names for the scene shape
def __printSelectedComponents( sceneShape, *unused ) :

	fnS = IECoreMaya.FnSceneShape( sceneShape )
	selectedNames = fnS.selectedComponentNames()
	if selectedNames:
		selectedNames = list( selectedNames )
		selectedNames.sort()
		print "\n"
		print " ".join( selectedNames ) ,
		print "\n"

## Expand each scene shape one level down
def __expandOnce( sceneShapes, *unused ) :

	toSelect = []
	for sceneShape in sceneShapes:
		fnS = IECoreMaya.FnSceneShape( sceneShape )
		new = fnS.expandOnce( preserveNamespace=True )
		toSelect.extend( map( lambda x: x.fullPathName(), new ) )
	if toSelect:
		maya.cmds.select( toSelect, replace=True )

## Recursively expand the scene shapes
def __expandAll( sceneShapes, tagName=None, *unused ) :

	toSelect = []
	for sceneShape in sceneShapes:
		fnS = IECoreMaya.FnSceneShape( sceneShape )
		newFn = fnS.expandAll( preserveNamespace=True, tagName=tagName )

		toSelect.extend( map( lambda x: x.fullPathName(), newFn ) )
	if toSelect:
		maya.cmds.select( toSelect, replace=True )

## Recursively expand the scene shapes and converts objects to geometry
def __expandAsGeometry( sceneShapes, *unused ) :

	for sceneShape in sceneShapes:
		fnS = IECoreMaya.FnSceneShape( sceneShape )
		fnS.convertAllToGeometry( True )

## Expand the scene shape the minimal amount to reach the selected components
def __expandToSelected( sceneShape, *unused ) :

	fnScS = IECoreMaya.FnSceneShape( sceneShape )
	sceneShape = fnScS.fullPathName()
	selectedNames = fnScS.selectedComponentNames()
	if not selectedNames:
		return

	if "/" in selectedNames:
		selectedNames.remove("/")

	# Go back to object mode
	parent =  maya.cmds.listRelatives( sceneShape, parent=True, fullPath=True )[0]
	maya.cmds.hilite( parent, unHilite=True )
	maya.cmds.selectMode( object=True )

	if selectedNames == []:
		return

	toSelect = []

	for selected in selectedNames:
		transformName = parent
		transformNames = [ transformName ]
		for item in selected.split("/")[1:-1]:
			transformName = transformName + "|" + item
			if not transformName in transformNames:
				transformNames.append( transformName )

		for transform in transformNames:
			shape = maya.cmds.listRelatives( transform, fullPath=True, type = "ieSceneShape" )[0]
			fnS = IECoreMaya.FnSceneShape( shape )
			fnS.expandOnce()

		toSelect.append( transformNames[-1] )
	if toSelect:
		maya.cmds.select( toSelect, replace=True )

## Collapse all the children of the scene shapes
def __collapseChildren( sceneShapes, *unused ) :

	for sceneShape in sceneShapes:
		fnS = IECoreMaya.FnSceneShape( sceneShape )
		fnS.collapse()

## Returns the first common parent scene shape for the given scene shapes
# Returns None if no parent found.
def __parentSceneShape( sceneShapes ):

	def getParentShapes( transform, allParentShapes ):
		parent = maya.cmds.listRelatives( transform, p=True, fullPath=True )
		if parent:
			parentShape = maya.cmds.listRelatives( parent[0], fullPath=True, type = "ieSceneShape" )
			if parentShape:
			    allParentShapes.append( parentShape[0] )
			    getParentShapes( parent[0], allParentShapes )

	parents = None
	for sceneShape in sceneShapes:
		transform = maya.cmds.listRelatives( sceneShape, parent=True, fullPath=True )
		if transform:
			allParentShapes = []
			getParentShapes( transform[0], allParentShapes )
			if parents is None:
				parents = set( allParentShapes )
			else:
				parents.intersection_update( set(allParentShapes) )
	if parents:
		parent = ""
		for p in parents:
			if p.count("|") > parent.count("|"):
				parent = p
		return parent

	return None

## Sets the given preview attribute on the scene shapes with the given boolean value
# Preview attributes can be drawGeometry, drawLocators, drawRootBound and drawChildBounds
def __setChildrenPreviewAttributes( sceneShapes, attributeName, value, *unused ) :

	for sceneShape in sceneShapes:
		transform = maya.cmds.listRelatives( sceneShape, parent=True, fullPath=True )
		if transform:
			allChildren = maya.cmds.listRelatives( transform[0], ad=True, fullPath=True, type = "ieSceneShape" ) or []
			for node in allChildren:
				maya.cmds.setAttr( node+"."+attributeName, value )

## Sets the given tags filter attribute on the scene shapes with the given string value
def __setTagsFilterPreviewAttributes( sceneShapes, tagName, *unused ) :

	for sceneShape in sceneShapes:
		transform = maya.cmds.listRelatives( sceneShape, parent=True, fullPath=True )
		if transform:
			allChildren = maya.cmds.listRelatives( transform[0], ad=False, fullPath=True, type = "ieSceneShape" ) or []
			for node in allChildren:
				maya.cmds.setAttr( node+".drawTagsFilter", tagName, type = "string" )

def __createLocatorAtPoints( sceneShape, childPlugSuffixes, *unused ) :

	fnSc = IECoreMaya.FnSceneShape( sceneShape )
	selectedNames = fnSc.selectedComponentNames()

	locators = []
	for name in selectedNames :
		locators.extend( fnSc.createLocatorAtPoints( name, childPlugSuffixes ) )

	maya.cmds.select( locators, replace=True )

def __createLocatorWithTransform( sceneShape, *unused ) :

	fnSc = IECoreMaya.FnSceneShape( sceneShape )
	selectedNames = fnSc.selectedComponentNames()

	locators = []
	for name in selectedNames :
		locators.append( fnSc.createLocatorAtTransform( name ) )

	maya.cmds.select( locators, replace=True )


# coding: utf-8

"""
    Deep Lynx

    The construction of megaprojects has consistently demonstrated challenges for project managers in regard to meeting cost, schedule, and performance requirements. Megaproject construction challenges are common place within megaprojects with many active projects in the United States failing to meet cost and schedule efforts by significant margins. Currently, engineering teams operate in siloed tools and disparate teams where connections across design, procurement, and construction systems are translated manually or over brittle point-to-point integrations. The manual nature of data exchange increases the risk of silent errors in the reactor design, with each silent error cascading across the design. These cascading errors lead to uncontrollable risk during construction, resulting in significant delays and cost overruns. Deep Lynx allows for an integrated platform during design and operations of mega projects.  The Deep Lynx Core API delivers a few main features.  1. Provides a set of methods and endpoints for manipulating data in an object oriented database. This allows us to store complex datatypes as records and then to compile them into actual, modifiable objects at run-time. Users can store taxonomies or ontologies in a readable format.  2. Provides methods for storing and retrieving data in a graph database. This data is structured and validated against the aformentioned object oriented database before storage.  # noqa: E501

    OpenAPI spec version: 1.0

    Generated by: https://github.com/swagger-api/swagger-codegen.git
"""

from __future__ import absolute_import

import unittest

import swagger_client
from swagger_client.models.credential_validation_result import CredentialValidationResult  # noqa: E501
from swagger_client.rest import ApiException

class TestCredentialValidationResult(unittest.TestCase):
    """CredentialValidationResult unit test stubs"""

    def setUp(self):
        pass

    def tearDown(self):
        pass

    def testCredentialValidationResult(self):
        """Test CredentialValidationResult"""
        # FIXME: construct object with mandatory attributes with example values
        # model = swagger_client.models.credential_validation_result.CredentialValidationResult()  # noqa: E501
        pass

if __name__ == '__main__':
    unittest.main()