예제 #1
0
 def test_to_yaml_basic(self):
     a = Box(test_dict)
     assert yaml.load(a.to_yaml(), Loader=yaml.SafeLoader) == test_dict
예제 #2
0
 def get_range(self):
     """Return valid range."""
     return Box(self._range)
예제 #3
0
def run_test(in_file, test_spec, global_cfg):
    """Run a single tavern test

    Note that each tavern test can consist of multiple requests (log in,
    create, update, delete, etc).

    The global configuration is copied and used as an initial configuration for
    this test. Any values which are saved from any tests are saved into this
    test block and can be used for formatting in later stages in the test.

    Args:
        in_file (str): filename containing this test
        test_spec (dict): The specification for this test
        global_cfg (dict): Any global configuration for this test

    No Longer Raises:
        TavernException: If any of the tests failed
    """

    # pylint: disable=too-many-locals

    # Initialise test config for this test with the global configuration before
    # starting
    test_block_config = dict(global_cfg)

    if "variables" not in test_block_config:
        test_block_config["variables"] = {}

    tavern_box = Box({"env_vars": dict(os.environ)})

    if not test_spec:
        logger.warning("Empty test block in %s", in_file)
        return

    # Get included stages and resolve any into the test spec dictionary
    available_stages = test_block_config.get("stages", [])
    included_stages = _get_included_stages(tavern_box, test_block_config,
                                           test_spec, available_stages)
    all_stages = {s["id"]: s for s in available_stages + included_stages}
    test_spec["stages"] = _resolve_test_stages(test_spec, all_stages)

    test_block_config["variables"]["tavern"] = tavern_box

    test_block_name = test_spec["test_name"]

    # Strict on body by default
    default_strictness = test_block_config["strict"]

    logger.info("Running test : %s", test_block_name)

    with ExitStack() as stack:
        sessions = get_extra_sessions(test_spec, test_block_config)

        for name, session in sessions.items():
            logger.debug("Entering context for %s", name)
            stack.enter_context(session)

        def getonly(stage):
            o = stage.get("only")
            if o is None:
                return False
            elif isinstance(o, bool):
                return o
            else:
                return strtobool(o)

        has_only = any(getonly(stage) for stage in test_spec["stages"])

        # Run tests in a path in order
        for stage in test_spec["stages"]:
            if stage.get("skip"):
                continue
            elif has_only and not getonly(stage):
                continue

            test_block_config["strict"] = default_strictness

            # Can be overridden per stage
            # NOTE
            # this is hardcoded to check for the 'response' block. In the far
            # future there might not be a response block, but at the moment it
            # is the hardcoded value for any HTTP request.
            if stage.get("response", {}):
                if stage.get("response").get("strict", None) is not None:
                    stage_strictness = stage.get("response").get(
                        "strict", None)
                elif test_spec.get("strict", None) is not None:
                    stage_strictness = test_spec.get("strict", None)
                else:
                    stage_strictness = default_strictness

                logger.debug("Strict key checking for this stage is '%s'",
                             stage_strictness)

                test_block_config["strict"] = stage_strictness
            elif default_strictness:
                logger.debug("Default strictness '%s' ignored for this stage",
                             default_strictness)

            # Wrap run_stage with retry helper
            run_stage_with_retries = retry(stage, test_block_config)(run_stage)

            try:
                run_stage_with_retries(sessions, stage, tavern_box,
                                       test_block_config)
            except exceptions.TavernException as e:
                e.stage = stage
                e.test_block_config = test_block_config
                raise

            if getonly(stage):
                break
예제 #4
0
from minikts.monitoring import report, shorten_path

def _join_path(loader, node):
    seq = loader.construct_sequence(node)
    return Path().joinpath(*seq)

def _get_from_env(loader, node):
    return os.environ.get(node.value, None)

yaml.SafeLoader.add_constructor('!join_path', _join_path)
yaml.SafeLoader.add_constructor('!env', _get_from_env)

_CONFIG_FILENAME = None
_CONFIG_POSTLOAD_HOOKS = []

config = Box(box_dots=True)
hparams = Box(box_dots=True)

def load_config(filename, postload_hooks=True):
    global _CONFIG_FILENAME
    _CONFIG_FILENAME = filename
    loaded_config = Box.from_yaml(
        filename=filename, 
        box_dots=True,
        Loader=yaml.SafeLoader
    )
    report("config", f"Loaded config from [!path]{shorten_path(filename)}[/]")

    config.merge_update(loaded_config)
    if "hparams" in loaded_config:
        hparams.merge_update(loaded_config.hparams)
예제 #5
0
def build(
    source,
    video_track,
    ffmpeg,
    temp_dir,
    output_video,
    bitrate=None,
    crf=None,
    preset="fast",
    audio_tracks=(),
    subtitle_tracks=(),
    disable_hdr=False,
    side_data=None,
    pix_fmt="yuv420p",
    tune=None,
    profile="default",
    attachments="",
    **kwargs,
):
    filters = generate_filters(disable_hdr=disable_hdr, **kwargs)
    audio = build_audio(audio_tracks)
    subtitles = build_subtitle(subtitle_tracks)
    ending = generate_ending(audio=audio,
                             subtitles=subtitles,
                             cover=attachments,
                             output_video=output_video,
                             **kwargs)

    if not side_data:
        side_data = Box(default_box=True)

    beginning = generate_ffmpeg_start(
        source=source,
        ffmpeg=ffmpeg,
        encoder="libx264",
        video_track=video_track,
        filters=filters,
        pix_fmt=pix_fmt,
        **kwargs,
    )

    beginning += f'{f"-tune {tune}" if tune else ""} '

    if profile and profile != "default":
        beginning += f"-profile {profile} "

    if not disable_hdr and pix_fmt == "yuv420p10le":

        if side_data and side_data.get("color_primaries") == "bt2020":
            beginning += "-color_primaries bt2020 -color_trc smpte2084 -colorspace bt2020nc"

    if side_data.cll:
        pass

    extra_data = "-map_chapters 0 "  # -map_metadata 0 # safe to do for rotation?
    pass_log_file = Path(
        temp_dir) / f"pass_log_file_{secrets.token_hex(10)}.log"

    if bitrate:
        command_1 = (
            f"{beginning} -pass 1 "
            f'-passlogfile "{pass_log_file}" -b:v {bitrate} -preset {preset} -an -sn -dn -f mp4 {null}'
        )
        command_2 = (f'{beginning} -pass 2 -passlogfile "{pass_log_file}" '
                     f"-b:v {bitrate} -preset {preset} {extra_data}") + ending
        return [
            Command(re.sub("[ ]+", " ", command_1), ["ffmpeg", "output"],
                    False,
                    name="First pass bitrate",
                    exe="ffmpeg"),
            Command(re.sub("[ ]+", " ", command_2), ["ffmpeg", "output"],
                    False,
                    name="Second pass bitrate",
                    exe="ffmpeg"),
        ]

    elif crf:
        command = (f"{beginning} -crf {crf} "
                   f"-preset {preset} {extra_data}") + ending
        return [
            Command(re.sub("[ ]+", " ", command), ["ffmpeg", "output"],
                    False,
                    name="Single pass CRF",
                    exe="ffmpeg")
        ]

    else:
        return []
예제 #6
0
 def test_camel_killer_hashables(self):
     bx = Box(camel_killer_box=True)
     bx[(1, 2)] = 32
     assert bx == {(1, 2): 32}
예제 #7
0
 def test_type_recast(self):
     b = Box(id="6", box_recast={"id": int})
     assert isinstance(b.id, int)
     with pytest.raises(ValueError):
         b["sub_box"] = {"id": "bad_id"}
예제 #8
0
 def test_safe_attrs(self):
     assert Box()._safe_attr("BAD!KEY!1") == "BAD_KEY_1"
     assert Box(camel_killer_box=True)._safe_attr("BAD!KEY!2") == "bad_key_2"
     assert Box()._safe_attr((5, 6, 7)) == "x5_6_7"
     assert Box()._safe_attr(356) == "x356"
예제 #9
0
 def test_pickle_default_box(self):
     if platform.python_implementation() == "PyPy":
         pytest.skip("Pickling does not work correctly on PyPy")
     bb = Box(default_box=True)
     loaded = pickle.loads(pickle.dumps(bb))
     assert bb == loaded
예제 #10
0
 def test_from_yaml(self):
     bx = Box.from_yaml(yaml.dump(test_dict), conversion_box=False, default_box=True)
     assert isinstance(bx, Box)
     assert bx.key1 == "value1"
     assert bx.Key_2 == Box()
예제 #11
0
 def test_box_modify_tuples(self):
     bx = Box(extended_test_dict, modify_tuples_box=True)
     assert bx.tuples_galore[0].item == 3
     assert isinstance(bx.tuples_galore[0], Box)
     assert isinstance(bx.tuples_galore[1], tuple)
예제 #12
0
 def test_set_default_dict(self):
     a = Box(test_dict)
     new = a.setdefault("key3", {})
     new.yy = 8
     assert a.key3.yy == 8
예제 #13
0
 def test_auto_attr(self):
     a = Box(test_dict, default_box=True)
     assert isinstance(a.a.a.a.a, Box)
     a.b.b = 4
     assert a.b.b == 4
예제 #14
0
 def test_to_yaml_file(self):
     a = Box(test_dict)
     a.to_yaml(tmp_yaml_file)
     with open(tmp_yaml_file) as f:
         data = yaml.load(f, Loader=yaml.SafeLoader)
         assert data == test_dict
예제 #15
0
 def test_revered(self):
     bx = Box()
     bx.a = 1
     bx.c = 2
     assert list(reversed(bx)) == ["c", "a"]
예제 #16
0
 def test_conversion_dup_only(self):
     with pytest.raises(BoxError):
         Box(movie_data, conversion_box=False, box_duplicates="error")
예제 #17
0
 def test_bad_recursive(self):
     b = Box()
     bl = b.setdefault("l", [])
     bl.append(["foo"])
     assert bl == [["foo"]], bl
예제 #18
0
 def test_get_default_box(self):
     bx = Box(default_box=True)
     assert bx.get("test", 4) == 4
     assert isinstance(bx.get("a"), Box)
     assert bx.get("test", None) is None
예제 #19
0
 def test_or_boxes(self):
     b = Box(c=1, d={"sub": 1}, e=1)
     c = dict(d={"val": 2}, e=4)
     assert b | c == Box(c=1, d={"val": 2}, e=4)
     with pytest.raises(BoxError):
         Box() | BoxList()
예제 #20
0
 def test_through_queue(self):
     my_box = Box(a=4, c={"d": 3})
     queue = Queue()
     queue.put(my_box)
     assert queue.get()
예제 #21
0
파일: heremap.py 프로젝트: pdubeau/geemap
from here_map_widget import (
    FullscreenControl,
    MeasurementControl,
    ScaleBar,
    ZoomControl,
    ImageTileProvider,
    MapSettingsControl,
    TileLayer,
    GeoJSON,
    WidgetControl,
    LayersControl,
)


basemaps = Box(xyz_to_heremap(), frozen_box=True)


class Map(here_map_widget.Map):
    """
    The Map class inherits here_map_widget.Map. The arguments you can pass to the Map can be found
    at https://here-map-widget-for-jupyter.readthedocs.io/en/latest/api_reference/map.html.

    Returns:
        object: here_map_widget map object.
    """

    def __init__(self, api_key=None, **kwargs):

        # Authenticates Earth Engine and initializes an Earth Engine session
        if "ee_initialize" not in kwargs.keys():
예제 #22
0
 def test_update_with_integer(self):
     bx = Box()
     bx[1] = 4
     assert bx[1] == 4
     bx.update({1: 2})
     assert bx[1] == 2
예제 #23
0
    def Boundaries(self):
        b = Box()
        path = self.path

        currX = currY = None
        additive = False
        currentSkip = skip = -1
        coords = []
        if "d" in path.attrib:
            coords = path.attrib["d"].split(" ")
            if coords[0] == "M":
                additive = False
                coords = coords[1:]
        elif "points" in path.attrib:
            additive = False
            coords = path.attrib["points"].split(" ")

        activeCommand = ""
        for command in coords:
            try:
                xy = command.split(",")
                x = y = None
                if (activeCommand.upper() == "H"):
                    x = float(xy[0])
                    y = None
                elif (activeCommand.upper() == "V"):
                    y = float(xy[0])
                    x = None
                else:
                    x = float(xy[0])
                    y = float(xy[1])

                if currentSkip < 0 and skip > 0:
                    currentSkip = skip
                if currentSkip > 0:
                    currentSkip -= 1
                    # print "skipping", command, currentSkip, skip
                    continue
                if currentSkip == 0:
                    # print "processing", command
                    currentSkip -= 1

                if not additive or currX is None:
                    currX = (x if x is not None else currX)
                    currY = (y if y is not None else currY)
                else:
                    currX += (x if x is not None else 0)
                    currY += (y if y is not None else 0)

                (transX, transY) = self.Transform(currX, currY)

                if b.minX == None or b.minX > transX:
                    b.minX = transX
                if b.minY == None or b.minY > transY:
                    b.minY = transY
                if b.maxX == None or b.maxX < transX:
                    b.maxX = transX
                if b.maxY == None or b.maxY < transY:
                    b.maxY = transY
            except Exception as e:
                skip = -1
                if command == "z" or command == "Z":
                    continue
                if command.upper() == command:
                    additive = False
                    currX = currY = None
                else:
                    additive = True
                if command == "c" or command == "C":
                    skip = 2
                activeCommand = command

        return b
예제 #24
0
 def test_get_box_config(self):
     bx = Box()
     bx_config = bx.__getattr__("_box_config")
     assert bx_config
     with pytest.raises(BoxKeyError):
         bx["_box_config"]
예제 #25
0
파일: cli.py 프로젝트: jomarquez/squiggle
def visualize(fasta, width, palette, color, hide, bar, title, separate, cols,
              link_x, link_y, output, offline, method, dimensions, skip, mode,
              legend_loc, output_backend, downsample):
    # check filetype
    if fasta is None:
        raise ValueError("Must provide FASTA file.")

    # handle selecting the palette
    palette = small_palettes[palette]

    # handle setting the dimensions automatically if not specified
    if not dimensions:
        dimensions = (750, 500)

    if len(
        [record for _f in fasta for record in Fasta(_f, read_long_names=True)
         ]) > len(palette) and mode != "file":
        if len(fasta) > 1 and mode == "auto":
            if not skip:
                print(
                    "Visualizing each file in separate color. To override, provide mode selection."
                )
            mode = "file"
        else:
            print("Visualizing each sequence in black.")
            color = False
    elif mode == "auto":
        mode = "seq"

    # get all the sequences
    seqs = []
    color_counter = 0
    warned = False
    for i, _f in enumerate(fasta):
        for j, seq in enumerate(
                Fasta(_f, sequence_always_upper=True, read_long_names=True)):
            seqs.append(
                Box(color=palette[color_counter +
                                  1 if color_counter > 2 else 3][color_counter]
                    if color else "black",
                    name=_f if mode == "file" else seq.name,
                    raw_seq=str(seq)))

            # check the length of the seq
            if len(seq
                   ) > 10000 and not skip and not warned and downsample == 1:
                click.confirm(
                    "You are plotting a long sequence ({} bp). This may be very slow, although downsampling might help. "
                    "Do you want to continue?".format(len(seq)),
                    abort=True)
                warned = True

            if mode == "seq":
                color_counter += 1
        if mode == "file":
            color_counter += 1

    # warn if plotting a large number of seqs
    if len(seqs) > 500 and not skip:
        click.confirm(
            "You are plotting a large number of sequences ({}). This may be very slow, although downsampling might help. "
            "Do you want to continue?".format(len(seqs)),
            abort=True)

    # warn if using a bad method
    if max([len(seq.raw_seq)
            for seq in seqs]) > 25 and method in ["qi", "randic"] and not skip:
        click.confirm(
            "This method is not well suited to a sequence of this length. "
            "Do you want to continue?",
            abort=True)

    axis_labels = {
        "squiggle": {
            "x": "position (BP)",
            "y": None
        },
        "gates": {
            "x": "C-G axis",
            "y": "A-T axis"
        },
        "yau": {
            "x": None,
            "y": None
        },
        "yau-bp": {
            "x": "position (BP)",
            "y": None
        },
        "randic": {
            "x": "position (BP)",
            "y": "nucleotide"
        },
        "qi": {
            "x": "position (BP)",
            "y": "dinucleotide"
        }
    }

    # the number of figures to draw is either the number of sequences or files (or 1)
    if separate:
        if mode == "seq":
            fig_count = len(seqs)
        elif mode == "file":
            fig_count = len(fasta)
    else:
        fig_count = 1

    fig = []
    for i in range(fig_count):

        # link the axes, if requested
        if i > 0 and link_x:
            x_range = fig[i - 1].x_range
        else:
            x_range = None
        if i > 0 and link_y:
            y_range = fig[i - 1].y_range
        else:
            y_range = None

        # the y axes for randic and qi are bases
        if method == "randic":
            y_range = ["A", "T", "G", "C"]
        elif method == "qi":
            y_range = [
                'AA', 'AC', 'AG', 'AT', 'CA', 'CC', 'CG', 'CT', 'GA', 'GC',
                'GG', 'GT', 'TA', 'TC', 'TG', 'TT'
            ]

        fig.append(
            figure(x_axis_label=axis_labels[method]["x"],
                   y_axis_label=axis_labels[method]["y"],
                   title=title,
                   x_range=x_range,
                   y_range=y_range,
                   plot_width=dimensions[0],
                   plot_height=dimensions[1],
                   output_backend=output_backend))

    # show a progress bar if processing multiple files
    if len(seqs) > 1 and bar:
        _seqs = tqdm(seqs, unit=" seqs", leave=False)
    else:
        _seqs = seqs

    for i, seq in enumerate(_seqs):
        # perform the actual transformation
        transformed = transform(seq.raw_seq, method=method)
        transformed = (transformed[0][::downsample],
                       transformed[1][::downsample])

        # figure (no pun intended) which figure to plot the data on
        if separate:
            if mode == "seq":
                _fig = fig[i]
            elif mode == "file":
                _fig = fig[fasta.index(seq.name)]

            # add a title to the plot
            _fig.title = annotations.Title()
            if mode == "seq":
                _fig.title.text = seq.name
            elif mode == "file":
                _fig.title.text = click.format_filename(seq.name, shorten=True)
        else:
            _fig = fig[0]
            _fig.title = annotations.Title()

            # if only plotting on one figure, set up the title
            if title:
                _fig.title.text = title
            elif len(seqs) > 1 and not title and len(fasta) == 1:
                _fig.title.text = click.format_filename(fasta[0], shorten=True)
            elif len(seqs) == 1:
                # if just plotting one sequence, title it with the name of the sequence
                _fig.title.text = seq.name

        # randic and qi method's have categorical y axes
        if method == "randic":
            y = list(seq.raw_seq)
        elif method == "qi":
            y = [seq.raw_seq[i:i + 2] for i in range(len(seq.raw_seq))]
            y = [str(i) for i in y if len(i) == 2]
        else:
            y = transformed[1]

        # figure out whether to add a legend
        if (separate or not color or mode == "file"
                or len(seqs) == 1) and not hide:
            legend = None
        else:
            legend = click.format_filename(seq.name, shorten=True)

        # optimization for comparing large FASTA files without hiding
        try:
            if mode == "file" and seqs[i +
                                       1].color != seq.color and not separate:
                legend = click.format_filename(seq.name, shorten=True)
        except IndexError:
            if mode == "file" and not separate:
                legend = click.format_filename(seq.name, shorten=True)

    # do the actual plotting
        _fig.line(x=transformed[0],
                  y=y,
                  line_width=width,
                  legend=legend,
                  color=seq.color)

        # set up the legend
        if legend is not None:
            _fig.legend.location = legend_loc
            if hide:
                _fig.legend.click_policy = "hide"

    # clean up the tqdm bar
    try:
        _seqs.close()
    except AttributeError:
        pass

    # lay out the figure
    if separate:
        plot = gridplot(
            fig,
            ncols=math.ceil(len(fig)**0.5) if cols == 0 else cols,
            toolbar_options=dict(
                logo=None))  # note that 0 denotes the automatic default
    else:
        plot = fig[0]

    if output is not None and output.endswith(".html"):
        output_file(
            output,
            title="Squiggle Visualization" if title is not None else title)
        save(plot, resources=INLINE if offline else None)
    else:
        show(plot)
예제 #26
0
 def test_pop_items(self):
     bx = Box(a=4)
     assert bx.popitem() == ("a", 4)
     with pytest.raises(BoxKeyError):
         assert bx.popitem()
예제 #27
0
    def __init__(self, parent, subtitle, index, enabled=True, first=False):
        self.loading = True
        super(Subtitle, self).__init__(parent)
        self.parent = parent
        self.index = index
        self.outdex = None
        self.subtitle = Box(subtitle, default_box=True)
        self.first = first
        self.last = False
        self.subtitle_lang = subtitle.get("tags", {}).get("language")
        self.subtitle_type = subtitle_types.get(subtitle["codec_name"], "text")
        self.setFixedHeight(60)

        self.widgets = Box(
            track_number=QtWidgets.QLabel(f"{self.index}:{self.outdex}" if enabled else "❌"),
            title=QtWidgets.QLabel(f"  {self.subtitle.codec_long_name}"),
            up_button=QtWidgets.QPushButton(QtGui.QIcon(up_arrow_icon), ""),
            down_button=QtWidgets.QPushButton(QtGui.QIcon(down_arrow_icon), ""),
            enable_check=QtWidgets.QCheckBox(t("Preserve")),
            disposition=QtWidgets.QComboBox(),
            language=QtWidgets.QComboBox(),
            burn_in=QtWidgets.QCheckBox(t("Burn In")),
        )

        self.widgets.up_button.setStyleSheet(no_border)
        self.widgets.down_button.setStyleSheet(no_border)

        self.widgets.disposition.addItems(dispositions)
        self.widgets.enable_check.setChecked(enabled)
        self.widgets.enable_check.toggled.connect(self.update_enable)
        self.widgets.burn_in.toggled.connect(self.update_burn_in)
        self.widgets.disposition.currentIndexChanged.connect(self.page_update)
        self.widgets.disposition.setCurrentIndex(0)
        for disposition, is_set in self.subtitle.disposition.items():
            if is_set:
                try:
                    self.widgets.disposition.setCurrentIndex(dispositions.index(disposition))
                except ValueError:
                    pass
                break

        self.setFixedHeight(60)
        self.widgets.title.setToolTip(self.subtitle.to_yaml())
        self.widgets.burn_in.setToolTip(
            f"""{t("Overlay this subtitle track onto the video during conversion.")}\n
            {t("Please make sure seek method is set to exact")}.\n
            {t("Cannot remove afterwards!")}
            """
        )
        self.widgets.extract = QtWidgets.QPushButton(t("Extract"))
        self.widgets.extract.clicked.connect(self.extract)

        self.gif_label = QtWidgets.QLabel(self)
        self.movie = QtGui.QMovie(loading_movie)
        self.movie.setScaledSize(QtCore.QSize(25, 25))
        self.gif_label.setMovie(self.movie)
        # self.movie.start()

        disposition_layout = QtWidgets.QHBoxLayout()
        disposition_layout.addWidget(QtWidgets.QLabel(t("Disposition")))
        disposition_layout.addWidget(self.widgets.disposition)

        self.grid = QtWidgets.QGridLayout()
        self.grid.addLayout(self.init_move_buttons(), 0, 0)
        self.grid.addWidget(self.widgets.track_number, 0, 1)
        self.grid.addWidget(self.widgets.title, 0, 2)
        self.grid.setColumnStretch(2, True)
        if self.subtitle_type == "text":
            self.grid.addWidget(self.widgets.extract, 0, 3)
            self.grid.addWidget(self.gif_label, 0, 3)
            self.gif_label.hide()

        self.grid.addLayout(disposition_layout, 0, 4)
        self.grid.addWidget(self.widgets.burn_in, 0, 5)
        self.grid.addLayout(self.init_language(), 0, 6)

        self.grid.addWidget(self.widgets.enable_check, 0, 8)

        self.setLayout(self.grid)
        self.loading = False
        self.updating_burn = False
        self.extract_completed_signal.connect(self.extraction_complete)
예제 #28
0
 def test_iter(self):
     bx = Box()
     bx.a = 1
     bx.c = 2
     assert list(bx.__iter__()) == ["a", "c"]
예제 #29
0
    async def clanmembersearch(self, ctx, *args):
        """Search for member.

        usage: [p]crmembersearch [-h] [-t TAG] name

        positional arguments:
          name                  IGN

        optional arguments:
          -h, --help            show this help message and exit
          -c CLAN, --clan CLAN  Clan name
          -n MIN --min MIN      Min Trophies
          -m MAX --max MAX      Max Trophies
          -l --link             Display link to cr-api.com
        """
        parser = self.search_args_parser()
        try:
            pargs = parser.parse_args(args)
        except SystemExit:
            await self.bot.send_cmd_help(ctx)
            return

        await self.bot.type()
        config = self.clans_config
        clan_tags = [clan.tag for clan in config.clans]

        api_error = False
        clans = []
        try:
            clans = await self.get_clans(clan_tags)
            dataIO.save_json(CACHE, clans)
        except json.decoder.JSONDecodeError:
            api_error = True
        except asyncio.TimeoutError:
            api_error = True

        if api_error:
            await self.bot.say("Cannot load clans from API.")
            return

        members = []
        for clan in clans:
            for member in clan.get('members'):
                member = Box(member)
                member.clan = clan
                members.append(member)

        results = []

        if pargs.name != '_':
            for member in members:
                # simple search
                if pargs.name.lower() in member['name'].lower():
                    results.append(member)
                else:
                    # unidecode search
                    s = unidecode.unidecode(member['name'])
                    s = ''.join(re.findall(r'\w', s))
                    if pargs.name.lower() in s.lower():
                        results.append(member)
        else:
            results = members
            print(len(results))

        # filter by clan name
        if pargs.clan:
            results = [
                m for m in results
                if pargs.clan.lower() in m.clan.name.lower()
            ]

        # filter by trophies
        results = [
            m for m in results if pargs.min <= m['trophies'] <= pargs.max
        ]

        limit = 10
        if len(results) > limit:
            await self.bot.say(
                "Found more than {0} results. Returning top {0} only.".format(
                    limit))
            results = results[:limit]

        roles = {
            'leader': 'Leader',
            'coleader': 'Co-Leader',
            'elder': 'Elder',
            'member': 'Member'
        }

        if len(results):
            out = []
            for member_model in results:
                member_model['role_name'] = roles[member_model['role'].lower()]
                out.append(
                    "**{0.name}** #{0.tag}, {0.clan.name}, {0.role_name}, {0.trophies}"
                    .format(member_model))
                if pargs.link:
                    out.append('http://cr-api.com/profile/{}'.format(
                        member_model.tag))
            for page in pagify('\n'.join(out)):
                await self.bot.say(page)
        else:
            await self.bot.say("No results found.")
예제 #30
0
 def test_bad_args(self):
     with pytest.raises(TypeError):
         Box("123", "432")