text:
"""This module defines classes that handle mesh and mesh operations.

This module defines a factory class for mesh, similar to geometry and
size function factory class. It also defines concrete mesh types.
Currently two concrete mesh types are defined for generic Eucledian
mesh and specific 2D Eucledian mesh.
"""
from functools import lru_cache
import logging
from multiprocessing import Pool, cpu_count
import os
import pathlib
from collections import defaultdict
import warnings
from typing import Union, List, Tuple, Dict, Any, Optional
try:
    from typing import Literal
except ImportError:
    from typing_extensions import Literal

import pandas as pd
import geopandas as gpd
from jigsawpy import jigsaw_msh_t, savemsh, loadmsh, savevtk
from matplotlib.path import Path
from matplotlib.transforms import Bbox
from matplotlib.tri import Triangulation
from matplotlib.axes import Axes
import matplotlib.pyplot as plt
import numpy as np
import numpy.typing as npt
from pyproj import CRS, Transformer
from scipy.interpolate import (
        RectBivariateSpline, RegularGridInterpolator)
from shapely.geometry import (
        LineString, box, Polygon, MultiPolygon)
from shapely.ops import polygonize, linemerge

from ocsmesh import utils
from ocsmesh.raster import Raster
from ocsmesh.mesh.base import BaseMesh
from ocsmesh.mesh.parsers import grd, sms2dm

_logger = logging.getLogger(__name__)

class EuclideanMesh(BaseMesh):
    """Generic Euclidean mesh class

    This is the base class for 2D or 3D Euclidean mesh.

    Attributes
    ----------
    tria3 : npt.NDArray[jigsaw_msh_t.TRIA3_t]
        Reference to underlying jigsaw mesh's triangle element
        structure.
    triangles : npt.NDArray[np.float32]
        Array of node index for triangular elements.
    quad4 : npt.NDArray[jigsaw_msh_t.QUAD4_t]
        Reference to underlying jigsaw mesh's quadrangle element
        structure.
    quads : npt.NDArray[np.float32]
        Array of node index for quadrangular elements.
    crs : CRS
        Coodrinate reference system of the mesh object
    hull : Hull
        Handle to hull calculation helper object
    nodes : Nodes
        Handle to node handler helper object
    elements : Elements
        Handle to element handler helper object

    Methods
    -------
    write(path, overwrite=False, format='grd')
        Export mesh object to the disk in the specified format.
    """

    def __init__(self, mesh: jigsaw_msh_t) -> None:
        """Initialize Euclidean mesh object.

        Parameters
        ----------
        mesh : jigsaw_msh_t
            The underlying jigsaw_msh_t object to hold onto mesh data.

        Raises
        ------
        TypeError
            If input mesh is not of `jigsaw_msh_t` type.
        ValueError
            If input mesh's `mshID` is not equal to ``euclidean-mesh``.
            If input mesh has `crs` property which is not of `CRS` type.
        """

        if not isinstance(mesh, jigsaw_msh_t):
            raise TypeError(f'Argument mesh must be of type {jigsaw_msh_t}, '
                            f'not type {type(mesh)}.')
        if mesh.mshID != 'euclidean-mesh':
            raise ValueError(f'Argument mesh has property mshID={mesh.mshID}, '
                             "but expected 'euclidean-mesh'.")
        if not hasattr(mesh, 'crs'):
            warnings.warn('Input mesh has no CRS information.')
            mesh.crs = None
        else:
            if not isinstance(mesh.crs, CRS):
                raise ValueError(f'crs property must be of type {CRS}, not '
                                 f'type {type(mesh.crs)}.')

        self._hull = None
        self._nodes = None
        self._elements = None
        self._msh_t = mesh

    def write(
            self,
            path: Union[str, os.PathLike],
            overwrite: bool = False,
            format : Literal['grd', '2dm', 'msh', 'vtk'] = 'grd', # pylint: disable=W0622
            ) -> None:
        """Export the mesh object to the disk

        Parameters
        ----------
        path : path-like
            Path to which the mesh should be exported.
        overwrite : bool, default=False
            Whether to overwrite, if a file already exists in `path`
        format : { 'grd', '2dm', 'msh', 'vtk' }
            Format of the export, SMS-2DM or GRD.

        Returns
        -------
        None

        Raises
        ------
        ValueError
            If specified export format is **not** supported.
        """

        path = pathlib.Path(path)
        if path.exists() and overwrite is not True:
            raise IOError(
                f'File {str(path)} exists and overwrite is not True.')
        if format == 'grd':
            grd_dict = utils.msh_t_to_grd(self.msh_t)
            if self._boundaries and self._boundaries.data:
                grd_dict.update(boundaries=self._boundaries.data)
            grd.write(grd_dict, path, overwrite)

        elif format == '2dm':
            sms2dm.writer(utils.msh_t_to_2dm(self.msh_t), path, overwrite)

        elif format == 'msh':
            savemsh(str(path), self.msh_t)

        elif format == 'vtk':
            savevtk(str(path), self.msh_t)

        else:
            raise ValueError(f'Unhandled format {format}.')

    @property
    def tria3(self):
        """Reference to underlying mesh tirangle element structure"""

        return self.msh_t.tria3

    @property
    def triangles(self):
        """Reference to underlying mesh triangle element index array"""

        return self.msh_t.tria3['index']

    @property
    def quad4(self):
        """Reference to underlying mesh quadrangle element structure"""

        return self.msh_t.quad4

    @property
    def quads(self):
        """Reference to underlying mesh quadrangle element index array"""

        return self.msh_t.quad4['index']

    @property
    def crs(self):
        """Reference to underlying mesh crs"""

        return self.msh_t.crs

    @property
    def hull(self):
        """Reference to hull calculator helper object"""

        if self._hull is None:
            self._hull = Hull(self)
        return self._hull

    @property
    def nodes(self):
        """Reference to node handler helper object"""

        if self._nodes is None:
            self._nodes = Nodes(self)
        return self._nodes

    @property
    def elements(self):
        """Reference to element handler helper object"""

        if self._elements is None:
            self._elements = Elements(self)
        return self._elements

class EuclideanMesh2D(EuclideanMesh):
    """2D Euclidean mesh definition

    Attributes
    ----------
    boundaries
    vert2
    value
    bbox

    Methods
    -------
    get_bbox(crs=None, output_type=None)
        Gets the bounding box of the mesh elements.
    tricontourf(**kwargs)
        Create a contour plot from the value data on the nodes of
        the mesh
    interpolate(raster, method='spline', nprocs=None)
        Interpolate raster date on the nodes.
    get_contour(level)
        Get contour lines from node value data at specified levels.
    get_multipolygon(zmin=None, zmax=None)
        Get multipolygon of the mesh hull.
    """

    def __init__(self, mesh: jigsaw_msh_t) -> None:
        """Initialize Euclidean 2D mesh object.

        Parameters
        ----------
        mesh : jigsaw_msh_t
            The underlying jigsaw_msh_t object to hold onto mesh data.

        Raises
        ------
        ValueError
            If number of mesh dimensions is not equal to ``2``.
        """

        super().__init__(mesh)
        self._boundaries = None

        if mesh.ndims != +2:
            raise ValueError(f'Argument mesh has property ndims={mesh.ndims}, '
                             "but expected ndims=2.")

        if len(self.msh_t.value) == 0:
            self.msh_t.value = np.array(
                np.full((self.vert2['coord'].shape[0], 1), np.nan))

    def get_bbox(
            self,
            crs: Union[str, CRS, None] = None,
            output_type: Literal[None, 'polygon', 'bbox'] = None
            ) -> Union[Polygon, Bbox]:
        """Get the bounding box of mesh elements.

        Parameters
        ----------
        crs : str or CRS or None, default=None
            CRS to transform the calculated bounding box into before
            returning
        output_type : { None, 'polygon', 'bbox'}, default=None
            Output type

        Returns
        -------
        Polygon or Bbox
            Bounding box of the mesh elements.
        """

        output_type = 'polygon' if output_type is None else output_type
        xmin, xmax = np.min(self.coord[:, 0]), np.max(self.coord[:, 0])
        ymin, ymax = np.min(self.coord[:, 1]), np.max(self.coord[:, 1])
        crs = self.crs if crs is None else crs
        if crs is not None:
            if not self.crs.equals(crs):
                transformer = Transformer.from_crs(
                    self.crs, crs, always_xy=True)
                # pylint: disable=E0633
                (xmin, xmax), (ymin, ymax) = transformer.transform(
                    (xmin, xmax), (ymin, ymax))
        if output_type == 'polygon': # pylint: disable=R1705
            return box(xmin, ymin, xmax, ymax)
        elif output_type == 'bbox':
            return Bbox([[xmin, ymin], [xmax, ymax]])

        raise TypeError(
            'Argument output_type must a string literal \'polygon\' or '
            '\'bbox\'')

    @property
    def boundaries(self):
        """Handle to boundaries calculator helper object"""

        if self._boundaries is None:
            self._boundaries = Boundaries(self)
        return self._boundaries

    def tricontourf(self, **kwargs) -> Axes:
        """Generate contour for the data of triangular elements of the mesh

        Parameters
        ----------
        **kwargs : dict, optional
           Passed to underlying `matplotlib` API.

        Returns
        -------
        Axes
            Axes on which the filled contour is drawn.
        """

        return utils.tricontourf(self.msh_t, **kwargs)

    def interpolate(
            self,
            raster: Union[Raster, List[Raster]],
            method: Literal['spline', 'linear', 'nearest'] = 'spline',
            nprocs: Optional[int] = None,
            info_out_path: Union[pathlib.Path, str, None] = None,
            filter_by_shape: bool = False
            ) -> None:
        """Interplate values from raster inputs to the mesh nodes.

        Parameters
        ----------
        raster : Raster or list of Raster
            A single or a list of rasters from which values are
            interpolated onto the mesh
        method : {'spline', 'linear', 'nearest'}, default='spline'
            Method of interpolation.
        nprocs : int or None, default=None
            Number of workers to use when interpolating data.
        info_out_path : pathlike or str or None
            Path for the output node interpolation information file
        filter_by_shape : bool
            Flag for node filtering based on raster bbox or shape

        Returns
        -------
        None
        """

        if isinstance(raster, Raster):
            raster = [raster]

        nprocs = -1 if nprocs is None else nprocs
        nprocs = cpu_count() if nprocs == -1 else nprocs

        # Fix an issue on Jupyter notebook where having pool execute
        # interpolation even in case of nprocs == 1 would results in
        # application getting stuck
        if nprocs > 1:
            with Pool(processes=nprocs) as pool:
                res = pool.starmap(
                    _mesh_interpolate_worker,
                    [(self.vert2['coord'], self.crs,
                        _raster.tmpfile, _raster.chunk_size,
                        method, filter_by_shape)
                     for _raster in raster]
                    )
            pool.join()
        else:
            res = [_mesh_interpolate_worker(
                        self.vert2['coord'], self.crs,
                        _raster.tmpfile, _raster.chunk_size,
                        method, filter_by_shape)
                   for _raster in raster]

        values = self.msh_t.value.flatten()

        interp_info_map = {}
        for (mask, _values), rast in zip(res, raster):
            values[mask] = _values

            if info_out_path is not None:
                vert_cs = None
                rast_crs = rast.crs
                if rast_crs.is_vertical:
                    if rast_crs.sub_crs_list is not None:
                        for sub_crs in rast_crs.sub_crs_list:
                            if sub_crs.is_vertical:
                                # TODO: What if sub CRS is compound, etc.?
                                vert_cs = sub_crs
                    elif rast_crs.source_crs is not None:
                        if rast_crs.source_crs.is_vertical:
                            # TODO: What if source CRS is compound, etc.?
                            vert_cs = rast_crs.source_crs

                vert_cs_name = vert_cs.name
                idxs = np.argwhere(mask).ravel()
                interp_info_map.update({
                    idx: (rast.path, vert_cs_name)
                    for idx in idxs})

        if info_out_path is not None:
            coords = self.msh_t.vert2['coord'].copy()
            geo_coords = coords.copy()
            if not self.crs.is_geographic:
                transformer = Transformer.from_crs(
                    self.crs, CRS.from_epsg(4326), always_xy=True)
                # pylint: disable=E0633
                geo_coords[:, 0], geo_coords[:, 1] = transformer.transform(
                    coords[:, 0], coords[:, 1])
            vd_idxs=np.array(list(interp_info_map.keys()))
            df_interp_info = pd.DataFrame(
                index=vd_idxs,
                data={
                    'x': coords[vd_idxs, 0],
                    'y': coords[vd_idxs, 1],
                    'lat': geo_coords[vd_idxs, 0],
                    'lon': geo_coords[vd_idxs, 1],
                    'elev': values[vd_idxs],
                    'crs': [i[1] for i in interp_info_map.values()],
                    'source': [i[0] for i in interp_info_map.values()]
                }
            )
            df_interp_info.sort_index().to_csv(
                info_out_path, header=False, index=True)

        self.msh_t.value = np.array(values.reshape((values.shape[0], 1)),
                                    dtype=jigsaw_msh_t.REALS_t)

    def get_contour(self, level: float) -> LineString:
        """Extract contour lines at the specified `level` from mesh values

        Parameters
        ----------
        level : float
            The level at which contour lines must be extracted.

        Returns
        -------
        LineString
            Extracted and merged contour lines.

        Raises
        ------
        ValueError
            If mesh has nodes that have null value `np.nan`.
        """

        # ONLY SUPPORTS TRIANGLES
        for attr in ['quad4', 'hexa8']:
            if len(getattr(self.msh_t, attr)) > 0:
                warnings.warn(
                    'Mesh contour extraction only supports triangles')

        coords = self.msh_t.vert2['coord']
        values = self.msh_t.value
        trias = self.msh_t.tria3['index']
        if np.any(np.isnan(values)):
            raise ValueError(
                "Mesh contains invalid values. Raster values must"
                "be interpolated to the mesh before generating "
                "boundaries.")

        x, y = coords[:, 0], coords[:, 1]
        features = []
        with warnings.catch_warnings():
            warnings.simplefilter('ignore', UserWarning)
            _logger.debug('Computing contours...')
            fig, ax = plt.subplots()
            ax.tricontour(
                x, y, trias, values.ravel(), levels=[level])
            plt.close(fig)
        for path_collection in ax.collections:
            for path in path_collection.get_paths():
                try:
                    features.append(LineString(path.vertices))
                except ValueError:
                    # LineStrings must have at least 2 coordinate tuples
                    pass
        return linemerge(features)

    def get_multipolygon(
            self,
            zmin: Optional[float] = None,
            zmax: Optional[float] = None
            ) -> MultiPolygon:
        """Calculate multipolygon covering mesh elements (hull)

        Parameters
        ----------
        zmin : float or None
            Minimum elevation to consider for multipolygon extraction
        zmax : float or None
            Maximum elevation to consider for multipolygon extraction

        Returns
        -------
        MultiPolygon
            Calculated multipolygon shape
        """

        values = self.msh_t.value
        mask = np.ones(values.shape)
        if zmin is not None:
            mask = np.logical_and(mask, values > zmin)
        if zmax is not None:
            mask = np.logical_and(mask, values < zmax)

        # Assuming value is of shape (N, 1)
        # ravel to make sure it's 1D
        verts_in = np.argwhere(mask).ravel()

        clipped_mesh = utils.clip_mesh_by_vertex(
            self.msh_t, verts_in,
            can_use_other_verts=True)

        boundary_edges = utils.get_boundary_edges(clipped_mesh)
        coords = clipped_mesh.vert2['coord']
        coo_to_idx = {
            tuple(coo): idx
            for idx, coo in enumerate(coords)}
        poly_gen = polygonize(coords[boundary_edges])
        polys = list(poly_gen)
        polys = sorted(polys, key=lambda p: p.area, reverse=True)

        rings = [p.exterior for p in polys]
        n_parents = np.zeros((len(rings),))
        represent = np.array([r.coords[0] for r in rings])
        for e, ring in enumerate(rings[:-1]):
            path = Path(ring.coords, closed=True)
            n_parents = n_parents + np.pad(
                np.array([
                    path.contains_point(pt) for pt in represent[e+1:]]),
                (e+1, 0), 'constant', constant_values=0)

        # Get actual polygons based on logic described above
        polys = [p for e, p in enumerate(polys) if not n_parents[e] % 2]

        return MultiPolygon(polys)

    @property
    def vert2(self):
        """Reference to underlying mesh 2D vertices structure"""
        return self.msh_t.vert2

    @property
    def value(self):
        """Reference to underlying mesh values"""
        return self.msh_t.value

    @property
    def bbox(self):
        """Calculates and returns bounding box of the mesh hull.

        See Also
        --------
        get_bbox
        """
        return self.get_bbox()

MeshType = Union[EuclideanMesh2D]

class Mesh(BaseMesh):
    """Mesh object factory

    Factory class that creates and returns concrete mesh object
    based on the input types.

    Methods
    -------
    open(path, crs=None)
        Read mesh data from a file on disk.
    """

    def __new__(cls, mesh: jigsaw_msh_t) -> MeshType:
        """Construct a concrete mesh object.

        Parameters
        ----------
        mesh : jigsaw_msh_t
            Input jigsaw mesh object

        Returns
        -------
        MeshType
            Mesh object created from the input

        Raises
        ------
        TypeError
            Input `mesh` is not a `jigsaw_msh_t` object.
        NotImplementedError
            Input `mesh` object cannot be used to create a EuclideanMesh2D
        """

        if not isinstance(mesh, jigsaw_msh_t):
            raise TypeError(f'Argument mesh must be of type {jigsaw_msh_t}, '
                            f'not type {type(mesh)}.')

        if mesh.mshID == 'euclidean-mesh':
            if mesh.ndims == 2:
                return EuclideanMesh2D(mesh)

            raise NotImplementedError(
                f'mshID={mesh.mshID} + mesh.ndims={mesh.ndims} not '


text:
"""
A module that contains utility functions to load the 'classical' workspace configuration.
This configuration may have three meaningful files:
.remote (required) - information about the connection options
.remoteindex (optional) - information about which connection from options above to use
.remoteignore (optional) - information about files that should be ignore when syncing files
"""
import os
import re

from collections import defaultdict
from dataclasses import asdict
from pathlib import Path
from typing import Dict, List, Tuple

from remote.exceptions import ConfigurationError

from . import ConfigurationMedium, RemoteConfig, SyncRules, WorkspaceConfig
from .shared import DEFAULT_REMOTE_ROOT, hash_path

CONFIG_FILE_NAME = ".remote"
INDEX_FILE_NAME = ".remoteindex"
IGNORE_FILE_NAME = ".remoteignore"
IGNORE_SECTION_REGEX = re.compile(r"^(push|pull|both)\s*:$")
BASE_IGNORES = (CONFIG_FILE_NAME, INDEX_FILE_NAME, IGNORE_FILE_NAME)
DEFAULT_SHELL = "sh"
DEFAULT_SHELL_OPTIONS = ""

def _extract_shell_info(line: str, env_vars: List[str]) -> Tuple[str, str]:
    if not env_vars:
        return DEFAULT_SHELL, DEFAULT_SHELL_OPTIONS

    vars_string = env_vars[0]

    env = {}
    items = vars_string.split()
    index = 0
    while index < len(items):
        key, value = items[index].split("=")
        if value.startswith("'") or value.startswith('"'):
            control_character = value[0]
            while index < len(items) - 1:
                if value[-1] == control_character:
                    break
                index += 1
                value += " " + items[index]
            if not value[-1] == control_character:
                raise ConfigurationError(f"Config line {line} is corrupted. Cannot parse end {key}={value}")

        env[key] = value.strip("\"'")

        index += 1
    print(env)
    # TODO: these shell types are not used in new implementation, need to remove them
    shell = env.pop("RSHELL", DEFAULT_SHELL)
    shell_options = env.pop("RSHELL_OPTS", DEFAULT_SHELL_OPTIONS)
    if env:
        raise ConfigurationError(
            f"Config line {line} contains unexpected env variables: {env}. Only RSHELL and RSHELL_OPTS can be used"
        )
    return shell, shell_options

def parse_config_line(line: str) -> RemoteConfig:
    # The line should look like this:
    # sdas-ld2:.remotes/814f27f15f4e7a0842cada353dfc765a RSHELL=zsh
    entry, *env_items = line.split(maxsplit=1)
    shell, shell_options = _extract_shell_info(line, env_items)

    parts = entry.split(":")
    if len(parts) != 2:
        raise ConfigurationError(
            f"The configuration string is malformed: {parts}. Please use host-name:remote_dir format"
        )
    host, directory = parts
    return RemoteConfig(host=host, directory=Path(directory), shell=shell, shell_options=shell_options)

def load_configurations(workspace_root: Path) -> List[RemoteConfig]:
    config_file = workspace_root / CONFIG_FILE_NAME

    configurations = []
    for line in config_file.read_text().splitlines():
        line = line.strip()
        if not line or line.startswith("#"):
            continue

        configurations.append(parse_config_line(line))

    return configurations

def load_default_configuration_num(workspace_root: Path) -> int:
    # If REMOTE_HOST_INDEX is set, that overrides settings in .remoteindex
    env_index = os.environ.get("REMOTE_HOST_INDEX")
    if env_index:
        try:
            return int(env_index)
        except ValueError:
            raise ConfigurationError(
                f"REMOTE_HOST_INDEX env variable contains symbols other than numbers: '{env_index}'. "
                "Please set the coorect index value to continue"
            )

    index_file = workspace_root / INDEX_FILE_NAME
    if not index_file.exists():
        return 0

    # Configuration uses 1-base index and we need to have 0-based
    text = index_file.read_text().strip()
    try:
        return int(text) - 1
    except ValueError:
        raise ConfigurationError(
            f"File {index_file} contains symbols other than numbers: '{text}'. "
            "Please remove it or replace the value to continue"
        )

def _postprocess(ignores):
    pull = ignores.pop("pull", [])
    push = ignores.pop("push", [])
    both = ignores.pop("both", [])
    if ignores:
        raise ConfigurationError(
            f"{IGNORE_FILE_NAME} file has unexpected sections: {', '.join(ignores.keys())}. Please remove them"
        )
    return SyncRules(pull=pull, push=push, both=both)

def load_ignores(workspace_root: Path) -> SyncRules:
    ignores: Dict[str, List[str]] = defaultdict(list)
    ignores["both"].extend(BASE_IGNORES)

    ignore_file = workspace_root / IGNORE_FILE_NAME
    if not ignore_file.exists():
        return _postprocess(ignores)

    active_section = "both"
    is_new_format = None
    for line in ignore_file.read_text().splitlines():
        line = line.strip()
        if not line or line.startswith("#"):
            continue

        matcher = IGNORE_SECTION_REGEX.match(line)
        if matcher is None:
            if is_new_format is None:
                is_new_format = False
            ignores[active_section].append(line)
        else:
            if is_new_format is None:
                is_new_format = True
            elif not is_new_format:
                raise ConfigurationError(
                    f"Few ignore patters were listed in {IGNORE_FILE_NAME} before the first section {matcher.group(1)} appeared. "
                    "Please list all ignored files after a section declaration if you use new ignore format"
                )
            active_section = matcher.group(1)

    return _postprocess(ignores)

def save_general_config(config_file: Path, configurations: List[RemoteConfig]):
    with config_file.open("w") as f:
        for item in configurations:
            f.write(f"{item.host}:{item.directory}")
            if item.shell != "sh":
                f.write(f" RSHELL={item.shell}")
            if item.shell_options:
                f.write(f" RSHELL_OPTS='{item.shell_options}'")
            f.write("\n")

def save_ignores(config_file: Path, ignores: SyncRules):
    ignores.both.extend(BASE_IGNORES)
    ignores.trim()

    if ignores.is_empty():
        if config_file.exists():
            config_file.unlink()
        return

    with config_file.open("w") as f:
        for key, value in asdict(ignores).items():
            f.write(f"{key}:\n")
            for item in value:
                f.write(f"{item}\n")

def save_index(config_file: Path, index: int):
    if index == 0:
        # We delete file when index is default
        if config_file.exists():
            config_file.unlink()
    else:
        config_file.write_text(f"{index + 1}\n")

class ClassicConfigurationMedium(ConfigurationMedium):
    """A medium class that knows how to load and save the 'classical' workspace configuration.

    This configuration may have three meaningful files:
    .remote (required) - information about the connection options
    .remoteindex (optional) - information about which connection from options above to use
    .remoteignore (optional) - information about files that should be ignore when syncing files
    """

    def load_config(self, workspace_root: Path) -> WorkspaceConfig:
        configurations = load_configurations(workspace_root)
        configuration_index = load_default_configuration_num(workspace_root)
        if configuration_index > len(configurations) - 1:
            raise ConfigurationError(
                f"Configuration #{configuration_index + 1} requested but there are only {len(configurations)} declared"
            )
        ignores = load_ignores(workspace_root)

        return WorkspaceConfig(
            root=workspace_root,
            configurations=configurations,
            default_configuration=configuration_index,
            ignores=ignores,
            includes=SyncRules.new(),
        )

    def save_config(self, config: WorkspaceConfig) -> None:
        save_general_config(config.root / CONFIG_FILE_NAME, config.configurations)
        save_ignores(config.root / IGNORE_FILE_NAME, config.ignores)
        save_index(config.root / INDEX_FILE_NAME, config.default_configuration)

    def is_workspace_root(self, path: Path) -> bool:
        return (path / CONFIG_FILE_NAME).exists()

    def generate_remote_directory(self, config: WorkspaceConfig) -> Path:
        md5 = hash_path(config.root)
        return Path(f"{DEFAULT_REMOTE_ROOT}/{config.root.name}_{md5}")

domain: python


text:
import pandas as pd

from nibabel.tmpdirs import InTemporaryDirectory
from nose.tools import (assert_raises,
                        assert_true,
                        )

from nistats.utils import _check_events_file_uses_tab_separators

def make_data_for_test_runs():
    data_for_temp_datafile = [
        ['csf', 'constant', 'linearTrend', 'wm'],
        [13343.032102491035, 1.0, 0.0, 9486.199545677482],
        [13329.224068063204, 1.0, 1.0, 9497.003324892803],
        [13291.755627241291, 1.0, 2.0, 9484.012965365506],
        ]

    delimiters = {
        'tab': '\t',
        'comma': ',',
        'space': ' ',
        'semicolon': ';',
        'hyphen': '-',
        }

    return data_for_temp_datafile, delimiters

def _create_test_file(temp_csv, test_data, delimiter):
    test_data = pd.DataFrame(test_data)
    test_data.to_csv(temp_csv, sep=delimiter)

def _run_test_for_invalid_separator(filepath, delimiter_name):
    if delimiter_name not in ('tab', 'comma'):
        with assert_raises(ValueError):
            _check_events_file_uses_tab_separators(events_files=filepath)
    else:
        result = _check_events_file_uses_tab_separators(events_files=filepath)
        assert_true(result is None)

def test_for_invalid_separator():
    data_for_temp_datafile, delimiters = make_data_for_test_runs()
    for delimiter_name, delimiter_char in delimiters.items():
        with InTemporaryDirectory():
            temp_tsv_file = 'tempfile.{} separated values'.format(
                    delimiter_name)
            _create_test_file(temp_csv=temp_tsv_file ,
                              test_data=data_for_temp_datafile,
                              delimiter=delimiter_char)
            _run_test_for_invalid_separator(filepath=temp_tsv_file ,
                                            delimiter_name=delimiter_name)

def test_with_2D_dataframe():
    data_for_pandas_dataframe, _ = make_data_for_test_runs()
    events_pandas_dataframe = pd.DataFrame(data_for_pandas_dataframe)
    result = _check_events_file_uses_tab_separators(
            events_files=events_pandas_dataframe)
    assert_true(result is None)

def test_with_1D_dataframe():
    data_for_pandas_dataframe, _ = make_data_for_test_runs()
    for dataframe_ in data_for_pandas_dataframe:
        events_pandas_dataframe = pd.DataFrame(dataframe_)
        result = _check_events_file_uses_tab_separators(
                events_files=events_pandas_dataframe)
        assert_true(result is None)

def test_for_invalid_filepath():
    filepath = 'junk_file_path.csv'
    result = _check_events_file_uses_tab_separators(events_files=filepath)
    assert_true(result is None)

def test_for_pandas_dataframe():
    events_pandas_dataframe = pd.DataFrame([['a', 'b', 'c'], [0, 1, 2]])
    result = _check_events_file_uses_tab_separators(
            events_files=events_pandas_dataframe)
    assert_true(result is None)

def test_binary_opening_an_image():
    img_data = bytearray(
            b'GIF87a\x01\x00\x01\x00\xe7*\x00\x00\x00\x00\x01\x01\x01\x02\x02'
            b'\x07\x08\x08\x08\x0b\x0b\x0b\x0c\x0c\x0c\r;')
    with InTemporaryDirectory():
        temp_img_file = 'temp_img.gif'
        with open(temp_img_file, 'wb') as temp_img_obj:
            temp_img_obj.write(img_data)
        with assert_raises(ValueError):
            _check_events_file_uses_tab_separators(
                    events_files=temp_img_file)

def test_binary_bytearray_of_ints_data():
    temp_data_bytearray_from_ints = bytearray([0, 1, 0, 11, 10])
    with InTemporaryDirectory():
        temp_bin_file = 'temp_bin.bin'
        with open(temp_bin_file, 'wb') as temp_bin_obj:
            temp_bin_obj.write(temp_data_bytearray_from_ints)
        with assert_raises(ValueError):
            _check_events_file_uses_tab_separators(
                    events_files=temp_bin_file)

if __name__ == '__main__':

    def _run_tests_print_test_messages(test_func):
        from pprint import pprint
        pprint(['Running', test_func.__name__])
        test_func()
        pprint('... complete')

    def run_test_suite():
        tests = [
            test_for_invalid_filepath,
            test_with_2D_dataframe,
            test_with_1D_dataframe,
            test_for_invalid_filepath,
            test_for_pandas_dataframe,
            test_binary_opening_an_image,
            test_binary_bytearray_of_ints_data,
            ]
        for test_ in tests:
            _run_tests_print_test_messages(test_func=test_)

    run_test_suite()


text:
import discord
import json
from discord.ext import commands
from cogs.ObjectCache import config
from cogs.ObjectCache import server_config
from cogs.ObjectCache import get_lang
from collections import OrderedDict

with open('commands.json') as json_data:
	commands_json = json.load(json_data, object_pairs_hook = OrderedDict)

class Help(commands.Cog):
	def __init__(self, bot):
		self.bot = bot

	@commands.command(aliases = ['h'])
	async def help(self, ctx, command_name = None):
		try:
			guild_prefix = server_config[ctx.guild.id]['prefix']
		except:
			guild_prefix = config['default_prefix']

		if not command_name:

			embed = discord.Embed(color = 0x00FF00)
			embed.set_author(name = self.bot.user.name, icon_url = self.bot.user.avatar_url)
			embed.add_field(name = 'Help', value = ', '.join(['`' + guild_prefix + i + '`' for i in commands_json.keys() if commands_json[i]['module'] == 'Help']), inline = False)
			embed.add_field(name = 'Administration', value = ', '.join(['`' + guild_prefix + i + '`' for i in commands_json.keys() if commands_json[i]['module'] == 'Administration']), inline = False)
			embed.add_field(name = 'MemberPresence', value = ', '.join(['`' + guild_prefix + i + '`' for i in commands_json.keys() if commands_json[i]['module'] == 'MemberPresence']), inline = False)
			embed.add_field(name = 'Economy', value = ', '.join(['`' + guild_prefix + i + '`' for i in commands_json.keys() if commands_json[i]['module'] == 'Economy']), inline = False)
			embed.add_field(name = 'Utility', value = ', '.join(['`' + guild_prefix + i + '`' for i in commands_json.keys() if commands_json[i]['module'] == 'Utility']), inline = False)
			embed.set_footer(text = get_lang(ctx.guild, 'HELP_response_footer').format(guild_prefix))

		else:

			try:
				cmd_data = commands_json[command_name.lower()]
			except:
				return await ctx.send(embed = discord.Embed(description = get_lang(ctx, 'HELP_command_notfound'), color = 0xFF0000))

			embed = discord.Embed(title = ' / '.join(['`' + guild_prefix + i + '`' for i in cmd_data['title']]), description = get_lang(ctx.guild, cmd_data['description']), color = 0x00FF00)
			embed.add_field(name = get_lang(ctx.guild, 'HELP_permission_string_user'), value = '\n'.join(['`' + get_lang(ctx.guild, i) + '`' for i in cmd_data['user_permissions']]), inline = True)
			embed.add_field(name = get_lang(ctx.guild, 'HELP_permission_string_bot'), value = '\n'.join(['`' + get_lang(ctx.guild, i) + '`' for i in cmd_data['bot_permissions']]), inline = True)
			embed.add_field(name = get_lang(ctx.guild, 'HELP_example_string'), value = ' or '.join(['`' + guild_prefix + i + '`' for i in cmd_data['examples']]), inline = False)
			embed.set_footer(text = 'Module: ' + cmd_data['module'])

		await ctx.send(embed = embed)

	@commands.command()
	async def invite(self, ctx):
		await ctx.send(embed = discord.Embed(description = '[Support Server](https://discord.gg/sbySHxA)\n[Add Me](https://discordapp.com/oauth2/authorize?client_id=' + str(self.bot.user.id) + '&scope=bot&permissions=0)\n[GitHub](https://github.com/Deivedux/Shiramine)\n[Patreon](https://www.patreon.com/QuoteBot)', color = 0x00FF00))

def setup(bot):
	bot.add_cog(Help(bot))


text:
''' Taking characters from terminal without pressing enter for movements '''
from __future__ import print_function

class AlarmException(Exception):
    pass


text:
#! /usr/bin/env python
# -*- coding: utf-8 -*-
# vim:fenc=utf-8
#
# Copyright © 2018 damian <damian@C-DZ-E5500>
#
# Distributed under terms of the MIT license.

"""

"""

import subprocess
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
import yaml

def read_file(filename):
    with open(filename) as f:
        data = yaml.load(f.read())

def run_command(cmd):
    return subprocess.check_call(cmd, shell=True)

db = create_engine('sqlite:///somedatabase')
Session = sessionmaker(bind=db)

def get_user(uid):
    session = Session()
    query = "select * from user where id='%s'" % uid
    return session.execute(query)


text:
from __future__ import print_function, division, absolute_import
from fontTools.misc.py23 import *
from fontTools.misc.textTools import safeEval, readHex
from fontTools.misc.encodingTools import getEncoding
from fontTools.ttLib import getSearchRange
from fontTools.unicode import Unicode
from . import DefaultTable
import sys
import struct
import array
import operator

class table__c_m_a_p(DefaultTable.DefaultTable):

	def getcmap(self, platformID, platEncID):
		for subtable in self.tables:
			if (subtable.platformID == platformID and
					subtable.platEncID == platEncID):
				return subtable
		return None # not found

	def decompile(self, data, ttFont):
		tableVersion, numSubTables = struct.unpack(">HH", data[:4])
		self.tableVersion = int(tableVersion)
		self.tables = tables = []
		seenOffsets = {}
		for i in range(numSubTables):
			platformID, platEncID, offset = struct.unpack(
					">HHl", data[4+i*8:4+(i+1)*8])
			platformID, platEncID = int(platformID), int(platEncID)
			format, length = struct.unpack(">HH", data[offset:offset+4])
			if format in [8,10,12,13]:
				format, reserved, length = struct.unpack(">HHL", data[offset:offset+8])
			elif format in [14]:
				format, length = struct.unpack(">HL", data[offset:offset+6])

			if not length:
				print("Error: cmap subtable is reported as having zero length: platformID %s, platEncID %s,  format %s offset %s. Skipping table." % (platformID, platEncID,format, offset))
				continue
			table = CmapSubtable.newSubtable(format)
			table.platformID = platformID
			table.platEncID = platEncID
			# Note that by default we decompile only the subtable header info;
			# any other data gets decompiled only when an attribute of the
			# subtable is referenced.
			table.decompileHeader(data[offset:offset+int(length)], ttFont)
			if offset in seenOffsets:
				table.cmap = tables[seenOffsets[offset]].cmap
			else:
				seenOffsets[offset] = i
			tables.append(table)

	def compile(self, ttFont):
		self.tables.sort()    # sort according to the spec; see CmapSubtable.__lt__()
		numSubTables = len(self.tables)
		totalOffset = 4 + 8 * numSubTables
		data = struct.pack(">HH", self.tableVersion, numSubTables)
		tableData = b""
		seen = {}  # Some tables are the same object reference. Don't compile them twice.
		done = {}  # Some tables are different objects, but compile to the same data chunk
		for table in self.tables:
			try:
				offset = seen[id(table.cmap)]
			except KeyError:
				chunk = table.compile(ttFont)
				if chunk in done:
					offset = done[chunk]
				else:
					offset = seen[id(table.cmap)] = done[chunk] = totalOffset + len(tableData)
					tableData = tableData + chunk
			data = data + struct.pack(">HHl", table.platformID, table.platEncID, offset)
		return data + tableData

	def toXML(self, writer, ttFont):
		writer.simpletag("tableVersion", version=self.tableVersion)
		writer.newline()
		for table in self.tables:
			table.toXML(writer, ttFont)

	def fromXML(self, name, attrs, content, ttFont):
		if name == "tableVersion":
			self.tableVersion = safeEval(attrs["version"])
			return
		if name[:12] != "cmap_format_":
			return
		if not hasattr(self, "tables"):
			self.tables = []
		format = safeEval(name[12:])
		table = CmapSubtable.newSubtable(format)
		table.platformID = safeEval(attrs["platformID"])
		table.platEncID = safeEval(attrs["platEncID"])
		table.fromXML(name, attrs, content, ttFont)
		self.tables.append(table)

class CmapSubtable(object):

	@staticmethod
	def getSubtableClass(format):
		"""Return the subtable class for a format."""
		return cmap_classes.get(format, cmap_format_unknown)

	@staticmethod
	def newSubtable(format):
		"""Return a new instance of a subtable for format."""
		subtableClass = CmapSubtable.getSubtableClass(format)
		return subtableClass(format)

	def __init__(self, format):
		self.format = format
		self.data = None
		self.ttFont = None

	def __getattr__(self, attr):
		# allow lazy decompilation of subtables.
		if attr[:2] == '__': # don't handle requests for member functions like '__lt__'
			raise AttributeError(attr)
		if self.data is None:
			raise AttributeError(attr)
		self.decompile(None, None) # use saved data.
		self.data = None # Once this table has been decompiled, make sure we don't
						# just return the original data. Also avoids recursion when
						# called with an attribute that the cmap subtable doesn't have.
		return getattr(self, attr)

	def decompileHeader(self, data, ttFont):
		format, length, language = struct.unpack(">HHH", data[:6])
		assert len(data) == length, "corrupt cmap table format %d (data length: %d, header length: %d)" % (format, len(data), length)
		self.format = int(format)
		self.length = int(length)
		self.language = int(language)
		self.data = data[6:]
		self.ttFont = ttFont

	def toXML(self, writer, ttFont):
		writer.begintag(self.__class__.__name__, [
				("platformID", self.platformID),
				("platEncID", self.platEncID),
				("language", self.language),
				])
		writer.newline()
		codes = sorted(self.cmap.items())
		self._writeCodes(codes, writer)
		writer.endtag(self.__class__.__name__)
		writer.newline()

	def getEncoding(self, default=None):
		"""Returns the Python encoding name for this cmap subtable based on its platformID,
		platEncID, and language.  If encoding for these values is not known, by default
		None is returned.  That can be overriden by passing a value to the default
		argument.

		Note that if you want to choose a "preferred" cmap subtable, most of the time
		self.isUnicode() is what you want as that one only returns true for the modern,
		commonly used, Unicode-compatible triplets, not the legacy ones.
		"""
		return getEncoding(self.platformID, self.platEncID, self.language, default)

	def isUnicode(self):
		return (self.platformID == 0 or
			(self.platformID == 3 and self.platEncID in [0, 1, 10]))

	def isSymbol(self):
		return self.platformID == 3 and self.platEncID == 0

	def _writeCodes(self, codes, writer):
		isUnicode = self.isUnicode()
		for code, name in codes:
			writer.simpletag("map", code=hex(code), name=name)
			if isUnicode:
				writer.comment(Unicode[code])
			writer.newline()

	def __lt__(self, other):
		if not isinstance(other, CmapSubtable):
			return NotImplemented

		# implemented so that list.sort() sorts according to the spec.
		selfTuple = (
			getattr(self, "platformID", None),
			getattr(self, "platEncID", None),
			getattr(self, "language", None),
			self.__dict__)
		otherTuple = (
			getattr(other, "platformID", None),
			getattr(other, "platEncID", None),
			getattr(other, "language", None),
			other.__dict__)
		return selfTuple < otherTuple

class cmap_format_0(CmapSubtable):

	def decompile(self, data, ttFont):
		# we usually get here indirectly from the subtable __getattr__ function, in which case both args must be None.
		# If not, someone is calling  the subtable decompile() directly, and must provide both args.
		if data is not None and ttFont is not None:
			self.decompileHeader(data, ttFont)
		else:
			assert (data is None and ttFont is None), "Need both data and ttFont arguments"
		data = self.data # decompileHeader assigns the data after the header to self.data
		assert 262 == self.length, "Format 0 cmap subtable not 262 bytes"
		glyphIdArray = array.array("B")
		glyphIdArray.fromstring(self.data)
		self.cmap = cmap = {}
		lenArray = len(glyphIdArray)
		charCodes = list(range(lenArray))
		names = map(self.ttFont.getGlyphName, glyphIdArray)
		list(map(operator.setitem, [cmap]*lenArray, charCodes, names))

	def compile(self, ttFont):
		if self.data:
			return struct.pack(">HHH", 0, 262, self.language) + self.data

		charCodeList = sorted(self.cmap.items())
		charCodes = [entry[0] for entry in charCodeList]
		valueList = [entry[1] for entry in charCodeList]
		assert charCodes == list(range(256))
		valueList = map(ttFont.getGlyphID, valueList)

		glyphIdArray = array.array("B", valueList)
		data = struct.pack(">HHH", 0, 262, self.language) + glyphIdArray.tostring()
		assert len(data) == 262
		return data

	def fromXML(self, name, attrs, content, ttFont):
		self.language = safeEval(attrs["language"])
		if not hasattr(self, "cmap"):
			self.cmap = {}
		cmap = self.cmap
		for element in content:
			if not isinstance(element, tuple):
				continue
			name, attrs, content = element
			if name != "map":
				continue
			cmap[safeEval(attrs["code"])] = attrs["name"]

subHeaderFormat = ">HHhH"
class SubHeader(object):
	def __init__(self):
		self.firstCode = None
		self.entryCount = None
		self.idDelta = None
		self.idRangeOffset = None
		self.glyphIndexArray = []

class cmap_format_2(CmapSubtable):

	def setIDDelta(self, subHeader):
		subHeader.idDelta = 0
		# find the minGI which is not zero.
		minGI = subHeader.glyphIndexArray[0]
		for gid in subHeader.glyphIndexArray:
			if (gid != 0) and (gid < minGI):
				minGI = gid
		# The lowest gid in glyphIndexArray, after subtracting idDelta, must be 1.
		# idDelta is a short, and must be between -32K and 32K. minGI can be between 1 and 64K.
		# We would like to pick an idDelta such that the first glyphArray GID is 1,
		# so that we are more likely to be able to combine glypharray GID subranges.
		# This means that we have a problem when minGI is > 32K
		# Since the final gi is reconstructed from the glyphArray GID by:
		#    (short)finalGID = (gid +  idDelta) % 0x10000),
		# we can get from a glypharray GID of 1 to a final GID of 65K by subtracting 2, and casting the
		# negative number to an unsigned short.

		if  (minGI > 1):
			if  minGI > 0x7FFF:
				subHeader.idDelta = -(0x10000 - minGI) -1
			else:
				subHeader.idDelta =  minGI -1
			idDelta = subHeader.idDelta
			for i in range(subHeader.entryCount):
				gid = subHeader.glyphIndexArray[i]
				if gid > 0:
					subHeader.glyphIndexArray[i] = gid - idDelta

	def decompile(self, data, ttFont):
		# we usually get here indirectly from the subtable __getattr__ function, in which case both args must be None.
		# If not, someone is calling  the subtable decompile() directly, and must provide both args.
		if data is not None and ttFont is not None:
			self.decompileHeader(data, ttFont)
		else:
			assert (data is None and ttFont is None), "Need both data and ttFont arguments"

		data = self.data # decompileHeader assigns the data after the header to self.data
		subHeaderKeys = []
		maxSubHeaderindex = 0
		# get the key array, and determine the number of subHeaders.
		allKeys = array.array("H")
		allKeys.fromstring(data[:512])
		data = data[512:]
		if sys.byteorder != "big":
			allKeys.byteswap()
		subHeaderKeys = [ key//8 for key in allKeys]
		maxSubHeaderindex = max(subHeaderKeys)

		#Load subHeaders
		subHeaderList = []
		pos = 0
		for i in range(maxSubHeaderindex + 1):
			subHeader = SubHeader()
			(subHeader.firstCode, subHeader.entryCount, subHeader.idDelta, \
				subHeader.idRangeOffset) = struct.unpack(subHeaderFormat, data[pos:pos + 8])
			pos += 8
			giDataPos = pos + subHeader.idRangeOffset-2
			giList = array.array("H")
			giList.fromstring(data[giDataPos:giDataPos + subHeader.entryCount*2])
			if sys.byteorder != "big":
				giList.byteswap()
			subHeader.glyphIndexArray = giList
			subHeaderList.append(subHeader)
		# How this gets processed.
		# Charcodes may be one or two bytes.
		# The first byte of a charcode is mapped through the  subHeaderKeys, to select
		# a subHeader. For any subheader but 0, the next byte is then mapped through the
		# selected subheader. If subheader Index 0 is selected, then the byte itself is
		# mapped through the subheader, and there is no second byte.
		# Then assume that the subsequent byte is the first byte of the next charcode,and repeat.
		#
		# Each subheader references a range in the glyphIndexArray whose length is entryCount.
		# The range in glyphIndexArray referenced by a sunheader may overlap with the range in glyphIndexArray
		# referenced by another subheader.
		# The only subheader that will be referenced by more than one first-byte value is the subheader
		# that maps the entire range of glyphID values to glyphIndex 0, e.g notdef:
		#	 {firstChar 0, EntryCount 0,idDelta 0,idRangeOffset xx}
		# A byte being mapped though a subheader is treated as in index into a mapping of array index to font glyphIndex.
		# A subheader specifies a subrange within (0...256) by the
		# firstChar and EntryCount values. If the byte value is outside the subrange, then the glyphIndex is zero
		# (e.g. glyph not in font).
		# If the byte index is in the subrange, then an offset index is calculated as (byteIndex - firstChar).
		# The index to glyphIndex mapping is a subrange of the glyphIndexArray. You find the start of the subrange by
		# counting idRangeOffset bytes from the idRangeOffset word. The first value in this subrange is the
		# glyphIndex for the index firstChar. The offset index should then be used in this array to get the glyphIndex.
		# Example for Logocut-Medium
		# first byte of charcode = 129; selects subheader 1.
		# subheader 1 = {firstChar 64, EntryCount 108,idDelta 42,idRangeOffset 0252}
		# second byte of charCode = 66
		# the index offset = 66-64 = 2.
		# The subrange of the glyphIndexArray starting at 0x0252 bytes from the idRangeOffset word is:
		# [glyphIndexArray index], [subrange array index] = glyphIndex
		# [256], [0]=1 	from charcode [129, 64]
		# [257], [1]=2  	from charcode [129, 65]
		# [258], [2]=3  	from charcode [129, 66]
		# [259], [3]=4  	from charcode [129, 67]
		# So, the glyphIndex = 3 from the array. Then if idDelta is not zero and the glyph ID is not zero,
		# add it to the glyphID to get the final glyphIndex
		# value. In this case the final glyph index = 3+ 42 -> 45 for the final glyphIndex. Whew!

		self.data = b""
		self.cmap = cmap = {}
		notdefGI = 0
		for firstByte in range(256):
			subHeadindex = subHeaderKeys[firstByte]
			subHeader = subHeaderList[subHeadindex]
			if subHeadindex == 0:
				if (firstByte < subHeader.firstCode) or (firstByte >= subHeader.firstCode + subHeader.entryCount):
					continue # gi is notdef.
				else:
					charCode = firstByte
					offsetIndex = firstByte - subHeader.firstCode
					gi = subHeader.glyphIndexArray[offsetIndex]
					if gi != 0:
						gi = (gi + subHeader.idDelta) % 0x10000
					else:
						continue # gi is notdef.
				cmap[charCode] = gi
			else:
				if subHeader.entryCount:
					charCodeOffset = firstByte * 256 + subHeader.firstCode
					for offsetIndex in range(subHeader.entryCount):
						charCode = charCodeOffset + offsetIndex
						gi = subHeader.glyphIndexArray[offsetIndex]
						if gi != 0:
							gi = (gi + subHeader.idDelta) % 0x10000
						else:
							continue
						cmap[charCode] = gi
				# If not subHeader.entryCount, then all char codes with this first byte are
				# mapped to .notdef. We can skip this subtable, and leave the glyphs un-encoded, which is the
				# same as mapping it to .notdef.
		# cmap values are GID's.
		glyphOrder = self.ttFont.getGlyphOrder()
		gids = list(cmap.values())
		charCodes = list(cmap.keys())
		lenCmap = len(gids)
		try:
			names = list(map(operator.getitem, [glyphOrder]*lenCmap, gids ))
		except IndexError:
			getGlyphName = self.ttFont.getGlyphName
			names = list(map(getGlyphName, gids ))
		list(map(operator.setitem, [cmap]*lenCmap, charCodes, names))

	def compile(self, ttFont):
		if self.data:
			return struct.pack(">HHH", self.format, self.length, self.language) + self.data
		kEmptyTwoCharCodeRange = -1
		notdefGI = 0

		items = sorted(self.cmap.items())
		charCodes = [item[0] for item in items]
		names = [item[1] for item in items]
		nameMap = ttFont.getReverseGlyphMap()
		lenCharCodes = len(charCodes)
		try:
			gids = list(map(operator.getitem, [nameMap]*lenCharCodes, names))
		except KeyError:
			nameMap = ttFont.getReverseGlyphMap(rebuild=True)
			try:
				gids = list(map(operator.getitem, [nameMap]*lenCharCodes, names))
			except KeyError:
				# allow virtual GIDs in format 2 tables
				gids = []
				for name in names:
					try:
						gid = nameMap[name]
					except KeyError:
						try:
							if (name[:3] == 'gid'):
								gid = eval(name[3:])
							else:
								gid = ttFont.getGlyphID(name)
						except:
							raise KeyError(name)

					gids.append(gid)

		# Process the (char code to gid) item list  in char code order.
		# By definition, all one byte char codes map to subheader 0.
		# For all the two byte char codes, we assume that the first byte maps maps to the empty subhead (with an entry count of 0,
		# which defines all char codes in its range to map to notdef) unless proven otherwise.
		# Note that since the char code items are processed in char code order, all the char codes with the
		# same first byte are in sequential order.

		subHeaderKeys = [ kEmptyTwoCharCodeRange for x in  range(256)] # list of indices into subHeaderList.
		subHeaderList = []

		# We force this subheader entry 0  to exist in the subHeaderList in the case where some one comes up
		# with a cmap where all the one byte char codes map to notdef,
		# with the result that the subhead 0 would not get created just by processing the item list.
		charCode = charCodes[0]
		if charCode > 255:
			subHeader = SubHeader()
			subHeader.firstCode = 0
			subHeader.entryCount = 0
			subHeader.idDelta = 0
			subHeader.idRangeOffset = 0
			subHeaderList.append(subHeader)

		lastFirstByte = -1
		items = zip(charCodes, gids)
		for charCode, gid in items:
			if gid == 0:
				continue
			firstbyte = charCode >> 8
			secondByte = charCode & 0x00FF

			if firstbyte != lastFirstByte: # Need to update the current subhead, and start a new one.
				if lastFirstByte > -1:
					# fix GI's and iDelta of current subheader.
					self.setIDDelta(subHeader)

					# If it was sunheader 0 for one-byte charCodes, then we need to set the subHeaderKeys value to zero
					# for the indices matching the char codes.
					if lastFirstByte == 0:
						for index in range(subHeader.entryCount):
							charCode = subHeader.firstCode + index
							subHeaderKeys[charCode] = 0

					assert (subHeader.entryCount == len(subHeader.glyphIndexArray)), "Error - subhead entry count does not match len of glyphID subrange."
				# init new subheader
				subHeader = SubHeader()
				subHeader.firstCode = secondByte
				subHeader.entryCount = 1
				subHeader.glyphIndexArray.append(gid)
				subHeaderList.append(subHeader)
				subHeaderKeys[firstbyte] = len(subHeaderList) -1
				lastFirstByte = firstbyte
			else:
				# need to fill in with notdefs all the code points between the last charCode and the current charCode.
				codeDiff = secondByte - (subHeader.firstCode + subHeader.entryCount)
				for i in range(codeDiff):
					subHeader.glyphIndexArray.append(notdefGI)
				subHeader.glyphIndexArray.append(gid)
				subHeader.entryCount = subHeader.entryCount + codeDiff + 1

		# fix GI's and iDelta of last subheader that we we added to the subheader array.
		self.setIDDelta(subHeader)

		# Now we add a final subheader for the subHeaderKeys which maps to empty two byte charcode ranges.
		subHeader = SubHeader()
		subHeader.firstCode = 0
		subHeader.entryCount = 0
		subHeader.idDelta = 0
		subHeader.idRangeOffset = 2
		subHeaderList.append(subHeader)
		emptySubheadIndex = len(subHeaderList) - 1
		for index in range(256):
			if subHeaderKeys[index] == kEmptyTwoCharCodeRange:
				subHeaderKeys[index] = emptySubheadIndex
		# Since this is the last subheader, the GlyphIndex Array starts two bytes after the start of the
		# idRangeOffset word of this subHeader. We can safely point to the first entry in the GlyphIndexArray,
		# since the first subrange of the GlyphIndexArray is for subHeader 0, which always starts with
		# charcode 0 and GID 0.

		idRangeOffset = (len(subHeaderList)-1)*8 + 2 # offset to beginning of glyphIDArray from first subheader idRangeOffset.
		subheadRangeLen = len(subHeaderList) -1 # skip last special empty-set subheader; we've already hardocodes its idRangeOffset to 2.
		for index in range(subheadRangeLen):
			subHeader = subHeaderList[index]
			subHeader.idRangeOffset = 0


text:
import abc
import logging
import Sea
import numpy as np
import itertools
from ..base import Base

class Connection(Base, Sea.model.connections.Connection):
    """
    Abstract base class for all :mod:`Sea.adapter.connections` classes.
    """
    __metaclass__ = abc.ABCMeta

    def __init__(self, obj, system, components):
        Base.__init__(self, obj)
        obj.addProperty("App::PropertyLink", "System", "Component", "System this connection belongs to.")
        obj.System = system

        obj.couplings = self.couplings
        obj.makeCoupling = self.makeCoupling
        obj.updateCouplings = self.updateCouplings
        obj.addCouplings = self.addCouplings

        #obj.addProperty("App::PropertyLinkList", "Couplings", "Connection", "List of all couplings.")
        obj.addProperty("App::PropertyLinkList", "Components", "Connection", "Components that are connected via this connection.")
        obj.Frequency = system.Frequency

        #obj.addProperty("App::PropertyLink", "CouplingsGroup", "Groups", "Couplings that are part of System.")
        #obj.CouplingsGroup = group.newObject("App::DocumentObjectGroup", "GroupCouplings")
        #obj.CouplingsGroup.Label = "Couplings"

        #obj.addProperty("Part::PropertyPartShape", "Shape", "Connection", "Shape of the connection.")

        #obj.addProperty("App::PropertyBool", "UpdateCouplings", "Connection", "Update couplings when the connection changes.").UpdateCouplings = True

        #obj.addProperty("App::PropertyString", "Sort", "Connection", "Is the connection described by a point, line or area.")

        obj.addProperty("App::PropertyFloatList", "ImpedanceJunction", "Connection", "Total impedance at the junction.")
        obj.setEditorMode("ImpedanceJunction", 1)
        obj.Components = components

        #obj.Shape = component_a.Shape.common(component_b.Shape)

        obj.updateCouplings()

    def onChanged(self, obj, prop):
        Base.onChanged(self, obj, prop)

        if prop == 'Components':
            pass

        #elif prop == 'Shape':
            #self.updateCouplings(obj)

        #if prop == 'Frequency':
            #for coupling in obj.couplings():
                #coupling.Frequency = obj.Frequency

    def execute(self, obj):
        Base.execute(self, obj)

    @staticmethod
    def couplings(obj):
        return filter(Sea.actions.document.isCoupling, obj.InList)

    @abc.abstractmethod
    def updateComponents(self, obj):
        pass

    #@staticmethod
    #def updateShape(obj):
        #"""
        #Update the common shape between the components.
        #"""
        #connection = Sea.adapter.connection.ShapeConnection([item.Shape for item in self.Components])
        #shape = connection.shape()

        #obj.Shape = shape

    @staticmethod
    def updateCouplings(connection):
        """
        The shape has changed, which means couplings might have to change, be added or removed.
        To be sure all couplings in this connection are deleted and then build up from scratch.
        """

        """Remove all old couplings."""
        for coupling in connection.couplings():
            connection.Document.removeObject(coupling.Name)

        """Add couplings for every shape."""
        connection.addCouplings()

    @staticmethod
    def addCouplings(connection):
        """
        Add couplings to the :attr:`connection`.

        :param connection: an instance of :class:`Sea.adapter.baseclasses.Connection`
        """

        for comp_from, comp_to in itertools.permutations(connection.Components, 2):
            coupling_sort = Connection.determineCouplingType(connection.ClassName, comp_from, comp_to)

            if not coupling_sort:
                App.Console.PrintWarning("Cannot add coupling.\n")
                return

            for sub_from, sub_to in itertools.product(comp_from.subsystems(), comp_to.subsystems()):
                #print connection
                #print 'From: ' + comp_from.ClassName + sub_from
                #print 'To: ' + comp_to.ClassName + sub_to
                connection.makeCoupling(sub_from, sub_to, coupling_sort)

    coupling_options = {
            ('ConnectionPoint', 'Component1DBeam', 'Component1DBeam') : 'Coupling1DStructural',
            ('ConnectionLine', 'Component1DBeam', 'Component1DBeam') : 'Coupling1DStructural',
            ('ConnectionSurface', 'Component1DBeam', 'Component1DBeam') : 'Coupling1DStructural',
            ('ConnectionPoint', 'Component2DPlate', 'Component2DPlate') : 'Coupling1DStructural',
            ('ConnectionLine', 'Component2DPlate', 'Component2DPlate') : 'Coupling2DStructural',
            ('ConnectionSurface', 'Component2DPlate', 'Component2DPlate') : 'Coupling2DStructural',

            ('ConnectionSurface', 'Component2DPlate', 'Component3DCavity') : 'Coupling3DPlateCavity',
            ('ConnectionSurface', 'Component3DCavity', 'Component2DPlate') : 'Coupling3DCavityPlate',
        }

    @staticmethod
    def determineCouplingType(connection_type, component_from, component_to):
        """
        Determine the type of coupling. Detects what type of connection the components have.
        Based on the type of connection and on the types of components a coupling is returned.

        :param component_from: an instance of a child of :class:`Sea.adapter.baseclasses.Component`
        :param component_to: an instance of a child of :class:`Sea.adapter.baseclasses.Component`
        """

        if connection_type:
            item = (connection_type, component_from.ClassName, component_to.ClassName)
            try:
                return Connection.coupling_options[item]
            except KeyError:
                txt = 'Could not determine the type of coupling for ' + component_from.ClassName + ' to ' + component_to.ClassName + ' with ' + connection_type +  '.\n'
                App.Console.PrintWarning(txt)
                return None

    @staticmethod
    def makeCoupling(connection, subsystem_from, subsystem_to, sort):
        """
        Add a coupling to system.

        :param connection: an instance of :class:`Sea.adapter.baseclasses.Connection`
        :param component_from: an instance of a child of :class:`Sea.adapter.baseclasses.Component`
        :param subsystem_from: string representing the type of subsystem
        :param component_to: an instance of a child of :class:`Sea.adapter.baseclasses.Component`
        :param subsystem_to: string representing the type of subsystem
        :param sort: sort of coupling as specified in :class:`Sea.adapter.couplings.couplings_map`

        """
        #if connection.System == component_from.System == component_to.System:
        from Sea.adapter.object_maps import couplings_map

        obj = connection.Document.addObject("App::FeaturePython", 'Coupling')
        couplings_map[sort](obj, connection, subsystem_from, subsystem_to)
        try:
            Sea.adapter.couplings.ViewProviderCoupling(obj.ViewObject)
        except AttributeError:
            pass
        obj.Label = obj.ClassName + '_' + subsystem_from.ClassName.replace('Subsystem', '') + '_to_' + subsystem_to.ClassName.replace('Subsystem', '')
        logging.info("Sea: Created %s.", obj.Name)
        obj.Document.recompute()
        return obj


text:
#!/usr/bin/env python3
#author markpurcell@ie.ibm.com

"""RabbitMQ helper class.
/*
 * 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.
 */
"""

"""
IBM-Review-Requirement: Art30.3 - DO NOT TRANSFER OR EXCLUSIVELY LICENSE THE FOLLOWING CODE UNTIL 30/11/2025!
Please note that the following code was developed for the project MUSKETEER in DRL funded by the European Union
under the Horizon 2020 Program.
The project started on 01/12/2018 and was completed on 30/11/2021. Thus, in accordance with article 30.3 of the
Multi-Beneficiary General Model Grant Agreement of the Program, the above limitations are in force until 30/11/2025.
"""

import pytest
import json

def pytest_addoption(parser):
    parser.addoption("--credentials", required=True)
    parser.addoption("--feed_queue", required=False)
    parser.addoption("--reply_queue", required=False)

@pytest.fixture
def credentials(request):
    value = request.config.getoption('credentials')
    if request.cls:
        with open(value) as json_file:
            request.cls.credentials = json.load(json_file)
    return value

@pytest.fixture
def feed_queue(request):
    value = request.config.getoption('feed_queue')
    if request.cls:
        request.cls.feed_queue = value
    return value

@pytest.fixture
def reply_queue(request):
    value = request.config.getoption('reply_queue')
    if request.cls:
        request.cls.reply_queue = value
    return value


text:
import json
import hashlib
import os
import pickle
import re
import shutil

class Block:
    def __init__(self, numberBlock, data, previousHash, idHash):
        self._idBlock = numberBlock
        self._data = data
        self._previousHash = previousHash
        self._idHash = idHash
        self._checker = True

    def getIdBlock(self):
        return self._idBlock

    def getData(self):
        return self._data

    def getPreviousHash(self):
        return self._previousHash

    def getIdHash(self):
        return self._idHash

    def getChecker(self):
        return self._checker

    def setData(self, data):
        self._data = data

    def setIdHash(self, idHash):
        self._idHash = idHash

    def setChecker(self, boolInfo):
        self._checker = boolInfo

    def getBlock(self):
        return [self._idBlock, self._data, self._previousHash, self._idHash]

    def getInfoGraph(self):
        info = "Bloque: " + str(self._idBlock) + "\\nData: " + str(self._data) + "\\nHash Bloque: " + str(self._idHash)\
               + "\\nHash Ant.: " + str(self._previousHash)
        return info

    def verifyBlock(self, hashAnteriorBA):
        if hashAnteriorBA == self._previousHash:
            return True
        # self._checker = False
        return False

class Blockchain:
    def __init__(self):
        self.idChain = 1
        self.previous = 0
        self.blocks_list = []
        self.firstHash = ""
        self.checkerChain = True

    def generate_hash(self, data):
        pattern = r'[0-9a-zA-Z]+'
        objectStr = pickle.dumps(data)
        while True:
            id_hash = hashlib.sha256(objectStr).hexdigest()
            if re.match(pattern, id_hash):
                return id_hash

    def verifyFirstBlock(self, hashActual):
        if self.firstHash == hashActual:
            return True
        return False

    def insertBlock(self, tupla, nameJson):
        id_hash = self.generate_hash(tupla)
        newBlock = Block(self.idChain, tupla, self.previous, id_hash)
        self.blocks_list.append(newBlock)

        file = self.load_json(nameJson)
        file.write(json.dumps([j.getBlock() for j in self.blocks_list]))
        file.close()

        # only for the first
        if self.idChain == 1:
            self.firstHash = id_hash

        self.idChain += 1
        self.previous = id_hash

    def graphBlockchain(self, nombreImagen):
        graph = 'digraph G{\n'
        graph += 'rankdir=LR;\n'
        graph += "node[shape = \"box\"]\n"
        graph += self.__graficar()
        graph += '}'
        direccion = self.pathImageGraph()
        file = open(f"{direccion}\\{nombreImagen}.dot", "w")
        file.write(graph)
        file.close()
        os.system(f'dot -Tpng {direccion}\\{nombreImagen}.dot -o {direccion}\\{nombreImagen}.png')

    def __graficar(self):
        graph = ""
        bandera = True
        for i in range(len(self.blocks_list)):
            info = self.blocks_list[i].getInfoGraph()
            nodo = 'node' + str(self.blocks_list[i].getIdBlock())
            color = "green"

            # If is not the first, verify the previous hash
            if not (i == 0):
                hashAnterior = self.blocks_list[i-1].getIdHash()
                brokeChain = self.blocks_list[i].verifyBlock(str(hashAnterior))

            # If is the first, verify the actual hash, because the first always has previous in 0
            else:
                hashActual = self.blocks_list[i].getIdHash()
                brokeChain = self.verifyFirstBlock(hashActual)

            if not brokeChain:
                self.checkerChain = False
                bandera = False

            if bandera is False:
                color = "red"

            # If is not the last to put the next pointer
            if not (i == (len(self.blocks_list) - 1)):
                nextId = self.blocks_list[i + 1].getIdBlock()
                nextNodo = 'node' + str(nextId)
                graph += nodo + f'[label="{info}", color="{color}", penwidth=3]\n'
                graph += nodo + '->' + nextNodo + '\n'

            # If is the Last not put the next pointer
            else:
                graph += nodo + f'[label="{info}", color="{color}", penwidth=3]\n'

            # If is not the First to the Back pointer
            if not (i == 0):
                nodoAnterior = "node" + str(self.blocks_list[i-1].getIdBlock())
                if color == "green":
                    graph += nodo + '->' + nodoAnterior + "\n"
                graph += nodoAnterior + f"[color={color}]"
        return graph

    def updateBlock(self, oldTuple, newTuple, nameJson):
        # Cambiando valores de la lista y generando nuevo hash
        file = open(os.getcwd() + "\\DataJsonBC\\" + nameJson + ".json", "r")
        JSblock_list = json.loads(file.read())
        file.close()

        newHash = self.generate_hash(newTuple)

        # Recorriendo y actualizando JSON
        for blockJS in JSblock_list:
            if oldTuple == blockJS[1]:
                blockJS[1] = newTuple
                blockJS[3] = newHash

        # recorriendo y actualizando Block list
        for block in self.blocks_list:
            if oldTuple == block.getData():
                block.setData(newTuple)
                block.setIdHash(newHash)

        file = open(os.getcwd() + "\\DataJsonBC\\" + nameJson + ".json", "w+")
        file.write(json.dumps(JSblock_list))
        file.close()

    # ------------------------------------------------------- FILES ----------------------------------------------------
    def load_json(self, nombre):
        if os.path.isdir(os.getcwd() + "\\DataJsonBC"):
            file = open(os.getcwd() + "\\DataJsonBC\\" + nombre + ".json", "+w")
            return file
        os.makedirs(os.getcwd() + "\\DataJsonBC")
        file = open(os.getcwd() + "\\DataJsonBC\\" + nombre + ".json", "+w")
        return file

    def pathImageGraph(self):
        if not os.path.isdir(os.getcwd() + "\\ImageBlockChain"):
            os.makedirs(os.getcwd() + "\\ImageBlockChain")
        direccion = os.getcwd() + "\\ImageBlockChain"
        return direccion

    def removeFilesBlock(self, nameJson):
        if os.path.isdir(os.getcwd() + "\\DataJsonBC"):
            if os.path.isfile(os.getcwd() + "\\DataJsonBC\\" + nameJson + ".json"):
                os.remove(os.getcwd() + "\\DataJsonBC\\" + nameJson + ".json")
                # os.remove(os.getcwd() + "\\DataJsonBC\\" + nameJson + ".dot")


text:
# coding=utf-8
# *** WARNING: this file was generated by the Pulumi Terraform Bridge (tfgen) Tool. ***
# *** Do not edit by hand unless you're certain you know what you are doing! ***

import warnings
import pulumi
import pulumi.runtime
from typing import Any, Mapping, Optional, Sequence, Union, overload
from .. import _utilities
from . import outputs

__all__ = [
    'GetListenerResult',
    'AwaitableGetListenerResult',
    'get_listener',
    'get_listener_output',
]

warnings.warn("""aws.elasticloadbalancingv2.getListener has been deprecated in favor of aws.lb.getListener""", DeprecationWarning)

@pulumi.output_type
class GetListenerResult:
    """
    A collection of values returned by getListener.
    """
    def __init__(__self__, alpn_policy=None, arn=None, certificate_arn=None, default_actions=None, id=None, load_balancer_arn=None, port=None, protocol=None, ssl_policy=None, tags=None):
        if alpn_policy and not isinstance(alpn_policy, str):
            raise TypeError("Expected argument 'alpn_policy' to be a str")
        pulumi.set(__self__, "alpn_policy", alpn_policy)
        if arn and not isinstance(arn, str):
            raise TypeError("Expected argument 'arn' to be a str")
        pulumi.set(__self__, "arn", arn)
        if certificate_arn and not isinstance(certificate_arn, str):
            raise TypeError("Expected argument 'certificate_arn' to be a str")
        pulumi.set(__self__, "certificate_arn", certificate_arn)
        if default_actions and not isinstance(default_actions, list):
            raise TypeError("Expected argument 'default_actions' to be a list")
        pulumi.set(__self__, "default_actions", default_actions)
        if id and not isinstance(id, str):
            raise TypeError("Expected argument 'id' to be a str")
        pulumi.set(__self__, "id", id)
        if load_balancer_arn and not isinstance(load_balancer_arn, str):
            raise TypeError("Expected argument 'load_balancer_arn' to be a str")
        pulumi.set(__self__, "load_balancer_arn", load_balancer_arn)
        if port and not isinstance(port, int):
            raise TypeError("Expected argument 'port' to be a int")
        pulumi.set(__self__, "port", port)
        if protocol and not isinstance(protocol, str):
            raise TypeError("Expected argument 'protocol' to be a str")
        pulumi.set(__self__, "protocol", protocol)
        if ssl_policy and not isinstance(ssl_policy, str):
            raise TypeError("Expected argument 'ssl_policy' to be a str")
        pulumi.set(__self__, "ssl_policy", ssl_policy)
        if tags and not isinstance(tags, dict):
            raise TypeError("Expected argument 'tags' to be a dict")
        pulumi.set(__self__, "tags", tags)

    @property
    @pulumi.getter(name="alpnPolicy")
    def alpn_policy(self) -> str:
        return pulumi.get(self, "alpn_policy")

    @property
    @pulumi.getter
    def arn(self) -> str:
        return pulumi.get(self, "arn")

    @property
    @pulumi.getter(name="certificateArn")
    def certificate_arn(self) -> str:
        return pulumi.get(self, "certificate_arn")

    @property
    @pulumi.getter(name="defaultActions")
    def default_actions(self) -> Sequence['outputs.GetListenerDefaultActionResult']:
        return pulumi.get(self, "default_actions")

    @property
    @pulumi.getter
    def id(self) -> str:
        """
        The provider-assigned unique ID for this managed resource.
        """
        return pulumi.get(self, "id")

    @property
    @pulumi.getter(name="loadBalancerArn")
    def load_balancer_arn(self) -> str:
        return pulumi.get(self, "load_balancer_arn")

    @property
    @pulumi.getter
    def port(self) -> int:
        return pulumi.get(self, "port")

    @property
    @pulumi.getter
    def protocol(self) -> str:
        return pulumi.get(self, "protocol")

    @property
    @pulumi.getter(name="sslPolicy")
    def ssl_policy(self) -> str:
        return pulumi.get(self, "ssl_policy")

    @property
    @pulumi.getter
    def tags(self) -> Mapping[str, str]:
        return pulumi.get(self, "tags")

class AwaitableGetListenerResult(GetListenerResult):
    # pylint: disable=using-constant-test
    def __await__(self):
        if False:
            yield self
        return GetListenerResult(
            alpn_policy=self.alpn_policy,
            arn=self.arn,
            certificate_arn=self.certificate_arn,
            default_actions=self.default_actions,
            id=self.id,
            load_balancer_arn=self.load_balancer_arn,
            port=self.port,
            protocol=self.protocol,
            ssl_policy=self.ssl_policy,
            tags=self.tags)

def get_listener(arn: Optional[str] = None,
                 load_balancer_arn: Optional[str] = None,
                 port: Optional[int] = None,
                 tags: Optional[Mapping[str, str]] = None,
                 opts: Optional[pulumi.InvokeOptions] = None) -> AwaitableGetListenerResult:
    """
    > **Note:** `alb.Listener` is known as `lb.Listener`. The functionality is identical.

    Provides information about a Load Balancer Listener.

    This data source can prove useful when a module accepts an LB Listener as an input variable and needs to know the LB it is attached to, or other information specific to the listener in question.

    ## Example Usage

    ```python
    import pulumi
    import pulumi_aws as aws

    config = pulumi.Config()
    listener_arn = config.require("listenerArn")
    listener = aws.lb.get_listener(arn=listener_arn)
    selected = aws.lb.get_load_balancer(name="default-public")
    selected443 = aws.lb.get_listener(load_balancer_arn=selected.arn,
        port=443)
    ```

    :param str arn: ARN of the listener. Required if `load_balancer_arn` and `port` is not set.
    :param str load_balancer_arn: ARN of the load balancer. Required if `arn` is not set.
    :param int port: Port of the listener. Required if `arn` is not set.
    """
    pulumi.log.warn("""get_listener is deprecated: aws.elasticloadbalancingv2.getListener has been deprecated in favor of aws.lb.getListener""")
    __args__ = dict()
    __args__['arn'] = arn
    __args__['loadBalancerArn'] = load_balancer_arn
    __args__['port'] = port
    __args__['tags'] = tags
    if opts is None:
        opts = pulumi.InvokeOptions()
    if opts.version is None:
        opts.version = _utilities.get_version()
    __ret__ = pulumi.runtime.invoke('aws:elasticloadbalancingv2/getListener:getListener', __args__, opts=opts, typ=GetListenerResult).value

    return AwaitableGetListenerResult(
        alpn_policy=__ret__.alpn_policy,
        arn=__ret__.arn,
        certificate_arn=__ret__.certificate_arn,
        default_actions=__ret__.default_actions,
        id=__ret__.id,
        load_balancer_arn=__ret__.load_balancer_arn,
        port=__ret__.port,
        protocol=__ret__.protocol,
        ssl_policy=__ret__.ssl_policy,
        tags=__ret__.tags)

@_utilities.lift_output_func(get_listener)
def get_listener_output(arn: Optional[pulumi.Input[Optional[str]]] = None,
                        load_balancer_arn: Optional[pulumi.Input[Optional[str]]] = None,
                        port: Optional[pulumi.Input[Optional[int]]] = None,
                        tags: Optional[pulumi.Input[Optional[Mapping[str, str]]]] = None,
                        opts: Optional[pulumi.InvokeOptions] = None) -> pulumi.Output[GetListenerResult]:
    """
    > **Note:** `alb.Listener` is known as `lb.Listener`. The functionality is identical.

    Provides information about a Load Balancer Listener.

    This data source can prove useful when a module accepts an LB Listener as an input variable and needs to know the LB it is attached to, or other information specific to the listener in question.

    ## Example Usage

    ```python
    import pulumi
    import pulumi_aws as aws

    config = pulumi.Config()
    listener_arn = config.require("listenerArn")
    listener = aws.lb.get_listener(arn=listener_arn)
    selected = aws.lb.get_load_balancer(name="default-public")
    selected443 = aws.lb.get_listener(load_balancer_arn=selected.arn,
        port=443)
    ```

    :param str arn: ARN of the listener. Required if `load_balancer_arn` and `port` is not set.
    :param str load_balancer_arn: ARN of the load balancer. Required if `arn` is not set.
    :param int port: Port of the listener. Required if `arn` is not set.
    """
    pulumi.log.warn("""get_listener is deprecated: aws.elasticloadbalancingv2.getListener has been deprecated in favor of aws.lb.getListener""")
    ...


text:
#!/usr/bin/env python
# -*- coding: utf-8 -*-

#
# This is very different to AboutModules in Ruby Koans
# Our AboutMultipleInheritance class is a little more comparable
#

from runner.koan import *

#
# Package hierarchy of Python Koans project:
#
# contemplate_koans.py
# koans/
#     __init__.py
#     about_asserts.py
#     about_attribute_access.py
#     about_class_attributes.py
#     about_classes.py
#     ...
#     a_package_folder/
#         __init__.py
#         a_module.py

class AboutPackages(Koan):
    def test_subfolders_can_form_part_of_a_module_package(self):
        # Import ./a_package_folder/a_module.py
        from a_package_folder.a_module import Duck

        duck = Duck()
        self.assertEqual("Donald", duck.name)

    def test_subfolders_become_modules_if_they_have_an_init_module(self):
        # Import ./a_package_folder/__init__.py
        from a_package_folder import an_attribute

        self.assertEqual(1984, an_attribute)

    def test_subfolders_without_an_init_module_are_not_part_of_the_package(self):
        # Import ./a_normal_folder/
        try:
            import a_normal_folder
        except ImportError as ex:
            self.assertMatch('normal', ex[0])

    # ------------------------------------------------------------------

    def test_use_absolute_imports_to_import_upper_level_modules(self):
        # Import /contemplate_koans.py
        import contemplate_koans

        self.assertEqual('contemplate_koans', contemplate_koans.__name__)

        # contemplate_koans.py is the root module in this package because its
        # the first python module called in koans.
        #
        # If contemplate_koan.py was based in a_package_folder that would be
        # the root folder, which would make reaching the koans folder
        # almost impossible. So always leave the starting python script in
        # a folder which can reach everything else.

    def test_import_a_module_in_a_subfolder_using_an_absolute_path(self):
        # Import contemplate_koans.py/koans/a_package_folder/a_module.py
        from koans.a_package_folder.a_module import Duck

        self.assertEqual('koans.a_package_folder.a_module', Duck.__module__)


text:
nome = input('Qual é o seu nome? ')
print('Olá', nome + '! Prazer em te conhecer!')


text:
#!/usr/bin/env python3
# Copyright (c) 2014-2017 The Bitcoin Core developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
"""Test the getchaintips RPC.

- introduce a network split
- work on chains of different lengths
- join the network together again
- verify that getchaintips now returns two chain tips.
"""

from test_framework.test_framework import ibacoinTestFramework
from test_framework.util import assert_equal

class GetChainTipsTest (ibacoinTestFramework):
    def set_test_params(self):
        self.num_nodes = 4

    def run_test (self):
        tips = self.nodes[0].getchaintips ()
        assert_equal (len (tips), 1)
        assert_equal (tips[0]['branchlen'], 0)
        assert_equal (tips[0]['height'], 200)
        assert_equal (tips[0]['status'], 'active')

        # Split the network and build two chains of different lengths.
        self.split_network ()
        self.nodes[0].generate(10)
        self.nodes[2].generate(20)
        self.sync_all(self.nodes[:2])
        self.sync_all(self.nodes[2:])

        tips = self.nodes[1].getchaintips ()
        assert_equal (len (tips), 1)
        shortTip = tips[0]
        assert_equal (shortTip['branchlen'], 0)
        assert_equal (shortTip['height'], 210)
        assert_equal (tips[0]['status'], 'active')

        tips = self.nodes[3].getchaintips ()
        assert_equal (len (tips), 1)
        longTip = tips[0]
        assert_equal (longTip['branchlen'], 0)
        assert_equal (longTip['height'], 220)
        assert_equal (tips[0]['status'], 'active')

        # Join the network halves and check that we now have two tips
        # (at least at the nodes that previously had the short chain).
        self.join_network ()

        tips = self.nodes[0].getchaintips ()
        assert_equal (len (tips), 2)
        assert_equal (tips[0], longTip)

        assert_equal (tips[1]['branchlen'], 10)
        assert_equal (tips[1]['status'], 'valid-fork')
        tips[1]['branchlen'] = 0
        tips[1]['status'] = 'active'
        assert_equal (tips[1], shortTip)

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


text:
from .plot import plot
from .simple_plot import simple_plot