<commit_before>import asyncio
from typing import List

import discord
from bs4 import BeautifulSoup
from discord.ext import commands
from discord.utils import escape_markdown

from utils import aiohttp_wrap as aw

class Google(commands.Cog):
    SEARCH_URI = "https://duckduckgo.com/html/"
    IMAGE_URI = "https://bing.com/images/"
    IE6_HEADERS = {
        "user-agent": "'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322)"
    }
    HEADERS = {
        "User-Agent": "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) "
        "Chrome/41.0.2228.0 Safari/537.36"
    }
    EMOJIS = [f"{x}\U000020e3" for x in range(1, 10)]

    def __init__(self, bot: commands.Bot):
        self.bot = bot
        self.session = bot.aio_session
        self.redis = bot.redis_client

    @commands.group(
        invoke_without_command=True, name="google", aliases=["g", "ddg", "ask"]
    )
    async def _google(self, ctx, *, query: str = None):
        """ Get search results from [REDACTED], now that Google hates me. """
        if query is None or query.strip() == "":
            return await ctx.error("Feel free to search something")

        resp = await aw.aio_get_text(
            self.session, self.SEARCH_URI, headers=self.HEADERS, params={"q": query}
        )

        soup = BeautifulSoup(resp, "lxml")
        links = [x["href"] for x in soup.find_all("a", {"class": "result__a"})]
        if len(links) == 0:
            return await ctx.error(
                f"Sorry, couldn't find anything for `{escape_markdown(query)}`"
            )

        await ctx.send(
            f"**Top Result:**\n{links[0]}\n**See Also:**\n1. <{links[1]}>\n2. <{links[2]}>"
        )

    @staticmethod
    def link_to_embed(query: str, link: str) -> discord.Embed:
        em = discord.Embed(title=query)
        em.set_image(url=link)
        return em

    @_google.command(name="-image", aliases=["-i", "-images"])
    async def images(self, ctx: commands.Context, *, query: str = None):
        """Search for images"""
        if query is None or query.strip() == "":
            return await ctx.error("Feel free to search for something")

        resp = await aw.aio_get_text(
            self.session, self.IMAGE_URI, headers=self.IE6_HEADERS, params={"q": query}
        )
        soup = BeautifulSoup(resp, "lxml")
        embeds = [
            self.link_to_embed(query, x["href"])
            for x in soup.find_all("a", {"class": "thumb"})[:5]
        ]

        msg = await ctx.send(embed=embeds[0])

        for x in self.EMOJIS[: len(embeds)]:
            await msg.add_reaction(x)

        while True:
            try:
                reaction, _ = await self.bot.wait_for(
                    "reaction_add",
                    check=lambda reaction, user: (
                        user == ctx.author
                        and reaction.emoji in self.EMOJIS
                        and reaction.message.id == msg.id
                    ),
                )
            except asyncio.TimeoutError:
                return await msg.clear_reactions()

            if reaction.emoji in self.EMOJIS:
                await msg.edit_message(embed=embeds[self.EMOJIS.index(reaction.emoji)])

def setup(bot):
    bot.add_cog(Google(bot))
<commit_msg>Fix malformed user-agent<commit_after>import asyncio
from typing import List

import discord
from bs4 import BeautifulSoup
from discord.ext import commands
from discord.utils import escape_markdown

from utils import aiohttp_wrap as aw

class Google(commands.Cog):
    SEARCH_URI = "https://duckduckgo.com/html/"
    IMAGE_URI = "https://bing.com/images/"
    IE6_HEADERS = {
        "user-agent": "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322)"
    }
    HEADERS = {
        "User-Agent": "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) "
        "Chrome/41.0.2228.0 Safari/537.36"
    }
    EMOJIS = [f"{x}\U000020e3" for x in range(1, 10)]

    def __init__(self, bot: commands.Bot):
        self.bot = bot
        self.session = bot.aio_session
        self.redis = bot.redis_client

    @commands.group(
        invoke_without_command=True, name="google", aliases=["g", "ddg", "ask"]
    )
    async def _google(self, ctx, *, query: str = None):
        """ Get search results from [REDACTED], now that Google hates me. """
        if query is None or query.strip() == "":
            return await ctx.error("Feel free to search something")

        resp = await aw.aio_get_text(
            self.session, self.SEARCH_URI, headers=self.HEADERS, params={"q": query}
        )

        soup = BeautifulSoup(resp, "lxml")
        links = [x["href"] for x in soup.find_all("a", {"class": "result__a"})]
        if len(links) == 0:
            return await ctx.error(
                f"Sorry, couldn't find anything for `{escape_markdown(query)}`"
            )

        await ctx.send(
            f"**Top Result:**\n{links[0]}\n**See Also:**\n1. <{links[1]}>\n2. <{links[2]}>"
        )

    @staticmethod
    def link_to_embed(query: str, link: str) -> discord.Embed:
        em = discord.Embed(title=query)
        em.set_image(url=link)
        return em

    @_google.command(name="-image", aliases=["-i", "-images"])
    async def images(self, ctx: commands.Context, *, query: str = None):
        """Search for images"""
        if query is None or query.strip() == "":
            return await ctx.error("Feel free to search for something")

        resp = await aw.aio_get_text(
            self.session, self.IMAGE_URI, headers=self.IE6_HEADERS, params={"q": query}
        )
        soup = BeautifulSoup(resp, "lxml")
        embeds = [
            self.link_to_embed(query, x["href"])
            for x in soup.find_all("a", {"class": "thumb"})[:5]
        ]

        msg = await ctx.send(embed=embeds[0])

        for x in self.EMOJIS[: len(embeds)]:
            await msg.add_reaction(x)

        while True:
            try:
                reaction, _ = await self.bot.wait_for(
                    "reaction_add",
                    check=lambda reaction, user: (
                        user == ctx.author
                        and reaction.emoji in self.EMOJIS
                        and reaction.message.id == msg.id
                    ),
                )
            except asyncio.TimeoutError:
                return await msg.clear_reactions()

            if reaction.emoji in self.EMOJIS:
                await msg.edit_message(embed=embeds[self.EMOJIS.index(reaction.emoji)])

def setup(bot):
    bot.add_cog(Google(bot))
<|endoftext|>


<commit_before># Copyright 2013-2016 The Meson development team

# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at

#     http://www.apache.org/licenses/LICENSE-2.0

# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# This script extracts the symbols of a given shared library
# into a file. If the symbols have not changed, the file is not
# touched. This information is used to skip link steps if the
# ABI has not changed.

# This file is basically a reimplementation of
# http://cgit.freedesktop.org/libreoffice/core/commit/?id=3213cd54b76bc80a6f0516aac75a48ff3b2ad67c

import typing as T
import os, sys
from .. import mesonlib
from .. import mlog
from ..mesonlib import Popen_safe
import argparse

parser = argparse.ArgumentParser()

parser.add_argument('--cross-host', default=None, dest='cross_host',
                    help='cross compilation host platform')
parser.add_argument('args', nargs='+')

TOOL_WARNING_FILE = None
RELINKING_WARNING = 'Relinking will always happen on source changes.'

def dummy_syms(outfilename: str):
    """Just touch it so relinking happens always."""
    with open(outfilename, 'w'):
        pass

def write_if_changed(text: str, outfilename: str):
    try:
        with open(outfilename, 'r') as f:
            oldtext = f.read()
        if text == oldtext:
            return
    except FileNotFoundError:
        pass
    with open(outfilename, 'w') as f:
        f.write(text)

def print_tool_warning(tool: list, msg: str, stderr: str = None):
    global TOOL_WARNING_FILE
    if os.path.exists(TOOL_WARNING_FILE):
        return
    if len(tool) == 1:
        tool = tool[0]
    m = '{!r} {}. {}'.format(tool, msg, RELINKING_WARNING)
    if stderr:
        m += '\n' + stderr
    mlog.warning(m)
    # Write it out so we don't warn again
    with open(TOOL_WARNING_FILE, 'w'):
        pass

def get_tool(name: str) -> T.List[str]:
    evar = name.upper()
    if evar in os.environ:
        import shlex
        return shlex.split(os.environ[evar])
    return [name]

def call_tool(name: str, args: T.List[str], **kwargs) -> str:
    tool = get_tool(name)
    try:
        p, output, e = Popen_safe(tool + args, **kwargs)
    except FileNotFoundError:
        print_tool_warning(tool, 'not found')
        return None
    if p.returncode != 0:
        print_tool_warning(tool, 'does not work', e)
        return None
    return output

def call_tool_nowarn(tool: T.List[str], **kwargs) -> T.Tuple[str, str]:
    try:
        p, output, e = Popen_safe(tool, **kwargs)
    except FileNotFoundError:
        return None, '{!r} not found\n'.format(tool[0])
    if p.returncode != 0:
        return None, e
    return output, None

def gnu_syms(libfilename: str, outfilename: str):
    # Get the name of the library
    output = call_tool('readelf', ['-d', libfilename])
    if not output:
        dummy_syms(outfilename)
        return
    result = [x for x in output.split('\n') if 'SONAME' in x]
    assert(len(result) <= 1)
    # Get a list of all symbols exported
    output = call_tool('nm', ['--dynamic', '--extern-only', '--defined-only',
                              '--format=posix', libfilename])
    if not output:
        dummy_syms(outfilename)
        return
    for line in output.split('\n'):
        if not line:
            continue
        line_split = line.split()
        entry = line_split[0:2]
        # Store the size of symbols pointing to data objects so we relink
        # when those change, which is needed because of copy relocations
        # https://github.com/mesonbuild/meson/pull/7132#issuecomment-628353702
        if line_split[1].upper() in ('B', 'G', 'D') and len(line_split) >= 4:
            entry += [line_split[3]]
        result += [' '.join(entry)]
    write_if_changed('\n'.join(result) + '\n', outfilename)

def solaris_syms(libfilename: str, outfilename: str):
    # gnu_syms() works with GNU nm & readelf, not Solaris nm & elfdump
    origpath = os.environ['PATH']
    try:
        os.environ['PATH'] = '/usr/gnu/bin:' + origpath
        gnu_syms(libfilename, outfilename)
    finally:
        os.environ['PATH'] = origpath

def osx_syms(libfilename: str, outfilename: str):
    # Get the name of the library
    output = call_tool('otool', ['-l', libfilename])
    if not output:
        dummy_syms(outfilename)
        return
    arr = output.split('\n')
    for (i, val) in enumerate(arr):
        if 'LC_ID_DYLIB' in val:
            match = i
            break
    result = [arr[match + 2], arr[match + 5]] # Libreoffice stores all 5 lines but the others seem irrelevant.
    # Get a list of all symbols exported
    output = call_tool('nm', ['--extern-only', '--defined-only',
                              '--format=posix', libfilename])
    if not output:
        dummy_syms(outfilename)
        return
    result += [' '.join(x.split()[0:2]) for x in output.split('\n')]
    write_if_changed('\n'.join(result) + '\n', outfilename)

def openbsd_syms(libfilename: str, outfilename: str):
    # Get the name of the library
    output = call_tool('readelf', ['-d', libfilename])
    if not output:
        dummy_syms(outfilename)
        return
    result = [x for x in output.split('\n') if 'SONAME' in x]
    assert(len(result) <= 1)
    # Get a list of all symbols exported
    output = call_tool('nm', ['-D', '-P', '-g', libfilename])
    if not output:
        dummy_syms(outfilename)
        return
    # U = undefined (cope with the lack of --defined-only option)
    result += [' '.join(x.split()[0:2]) for x in output.split('\n') if x and not x.endswith('U ')]
    write_if_changed('\n'.join(result) + '\n', outfilename)

def cygwin_syms(impfilename: str, outfilename: str):
    # Get the name of the library
    output = call_tool('dlltool', ['-I', impfilename])
    if not output:
        dummy_syms(outfilename)
        return
    result = [output]
    # Get the list of all symbols exported
    output = call_tool('nm', ['--extern-only', '--defined-only',
                              '--format=posix', impfilename])
    if not output:
        dummy_syms(outfilename)
        return
    for line in output.split('\n'):
        if ' T ' not in line:
            continue
        result.append(line.split(maxsplit=1)[0])
    write_if_changed('\n'.join(result) + '\n', outfilename)

def _get_implib_dllname(impfilename: str) -> T.Tuple[T.List[str], str]:
    all_stderr = ''
    # First try lib.exe, which is provided by MSVC. Then llvm-lib.exe, by LLVM
    # for clang-cl.
    #
    # We cannot call get_tool on `lib` because it will look at the `LIB` env
    # var which is the list of library paths MSVC will search for import
    # libraries while linking.
    for lib in (['lib'], get_tool('llvm-lib')):
        output, e = call_tool_nowarn(lib + ['-list', impfilename])
        if output:
            # The output is a list of DLLs that each symbol exported by the import
            # library is available in. We only build import libraries that point to
            # a single DLL, so we can pick any of these. Pick the last one for
            # simplicity. Also skip the last line, which is empty.
            return output.split('\n')[-2:-1], None
        all_stderr += e
    # Next, try dlltool.exe which is provided by MinGW
    output, e = call_tool_nowarn(get_tool('dlltool') + ['-I', impfilename])
    if output:
        return [output], None
    all_stderr += e
    return ([], all_stderr)

def _get_implib_exports(impfilename: str) -> T.Tuple[T.List[str], str]:
    all_stderr = ''
    # Force dumpbin.exe to use en-US so we can parse its output
    env = os.environ.copy()
    env['VSLANG'] = '1033'
    output, e = call_tool_nowarn(get_tool('dumpbin') + ['-exports', impfilename], env=env)
    if output:
        lines = output.split('\n')
        start = lines.index('File Type: LIBRARY')
        end = lines.index('  Summary')
        return lines[start:end], None
    all_stderr += e
    # Next, try llvm-nm.exe provided by LLVM, then nm.exe provided by MinGW
    for nm in ('llvm-nm', 'nm'):
        output, e = call_tool_nowarn(get_tool(nm) + ['--extern-only', '--defined-only',
                                                     '--format=posix', impfilename])
        if output:
            result = []
            for line in output.split('\n'):
                if ' T ' not in line or line.startswith('.text'):
                    continue
                result.append(line.split(maxsplit=1)[0])
            return result, None
        all_stderr += e
    return ([], all_stderr)

def windows_syms(impfilename: str, outfilename: str):
    # Get the name of the library
    result, e = _get_implib_dllname(impfilename)
    if not result:
        print_tool_warning('lib, llvm-lib, dlltool', 'do not work or were not found', e)
        dummy_syms(outfilename)
        return
    # Get a list of all symbols exported
    symbols, e = _get_implib_exports(impfilename)
    if not symbols:
        print_tool_warning('dumpbin, llvm-nm, nm', 'do not work or were not found', e)
        dummy_syms(outfilename)
        return
    result += symbols
    write_if_changed('\n'.join(result) + '\n', outfilename)

def gen_symbols(libfilename: str, impfilename: str, outfilename: str, cross_host: str):
    if cross_host is not None:
        # In case of cross builds just always relink. In theory we could
        # determine the correct toolset, but we would need to use the correct
        # `nm`, `readelf`, etc, from the cross info which requires refactoring.
        dummy_syms(outfilename)
    elif mesonlib.is_linux() or mesonlib.is_hurd():
        gnu_syms(libfilename, outfilename)
    elif mesonlib.is_osx():
        osx_syms(libfilename, outfilename)
    elif mesonlib.is_openbsd():
        openbsd_syms(libfilename, outfilename)
    elif mesonlib.is_windows():
        if os.path.isfile(impfilename):
            windows_syms(impfilename, outfilename)
        else:
            # No import library. Not sure how the DLL is being used, so just
            # rebuild everything that links to it every time.
            dummy_syms(outfilename)
    elif mesonlib.is_cygwin():
        if os.path.isfile(impfilename):
            cygwin_syms(impfilename, outfilename)
        else:
            # No import library. Not sure how the DLL is being used, so just
            # rebuild everything that links to it every time.
            dummy_syms(outfilename)
    elif mesonlib.is_sunos():
        solaris_syms(libfilename, outfilename)
    else:
        if not os.path.exists(TOOL_WARNING_FILE):
            mlog.warning('Symbol extracting has not been implemented for this '
                         'platform. ' + RELINKING_WARNING)
            # Write it out so we don't warn again
            with open(TOOL_WARNING_FILE, 'w'):
                pass
        dummy_syms(outfilename)

def run(args):
    global TOOL_WARNING_FILE
    options = parser.parse_args(args)
    if len(options.args) != 4:
        print('symbolextractor.py <shared library file> <import library> <output file>')
        sys.exit(1)
    privdir = os.path.join(options.args[0], 'meson-private')
    TOOL_WARNING_FILE = os.path.join(privdir, 'symbolextractor_tool_warning_printed')
    libfile = options.args[1]
    impfile = options.args[2] # Only used on Windows
    outfile = options.args[3]
    gen_symbols(libfile, impfile, outfile, options.cross_host)
    return 0

if __name__ == '__main__':
    sys.exit(run(sys.argv[1:]))
<commit_msg>symbolextractor: Handle PermissionError when running tool<commit_after># Copyright 2013-2016 The Meson development team

# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at

#     http://www.apache.org/licenses/LICENSE-2.0

# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# This script extracts the symbols of a given shared library
# into a file. If the symbols have not changed, the file is not
# touched. This information is used to skip link steps if the
# ABI has not changed.

# This file is basically a reimplementation of
# http://cgit.freedesktop.org/libreoffice/core/commit/?id=3213cd54b76bc80a6f0516aac75a48ff3b2ad67c

import typing as T
import os, sys
from .. import mesonlib
from .. import mlog
from ..mesonlib import Popen_safe
import argparse

parser = argparse.ArgumentParser()

parser.add_argument('--cross-host', default=None, dest='cross_host',
                    help='cross compilation host platform')
parser.add_argument('args', nargs='+')

TOOL_WARNING_FILE = None
RELINKING_WARNING = 'Relinking will always happen on source changes.'

def dummy_syms(outfilename: str):
    """Just touch it so relinking happens always."""
    with open(outfilename, 'w'):
        pass

def write_if_changed(text: str, outfilename: str):
    try:
        with open(outfilename, 'r') as f:
            oldtext = f.read()
        if text == oldtext:
            return
    except FileNotFoundError:
        pass
    with open(outfilename, 'w') as f:
        f.write(text)

def print_tool_warning(tool: list, msg: str, stderr: str = None):
    global TOOL_WARNING_FILE
    if os.path.exists(TOOL_WARNING_FILE):
        return
    if len(tool) == 1:
        tool = tool[0]
    m = '{!r} {}. {}'.format(tool, msg, RELINKING_WARNING)
    if stderr:
        m += '\n' + stderr
    mlog.warning(m)
    # Write it out so we don't warn again
    with open(TOOL_WARNING_FILE, 'w'):
        pass

def get_tool(name: str) -> T.List[str]:
    evar = name.upper()
    if evar in os.environ:
        import shlex
        return shlex.split(os.environ[evar])
    return [name]

def call_tool(name: str, args: T.List[str], **kwargs) -> str:
    tool = get_tool(name)
    try:
        p, output, e = Popen_safe(tool + args, **kwargs)
    except FileNotFoundError:
        print_tool_warning(tool, 'not found')
        return None
    except PermissionError:
        print_tool_warning(tool, 'not usable')
        return None
    if p.returncode != 0:
        print_tool_warning(tool, 'does not work', e)
        return None
    return output

def call_tool_nowarn(tool: T.List[str], **kwargs) -> T.Tuple[str, str]:
    try:
        p, output, e = Popen_safe(tool, **kwargs)
    except FileNotFoundError:
        return None, '{!r} not found\n'.format(tool[0])
    except PermissionError:
        return None, '{!r} not usable\n'.format(tool[0])
    if p.returncode != 0:
        return None, e
    return output, None

def gnu_syms(libfilename: str, outfilename: str):
    # Get the name of the library
    output = call_tool('readelf', ['-d', libfilename])
    if not output:
        dummy_syms(outfilename)
        return
    result = [x for x in output.split('\n') if 'SONAME' in x]
    assert(len(result) <= 1)
    # Get a list of all symbols exported
    output = call_tool('nm', ['--dynamic', '--extern-only', '--defined-only',
                              '--format=posix', libfilename])
    if not output:
        dummy_syms(outfilename)
        return
    for line in output.split('\n'):
        if not line:
            continue
        line_split = line.split()
        entry = line_split[0:2]
        # Store the size of symbols pointing to data objects so we relink
        # when those change, which is needed because of copy relocations
        # https://github.com/mesonbuild/meson/pull/7132#issuecomment-628353702
        if line_split[1].upper() in ('B', 'G', 'D') and len(line_split) >= 4:
            entry += [line_split[3]]
        result += [' '.join(entry)]
    write_if_changed('\n'.join(result) + '\n', outfilename)

def solaris_syms(libfilename: str, outfilename: str):
    # gnu_syms() works with GNU nm & readelf, not Solaris nm & elfdump
    origpath = os.environ['PATH']
    try:
        os.environ['PATH'] = '/usr/gnu/bin:' + origpath
        gnu_syms(libfilename, outfilename)
    finally:
        os.environ['PATH'] = origpath

def osx_syms(libfilename: str, outfilename: str):
    # Get the name of the library
    output = call_tool('otool', ['-l', libfilename])
    if not output:
        dummy_syms(outfilename)
        return
    arr = output.split('\n')
    for (i, val) in enumerate(arr):
        if 'LC_ID_DYLIB' in val:
            match = i
            break
    result = [arr[match + 2], arr[match + 5]] # Libreoffice stores all 5 lines but the others seem irrelevant.
    # Get a list of all symbols exported
    output = call_tool('nm', ['--extern-only', '--defined-only',
                              '--format=posix', libfilename])
    if not output:
        dummy_syms(outfilename)
        return
    result += [' '.join(x.split()[0:2]) for x in output.split('\n')]
    write_if_changed('\n'.join(result) + '\n', outfilename)

def openbsd_syms(libfilename: str, outfilename: str):
    # Get the name of the library
    output = call_tool('readelf', ['-d', libfilename])
    if not output:
        dummy_syms(outfilename)
        return
    result = [x for x in output.split('\n') if 'SONAME' in x]
    assert(len(result) <= 1)
    # Get a list of all symbols exported
    output = call_tool('nm', ['-D', '-P', '-g', libfilename])
    if not output:
        dummy_syms(outfilename)
        return
    # U = undefined (cope with the lack of --defined-only option)
    result += [' '.join(x.split()[0:2]) for x in output.split('\n') if x and not x.endswith('U ')]
    write_if_changed('\n'.join(result) + '\n', outfilename)

def cygwin_syms(impfilename: str, outfilename: str):
    # Get the name of the library
    output = call_tool('dlltool', ['-I', impfilename])
    if not output:
        dummy_syms(outfilename)
        return
    result = [output]
    # Get the list of all symbols exported
    output = call_tool('nm', ['--extern-only', '--defined-only',
                              '--format=posix', impfilename])
    if not output:
        dummy_syms(outfilename)
        return
    for line in output.split('\n'):
        if ' T ' not in line:
            continue
        result.append(line.split(maxsplit=1)[0])
    write_if_changed('\n'.join(result) + '\n', outfilename)

def _get_implib_dllname(impfilename: str) -> T.Tuple[T.List[str], str]:
    all_stderr = ''
    # First try lib.exe, which is provided by MSVC. Then llvm-lib.exe, by LLVM
    # for clang-cl.
    #
    # We cannot call get_tool on `lib` because it will look at the `LIB` env
    # var which is the list of library paths MSVC will search for import
    # libraries while linking.
    for lib in (['lib'], get_tool('llvm-lib')):
        output, e = call_tool_nowarn(lib + ['-list', impfilename])
        if output:
            # The output is a list of DLLs that each symbol exported by the import
            # library is available in. We only build import libraries that point to
            # a single DLL, so we can pick any of these. Pick the last one for
            # simplicity. Also skip the last line, which is empty.
            return output.split('\n')[-2:-1], None
        all_stderr += e
    # Next, try dlltool.exe which is provided by MinGW
    output, e = call_tool_nowarn(get_tool('dlltool') + ['-I', impfilename])
    if output:
        return [output], None
    all_stderr += e
    return ([], all_stderr)

def _get_implib_exports(impfilename: str) -> T.Tuple[T.List[str], str]:
    all_stderr = ''
    # Force dumpbin.exe to use en-US so we can parse its output
    env = os.environ.copy()
    env['VSLANG'] = '1033'
    output, e = call_tool_nowarn(get_tool('dumpbin') + ['-exports', impfilename], env=env)
    if output:
        lines = output.split('\n')
        start = lines.index('File Type: LIBRARY')
        end = lines.index('  Summary')
        return lines[start:end], None
    all_stderr += e
    # Next, try llvm-nm.exe provided by LLVM, then nm.exe provided by MinGW
    for nm in ('llvm-nm', 'nm'):
        output, e = call_tool_nowarn(get_tool(nm) + ['--extern-only', '--defined-only',
                                                     '--format=posix', impfilename])
        if output:
            result = []
            for line in output.split('\n'):
                if ' T ' not in line or line.startswith('.text'):
                    continue
                result.append(line.split(maxsplit=1)[0])
            return result, None
        all_stderr += e
    return ([], all_stderr)

def windows_syms(impfilename: str, outfilename: str):
    # Get the name of the library
    result, e = _get_implib_dllname(impfilename)
    if not result:
        print_tool_warning('lib, llvm-lib, dlltool', 'do not work or were not found', e)
        dummy_syms(outfilename)
        return
    # Get a list of all symbols exported
    symbols, e = _get_implib_exports(impfilename)
    if not symbols:
        print_tool_warning('dumpbin, llvm-nm, nm', 'do not work or were not found', e)
        dummy_syms(outfilename)
        return
    result += symbols
    write_if_changed('\n'.join(result) + '\n', outfilename)

def gen_symbols(libfilename: str, impfilename: str, outfilename: str, cross_host: str):
    if cross_host is not None:
        # In case of cross builds just always relink. In theory we could
        # determine the correct toolset, but we would need to use the correct
        # `nm`, `readelf`, etc, from the cross info which requires refactoring.
        dummy_syms(outfilename)
    elif mesonlib.is_linux() or mesonlib.is_hurd():
        gnu_syms(libfilename, outfilename)
    elif mesonlib.is_osx():
        osx_syms(libfilename, outfilename)
    elif mesonlib.is_openbsd():
        openbsd_syms(libfilename, outfilename)
    elif mesonlib.is_windows():
        if os.path.isfile(impfilename):
            windows_syms(impfilename, outfilename)
        else:
            # No import library. Not sure how the DLL is being used, so just
            # rebuild everything that links to it every time.
            dummy_syms(outfilename)
    elif mesonlib.is_cygwin():
        if os.path.isfile(impfilename):
            cygwin_syms(impfilename, outfilename)
        else:
            # No import library. Not sure how the DLL is being used, so just
            # rebuild everything that links to it every time.
            dummy_syms(outfilename)
    elif mesonlib.is_sunos():
        solaris_syms(libfilename, outfilename)
    else:
        if not os.path.exists(TOOL_WARNING_FILE):
            mlog.warning('Symbol extracting has not been implemented for this '
                         'platform. ' + RELINKING_WARNING)
            # Write it out so we don't warn again
            with open(TOOL_WARNING_FILE, 'w'):
                pass
        dummy_syms(outfilename)

def run(args):
    global TOOL_WARNING_FILE
    options = parser.parse_args(args)
    if len(options.args) != 4:
        print('symbolextractor.py <shared library file> <import library> <output file>')
        sys.exit(1)
    privdir = os.path.join(options.args[0], 'meson-private')
    TOOL_WARNING_FILE = os.path.join(privdir, 'symbolextractor_tool_warning_printed')
    libfile = options.args[1]
    impfile = options.args[2] # Only used on Windows
    outfile = options.args[3]
    gen_symbols(libfile, impfile, outfile, options.cross_host)
    return 0

if __name__ == '__main__':
    sys.exit(run(sys.argv[1:]))
<|endoftext|>


<commit_before>from nose.tools import *
from io import StringIO
from textwrap import dedent

from metaconfig import Config

# construct_from_mapping
# construct_from_sequence
# construct_from_string
# construct_from_integer
# construct_from_any
# construct_from_none
# construct_from_args_kwargs

def test_construct_from_mapping():

    source = """
    --- !declare
    func:
        type: !resolve metaconfig.tests.utils.identity
        load: !resolve metaconfig.construct_from_mapping
    ...

    --- !let
    value: !func
        a: 1
        b: 2
    ...
    """

    config = Config()

    with StringIO(dedent(source)) as stream:
        config.load(stream)

    value = config.get("value")

    assert_tuple_equal(value[0], ())
    assert_dict_equal(value[1], {"a": 1, "b": 2})<commit_msg>test construct from sequence<commit_after>from nose.tools import *
from io import StringIO
from textwrap import dedent

from metaconfig import Config

# construct_from_string
# construct_from_integer
# construct_from_any
# construct_from_none
# construct_from_args_kwargs

def test_construct_from_mapping():

    source = """
    --- !declare
    func:
        type: !resolve metaconfig.tests.utils.identity
        load: !resolve metaconfig.construct_from_mapping
    ...

    --- !let
    value: !func
        a: 1
        b: 2
    ...
    """

    config = Config()

    with StringIO(dedent(source)) as stream:
        config.load(stream)

    value = config.get("value")

    assert_tuple_equal(value[0], ())
    assert_dict_equal(value[1], {"a": 1, "b": 2})

def test_construct_from_sequence():

    source = """
    --- !declare
    func:
        type: !resolve metaconfig.tests.utils.identity
        load: !resolve metaconfig.construct_from_sequence
    ...

    --- !let
    value: !func
        - 1
        - 2
    ...
    """

    config = Config()

    with StringIO(dedent(source)) as stream:
        config.load(stream)

    value = config.get("value")

    assert_tuple_equal(value[0], (1, 2))
    assert_dict_equal(value[1], {})
<|endoftext|>


<commit_before>#!/usr/bin/env python
# -*- coding: utf-8 -*-

import wiringPy
import time

# screen size in pixel
HEIGHT = WIDTH = 84

# default PINs, BCM GPIO
pin_CLK   = 24
pin_DIN   = 23
pin_DC    = 22
pin_RST   = 18
pin_LIGHT = 17
pin_CE    = 4

# useful constants
ON,   OFF = [1, 0]
HIGH, LOW = [1, 0]

# contrast
default_contrast = 0xB0

# FONT
default_FONT = {
    ' ': [0x00, 0x00, 0x00, 0x00, 0x00],
    '!': [0x00, 0x00, 0x5f, 0x00, 0x00],
    '"': [0x00, 0x07, 0x00, 0x07, 0x00],
    '#': [0x14, 0x7f, 0x14, 0x7f, 0x14],
    '$': [0x24, 0x2a, 0x7f, 0x2a, 0x12],
    '%': [0x23, 0x13, 0x08, 0x64, 0x62],
    '&': [0x36, 0x49, 0x55, 0x22, 0x50],
    "'": [0x00, 0x05, 0x03, 0x00, 0x00],
    '(': [0x00, 0x1c, 0x22, 0x41, 0x00],
    ')': [0x00, 0x41, 0x22, 0x1c, 0x00],
    '*': [0x14, 0x08, 0x3e, 0x08, 0x14],
    '+': [0x08, 0x08, 0x3e, 0x08, 0x08],
    ',': [0x00, 0x50, 0x30, 0x00, 0x00],
    '-': [0x08, 0x08, 0x08, 0x08, 0x08],
    '.': [0x00, 0x60, 0x60, 0x00, 0x00],
    '/': [0x20, 0x10, 0x08, 0x04, 0x02],
    '0': [0x3e, 0x51, 0x49, 0x45, 0x3e],
    '1': [0x00, 0x42, 0x7f, 0x40, 0x00],
    '2': [0x42, 0x61, 0x51, 0x49, 0x46],
    '3': [0x21, 0x41, 0x45, 0x4b, 0x31],
    '4': [0x18, 0x14, 0x12, 0x7f, 0x10],
    '5': [0x27, 0x45, 0x45, 0x45, 0x39],
    '6': [0x3c, 0x4a, 0x49, 0x49, 0x30],
    '7': [0x01, 0x71, 0x09, 0x05, 0x03],
    '8': [0x36, 0x49, 0x49, 0x49, 0x36],
    '9': [0x06, 0x49, 0x49, 0x29, 0x1e],
    ':': [0x00, 0x36, 0x36, 0x00, 0x00],
    ';': [0x00, 0x56, 0x36, 0x00, 0x00],
    '<': [0x08, 0x14, 0x22, 0x41, 0x00],
    '=': [0x14, 0x14, 0x14, 0x14, 0x14],
    '>': [0x00, 0x41, 0x22, 0x14, 0x08],
    '?': [0x02, 0x01, 0x51, 0x09, 0x06],
    '@': [0x32, 0x49, 0x79, 0x41, 0x3e],
    'A': [0x7e, 0x11, 0x11, 0x11, 0x7e],
    'B': [0x7f, 0x49, 0x49, 0x49, 0x36],
    'C': [0x3e, 0x41, 0x41, 0x41, 0x22],
    'D': [0x7f, 0x41, 0x41, 0x22, 0x1c],
    'E': [0x7f, 0x49, 0x49, 0x49, 0x41],
    'F': [0x7f, 0x09, 0x09, 0x09, 0x01],
    'G': [0x3e, 0x41, 0x49, 0x49, 0x7a],
    'H': [0x7f, 0x08, 0x08, 0x08, 0x7f],
    'I': [0x00, 0x41, 0x7f, 0x41, 0x00],
    'J': [0x20, 0x40, 0x41, 0x3f, 0x01],
    'K': [0x7f, 0x08, 0x14, 0x22, 0x41],
    'L': [0x7f, 0x40, 0x40, 0x40, 0x40],
    'M': [0x7f, 0x02, 0x0c, 0x02, 0x7f],
    'N': [0x7f, 0x04, 0x08, 0x10, 0x7f],
    'O': [0x3e, 0x41, 0x41, 0x41, 0x3e],
    'P': [0x7f, 0x09, 0x09, 0x09, 0x06],
    'Q': [0x3e, 0x41, 0x51, 0x21, 0x5e],
    'R': [0x7f, 0x09, 0x19, 0x29, 0x46],
    'S': [0x46, 0x49, 0x49, 0x49, 0x31],
    'T': [0x01, 0x01, 0x7f, 0x01, 0x01],
    'U': [0x3f, 0x40, 0x40, 0x40, 0x3f],
    'V': [0x1f, 0x20, 0x40, 0x20, 0x1f],
    'W': [0x3f, 0x40, 0x38, 0x40, 0x3f],
    'X': [0x63, 0x14, 0x08, 0x14, 0x63],
    'Y': [0x07, 0x08, 0x70, 0x08, 0x07],
    'Z': [0x61, 0x51, 0x49, 0x45, 0x43],
    '[': [0x00, 0x7f, 0x41, 0x41, 0x00],
    '\\': [0x02, 0x04, 0x08, 0x10, 0x20],
    ']': [0x00, 0x41, 0x41, 0x7f, 0x00],
    '^': [0x04, 0x02, 0x01, 0x02, 0x04],
    '_': [0x40, 0x40, 0x40, 0x40, 0x40],
    '`': [0x00, 0x01, 0x02, 0x04, 0x00],
    'a': [0x20, 0x54, 0x54, 0x54, 0x78],
    'b': [0x7f, 0x48, 0x44, 0x44, 0x38],
    'c': [0x38, 0x44, 0x44, 0x44, 0x20],
    'd': [0x38, 0x44, 0x44, 0x48, 0x7f],
    'e': [0x38, 0x54, 0x54, 0x54, 0x18],
    'f': [0x08, 0x7e, 0x09, 0x01, 0x02],
    'g': [0x0c, 0x52, 0x52, 0x52, 0x3e],
    'h': [0x7f, 0x08, 0x04, 0x04, 0x78],
    'i': [0x00, 0x44, 0x7d, 0x40, 0x00],
    'j': [0x20, 0x40, 0x44, 0x3d, 0x00],
    'k': [0x7f, 0x10, 0x28, 0x44, 0x00],
    'l': [0x00, 0x41, 0x7f, 0x40, 0x00],
    'm': [0x7c, 0x04, 0x18, 0x04, 0x78],
    'n': [0x7c, 0x08, 0x04, 0x04, 0x78],
    'o': [0x38, 0x44, 0x44, 0x44, 0x38],
    'p': [0x7c, 0x14, 0x14, 0x14, 0x08],
    'q': [0x08, 0x14, 0x14, 0x18, 0x7c],
    'r': [0x7c, 0x08, 0x04, 0x04, 0x08],
    's': [0x48, 0x54, 0x54, 0x54, 0x20],
    't': [0x04, 0x3f, 0x44, 0x40, 0x20],
    'u': [0x3c, 0x40, 0x40, 0x20, 0x7c],
    'v': [0x1c, 0x20, 0x40, 0x20, 0x1c],
    'w': [0x3c, 0x40, 0x30, 0x40, 0x3c],
    'x': [0x44, 0x28, 0x10, 0x28, 0x44],
    'y': [0x0c, 0x50, 0x50, 0x50, 0x3c],
    'z': [0x44, 0x64, 0x54, 0x4c, 0x44],
    '{': [0x00, 0x08, 0x36, 0x41, 0x00],
    '|': [0x00, 0x00, 0x7f, 0x00, 0x00],
    '}': [0x00, 0x41, 0x36, 0x08, 0x00],
    '~': [0x10, 0x08, 0x08, 0x10, 0x08],
}

def init(CLK = 24, DIN = 23, DC = 22, RST = 18, LIGHT = 17, CE = 4, contrast = default_contrast):
    """ init screen, trun off backlight, clearscreen """
    wiringPy.setup_gpio()
    pins = [CLK, DIN, DC, RST, LIGHT]
    pin_CLK, pin_DIN, pin_DC, pin_RST, pin_LIGHT, pin_CE = pins
    map(lambda p: wiringPy.pin_mode(p, ON), pins)

    # Reset the device
    wiringPy.digital_write(pin_RST, OFF)
    time.sleep(0.1)
    wiringPy.digital_write(pin_RST, ON)

    contrast(contrast)
    cls()
    backlight(OFF)
    position(0, 0)

def contrast(value):
    """ sets the LCD contrast """
    map(command, [0x21, 0x14, contrast, 0x20, 0x0c])

def backlight(status):
    """ control backlight """
    wiringPy.digital_write(pin_LIGHT, 1 - status)

def SPI(value):
    """ send data, MSB first """
    for i in reversed(range(8)):
        wiringPy.digital_write(pin_DIN, (value>>i) & 0x01)
        wiringPy.digital_write(pin_CLK, ON)
        wiringPy.digital_write(pin_CLK, OFF)

def command(v):
    """ write command """
    wiringPy.digital_write(pin_DC, OFF)
    SPI(v)

def data(v):
    """ write a single byte of data at the current position """
    wiringPy.digital_write(pin_DC, ON)
    SPI(v)

def bitmap(arr):
    """ write a bitmap at the current position"""
    wiringPy.digital_write(pin_DC, ON)
    map(lambda b: SPI(b), arr)

def position(x, y):
    """ goto to column y in seg x """
    command(y + 0x80)
    command(x + 0x40)

def cls():
    """ clear screen """
    position(0, 0)
    bitmap([0] * (HEIGHT * WIDTH / 8))

def locate(x, y):
    """ goto row x and columd y to pain an character """
    position(x, y * 6)

def text(string, font = default_FONT, align = 'left'):
    """ draw string """
    map(lambda c: bitmap(font[c] + [0x00]), string)

<commit_msg>More tweaks<commit_after>#!/usr/bin/env python
# -*- coding: utf-8 -*-

import wiringPy
import time

# screen size in pixel
HEIGHT = WIDTH = 84

# default PINs, BCM GPIO
pin_CLK   = 24
pin_DIN   = 23
pin_DC    = 22
pin_RST   = 18
pin_LIGHT = 17
pin_CE    = 4

# useful constants
ON,   OFF = [1, 0]
HIGH, LOW = [1, 0]

# contrast
default_contrast = 0xB0

# FONT
default_FONT = {
    ' ': [0x00, 0x00, 0x00, 0x00, 0x00],
    '!': [0x00, 0x00, 0x5f, 0x00, 0x00],
    '"': [0x00, 0x07, 0x00, 0x07, 0x00],
    '#': [0x14, 0x7f, 0x14, 0x7f, 0x14],
    '$': [0x24, 0x2a, 0x7f, 0x2a, 0x12],
    '%': [0x23, 0x13, 0x08, 0x64, 0x62],
    '&': [0x36, 0x49, 0x55, 0x22, 0x50],
    "'": [0x00, 0x05, 0x03, 0x00, 0x00],
    '(': [0x00, 0x1c, 0x22, 0x41, 0x00],
    ')': [0x00, 0x41, 0x22, 0x1c, 0x00],
    '*': [0x14, 0x08, 0x3e, 0x08, 0x14],
    '+': [0x08, 0x08, 0x3e, 0x08, 0x08],
    ',': [0x00, 0x50, 0x30, 0x00, 0x00],
    '-': [0x08, 0x08, 0x08, 0x08, 0x08],
    '.': [0x00, 0x60, 0x60, 0x00, 0x00],
    '/': [0x20, 0x10, 0x08, 0x04, 0x02],
    '0': [0x3e, 0x51, 0x49, 0x45, 0x3e],
    '1': [0x00, 0x42, 0x7f, 0x40, 0x00],
    '2': [0x42, 0x61, 0x51, 0x49, 0x46],
    '3': [0x21, 0x41, 0x45, 0x4b, 0x31],
    '4': [0x18, 0x14, 0x12, 0x7f, 0x10],
    '5': [0x27, 0x45, 0x45, 0x45, 0x39],
    '6': [0x3c, 0x4a, 0x49, 0x49, 0x30],
    '7': [0x01, 0x71, 0x09, 0x05, 0x03],
    '8': [0x36, 0x49, 0x49, 0x49, 0x36],
    '9': [0x06, 0x49, 0x49, 0x29, 0x1e],
    ':': [0x00, 0x36, 0x36, 0x00, 0x00],
    ';': [0x00, 0x56, 0x36, 0x00, 0x00],
    '<': [0x08, 0x14, 0x22, 0x41, 0x00],
    '=': [0x14, 0x14, 0x14, 0x14, 0x14],
    '>': [0x00, 0x41, 0x22, 0x14, 0x08],
    '?': [0x02, 0x01, 0x51, 0x09, 0x06],
    '@': [0x32, 0x49, 0x79, 0x41, 0x3e],
    'A': [0x7e, 0x11, 0x11, 0x11, 0x7e],
    'B': [0x7f, 0x49, 0x49, 0x49, 0x36],
    'C': [0x3e, 0x41, 0x41, 0x41, 0x22],
    'D': [0x7f, 0x41, 0x41, 0x22, 0x1c],
    'E': [0x7f, 0x49, 0x49, 0x49, 0x41],
    'F': [0x7f, 0x09, 0x09, 0x09, 0x01],
    'G': [0x3e, 0x41, 0x49, 0x49, 0x7a],
    'H': [0x7f, 0x08, 0x08, 0x08, 0x7f],
    'I': [0x00, 0x41, 0x7f, 0x41, 0x00],
    'J': [0x20, 0x40, 0x41, 0x3f, 0x01],
    'K': [0x7f, 0x08, 0x14, 0x22, 0x41],
    'L': [0x7f, 0x40, 0x40, 0x40, 0x40],
    'M': [0x7f, 0x02, 0x0c, 0x02, 0x7f],
    'N': [0x7f, 0x04, 0x08, 0x10, 0x7f],
    'O': [0x3e, 0x41, 0x41, 0x41, 0x3e],
    'P': [0x7f, 0x09, 0x09, 0x09, 0x06],
    'Q': [0x3e, 0x41, 0x51, 0x21, 0x5e],
    'R': [0x7f, 0x09, 0x19, 0x29, 0x46],
    'S': [0x46, 0x49, 0x49, 0x49, 0x31],
    'T': [0x01, 0x01, 0x7f, 0x01, 0x01],
    'U': [0x3f, 0x40, 0x40, 0x40, 0x3f],
    'V': [0x1f, 0x20, 0x40, 0x20, 0x1f],
    'W': [0x3f, 0x40, 0x38, 0x40, 0x3f],
    'X': [0x63, 0x14, 0x08, 0x14, 0x63],
    'Y': [0x07, 0x08, 0x70, 0x08, 0x07],
    'Z': [0x61, 0x51, 0x49, 0x45, 0x43],
    '[': [0x00, 0x7f, 0x41, 0x41, 0x00],
    '\\': [0x02, 0x04, 0x08, 0x10, 0x20],
    ']': [0x00, 0x41, 0x41, 0x7f, 0x00],
    '^': [0x04, 0x02, 0x01, 0x02, 0x04],
    '_': [0x40, 0x40, 0x40, 0x40, 0x40],
    '`': [0x00, 0x01, 0x02, 0x04, 0x00],
    'a': [0x20, 0x54, 0x54, 0x54, 0x78],
    'b': [0x7f, 0x48, 0x44, 0x44, 0x38],
    'c': [0x38, 0x44, 0x44, 0x44, 0x20],
    'd': [0x38, 0x44, 0x44, 0x48, 0x7f],
    'e': [0x38, 0x54, 0x54, 0x54, 0x18],
    'f': [0x08, 0x7e, 0x09, 0x01, 0x02],
    'g': [0x0c, 0x52, 0x52, 0x52, 0x3e],
    'h': [0x7f, 0x08, 0x04, 0x04, 0x78],
    'i': [0x00, 0x44, 0x7d, 0x40, 0x00],
    'j': [0x20, 0x40, 0x44, 0x3d, 0x00],
    'k': [0x7f, 0x10, 0x28, 0x44, 0x00],
    'l': [0x00, 0x41, 0x7f, 0x40, 0x00],
    'm': [0x7c, 0x04, 0x18, 0x04, 0x78],
    'n': [0x7c, 0x08, 0x04, 0x04, 0x78],
    'o': [0x38, 0x44, 0x44, 0x44, 0x38],
    'p': [0x7c, 0x14, 0x14, 0x14, 0x08],
    'q': [0x08, 0x14, 0x14, 0x18, 0x7c],
    'r': [0x7c, 0x08, 0x04, 0x04, 0x08],
    's': [0x48, 0x54, 0x54, 0x54, 0x20],
    't': [0x04, 0x3f, 0x44, 0x40, 0x20],
    'u': [0x3c, 0x40, 0x40, 0x20, 0x7c],
    'v': [0x1c, 0x20, 0x40, 0x20, 0x1c],
    'w': [0x3c, 0x40, 0x30, 0x40, 0x3c],
    'x': [0x44, 0x28, 0x10, 0x28, 0x44],
    'y': [0x0c, 0x50, 0x50, 0x50, 0x3c],
    'z': [0x44, 0x64, 0x54, 0x4c, 0x44],
    '{': [0x00, 0x08, 0x36, 0x41, 0x00],
    '|': [0x00, 0x00, 0x7f, 0x00, 0x00],
    '}': [0x00, 0x41, 0x36, 0x08, 0x00],
    '~': [0x10, 0x08, 0x08, 0x10, 0x08],
}

def init(CLK = 24, DIN = 23, DC = 22, RST = 18, LIGHT = 17, CE = 4, contrast = default_contrast):
    """ init screen, trun off backlight, clearscreen """
    wiringPy.setup_gpio()
    pins = [CLK, DIN, DC, RST, LIGHT]
    pin_CLK, pin_DIN, pin_DC, pin_RST, pin_LIGHT, pin_CE = pins
    map(lambda p: wiringPy.pin_mode(p, ON), pins)

    # Reset the device
    wiringPy.digital_write(pin_RST, OFF)
    time.sleep(0.1)
    wiringPy.digital_write(pin_RST, ON)

    contrast(contrast)
    cls()
    backlight(OFF)
    position(0, 0)

def contrast(value):
    """ sets the LCD contrast """
    command([0x21, 0x14, contrast, 0x20, 0x0c])

def backlight(status):
    """ control backlight """
    wiringPy.digital_write(pin_LIGHT, 1 - status)

def SPI(value):
    """ send data, MSB first """
    for i in reversed(range(8)):
        wiringPy.digital_write(pin_DIN, (value>>i) & 0x01)
        wiringPy.digital_write(pin_CLK, ON)
        wiringPy.digital_write(pin_CLK, OFF)

def command(arr):
    """ write commands """
    bitmap(arr, OFF)

def data(arr):
    """ write data """
    bitmap(arr, ON)

def bitmap(arr, dc):
    """ write a sequence of bytes, either as data or command"""
    wiringPy.digital_write(pin_DC, dc)
    map(lambda b: SPI(b), arr)

def position(x, y):
    """ goto to column y in seg x """
    command([y + 0x80, x + 0x40])

def cls():
    """ clear screen """
    position(0, 0)
    data([0] * (HEIGHT * WIDTH / 8))

def locate(x, y):
    """ goto row x and columd y to pain an character """
    position(x, y * 6)

def text(string, font = default_FONT, align = 'left'):
    """ draw string """
    map(lambda c: data(font[c] + [0x00]), string)

<|endoftext|>


<commit_before>import random
import urllib.parse

# noinspection PyPackageRequirements
import discord
# noinspection PyPackageRequirements
from discord.ext import commands
# noinspection PyPackageRequirements
import utils.errors
import asyncio
from collections import defaultdict

locks = defaultdict(asyncio.Lock)

class Fun:
    def __init__(self, bot):
        self.bot = bot

        self.agent = {
            'User-Agent': 'lolbot(aiohttp/discord.py) - https://lolbot.banne.club'
        }

        self.dadjoke = {
            'User-Agent': 'lolbot(aiohttp/discord.py) - https://lolbot.banne.club',
            'Accept': 'text/plain'
        }

    @commands.command()
    async def cat(self, ctx):
        """Random cat images. Awww, so cute! Powered by random.cat"""
        async with self.bot.session.get('https://random.cat/meow', headers=self.agent) as r:
            if r.status == 200:
                js = await r.json()
                em = discord.Embed(name='random.cat', colour=0x690E8)
                em.set_image(url=js['file'])
                await ctx.send(embed=em)
            else:
                raise utils.errors.ServiceError(f'could not fetch cute cat :( (http {r.status})')

    @commands.command()
    async def httpcat(self, ctx, http_id: int):
        """http.cat images - ^httpcat <http code>"""
        codes = [100, 101, 200, 201, 202, 204, 206, 207, 300, 301, 302, 303, 304, 305, 307, 400,
                 401, 402, 403, 404, 405, 406, 408, 409, 410, 411, 412, 413, 414, 416, 417, 418, 420,
                 421, 422, 423, 424, 425, 426, 429, 444, 450, 451, 500, 502, 503, 504, 506, 507, 508,
                 509, 511, 599]
        if http_id in codes:
            httpcat_em = discord.Embed(name='http.cat', colour=0x690E8)
            httpcat_em.set_image(url=f'https://http.cat/{http_id}.jpg')
            await ctx.send(embed=httpcat_em)
        else:
            raise commands.BadArgument('Specified HTTP code invalid')

    @commands.command()
    async def dog(self, ctx):
        """Random dogs, by random.dog"""
        async with self.bot.session.get('https://random.dog/woof', headers=self.agent) as shibeGet:
            if shibeGet.status == 200:
                shibe_img = await shibeGet.text()
                shibe_url = 'https://random.dog/' + shibe_img
                if '.mp4' in shibe_url:
                    await ctx.send('mp4 file: ' + shibe_url)
                else:
                    shibe_em = discord.Embed(colour=0x690E8)
                    shibe_em.set_image(url=shibe_url)
                    await ctx.send(embed=shibe_em)
            else:
                raise utils.errors.ServiceError(f'could not fetch pupper :( (http {shibeGet.status})')

    @commands.command()
    async def lizard(self, ctx):
        """Shows a random lizard picture"""
        async with self.bot.session.get('https://nekos.life/api/lizard', headers=self.agent) as lizr:
            if lizr.status == 200:
                img = await lizr.json()
                liz_em = discord.Embed(colour=0x690E8)
                liz_em.set_image(url=img['url'])
                await ctx.send(embed=liz_em)
            else:
                raise utils.errors.ServiceError(f'something went boom (http {lizr.status})')

    @commands.command()
    async def why(self, ctx):
        """Why _____?"""
        async with self.bot.session.get('https://nekos.life/api/why', headers=self.agent) as why:
            if why.status == 200:
                why_js = await why.json()
                why_em = discord.Embed(title=f'{ctx.author.name} wonders...',
                                      description=why_js['why'], colour=0x690E8)
                await ctx.send(embed=why_em)
            else:
                raise utils.errors.ServiceError(f'something went boom (http {why.status})')

    @commands.command(aliases=['rhash', 'robothash', 'rh', 'rohash'])
    async def robohash(self, ctx, *, meme: str):
        """Generates a picture of some bot from some text"""
        try:
            e = discord.Embed(colour=0x690E8)
            meme = urllib.parse.quote_plus(meme)
            e.set_image(url=f'https://robohash.org/{meme}.png')
            await ctx.send(embed=e)
        except Exception as e:
            raise utils.errors.ServiceError(f'something broke: {e!s}')

    @commands.command()
    async def k(self, ctx):
        """k"""
        await ctx.send('k')

    @commands.command()
    async def fuck(self, ctx):
        """fuck"""
        await ctx.send('fuck')

    @commands.command(name='8ball')
    async def an8ball(self, ctx, *, question: str):
        pool = ['It is certain', 'Outlook good', 'You may rely on it', 'Ask again '
                                                                       'later', 'Concentrate and ask again',
                'Reply hazy, try again', 'My reply is '
                                         'no', 'My sources say no']
        ans = random.choice(pool)
        emb = discord.Embed(title='The Magic 8-ball', description='**Question: ' +
                                                                  str(question) + '**\nAnswer: ' + str(ans),
                            colour=0x690E8)
        await ctx.send(embed=emb)

    @commands.command(aliases=['fidget', 'fidgetspinner', 'spinner'])
    async def spin(self, ctx):
        """Spins a fidget spinner!
        The spin time varies from 1 second, to 300 secs (5 mins)."""
        try:
            await locks[ctx.author.id]
            spin_time = random.randint(1, 300)
            land = await ctx.send('You spun a fidget spinner! '
                                  'Let\'s see how long it goes.')
            await asyncio.sleep(spin_time)
            e = discord.Embed(description=f'Your fidget spinner spun for '
                                          f'**{spin_time}** seconds!',
                              colour=0x690E8)
            await land.edit(content='The results are in!', embed=e)
        finally:
            locks[ctx.author.id].release()

    async def get_answer(self, ans: str):
        if ans == 'yes':
            return 'Yes.'
        elif ans == 'no':
            return 'NOPE'
        elif ans == 'maybe':
            return 'maaaaaaybe?'
        else:
            raise commands.BadArgument('internal error: invalid answer lmaoo')

    @commands.command(aliases=['shouldi', 'ask'])
    async def yesno(self, ctx, *, question: str):
        """Why not make your decisions with a bot?"""
        async with ctx.bot.session.get('https://yesno.wtf/api', headers=self.agent) as meme:
            if meme.status == 200:
                mj = await meme.json()
                ans = await self.get_answer(mj['answer'])
                em = discord.Embed(title=ans, description=f'And the answer to {question} is this', colour=0x690E8)
                em.set_image(url=mj['image'])
                await ctx.send(embed=em)
            else:
                raise utils.errors.ServiceError(f'oof (http {meme.status})')

    @commands.command(aliases=['dadjoke', 'awdad', 'dadpls', 'shitjoke', 'badjoke'])
    async def joke(self, ctx):
        """Dad joke simulator 3017, basically"""
        async with ctx.bot.session.get('https://icanhazdadjoke.com', headers=self.dadjoke) as jok:
            if jok.status == 200:
                res = await jok.text()
                await ctx.send(f'`{res}`')
            else:
                raise utils.errors.ServiceError(f'rip dad (http {jok.status})')

    @commands.command(aliases=['ph', 'porn'])
    @commands.is_nsfw()
    async def pornhub(self, ctx, *, query: str):
        """Searches for porn on pornhub"""
        lol = await ctx.send('Searching...')
        await asyncio.sleep(1.7)
        pranked = discord.Embed(title='Pranked!', description='I can\'t really search PornHub. '
                                                              'BUT, some bots do.', colour=0x690E8)
        pranked.add_field(name='BoobBot', value='BoobBot can actually search PornHub. '
                     'To invite this bot [click here](https://discordapp.com/oauth2/authorize'
                     '?client_id=285480424904327179&scope=bot)!')
        await lol.edit(content=None, embed=pranked)
        del query

def setup(bot):
    bot.add_cog(Fun(bot))
<commit_msg>cogs[fun]: revamp dog<commit_after>import random
import urllib.parse

# noinspection PyPackageRequirements
import discord
# noinspection PyPackageRequirements
from discord.ext import commands
# noinspection PyPackageRequirements
import utils.errors
import asyncio
from collections import defaultdict

locks = defaultdict(asyncio.Lock)

class Fun:
    def __init__(self, bot):
        self.bot = bot

        self.agent = {
            'User-Agent': 'lolbot(aiohttp/discord.py) - https://lolbot.banne.club'
        }

        self.dadjoke = {
            'User-Agent': 'lolbot(aiohttp/discord.py) - https://lolbot.banne.club',
            'Accept': 'text/plain'
        }

    @commands.command()
    async def cat(self, ctx):
        """Random cat images. Awww, so cute! Powered by random.cat"""
        async with self.bot.session.get('https://random.cat/meow', headers=self.agent) as r:
            if r.status == 200:
                js = await r.json()
                em = discord.Embed(name='random.cat', colour=0x690E8)
                em.set_image(url=js['file'])
                await ctx.send(embed=em)
            else:
                raise utils.errors.ServiceError(f'could not fetch cute cat :( (http {r.status})')

    @commands.command()
    async def httpcat(self, ctx, http_id: int):
        """http.cat images - ^httpcat <http code>"""
        codes = [100, 101, 200, 201, 202, 204, 206, 207, 300, 301, 302, 303, 304, 305, 307, 400,
                 401, 402, 403, 404, 405, 406, 408, 409, 410, 411, 412, 413, 414, 416, 417, 418, 420,
                 421, 422, 423, 424, 425, 426, 429, 444, 450, 451, 500, 502, 503, 504, 506, 507, 508,
                 509, 511, 599]
        if http_id in codes:
            httpcat_em = discord.Embed(name='http.cat', colour=0x690E8)
            httpcat_em.set_image(url=f'https://http.cat/{http_id}.jpg')
            await ctx.send(embed=httpcat_em)
        else:
            raise commands.BadArgument('Specified HTTP code invalid')

    @commands.command()
    async def dog(self, ctx):
        """Random doggos just because!"""
        def decide_source():
            n = random.random()
            if n < 0.5:
                return 'https://random.dog/woof'
            elif n > 0.5:
                return 'https://dog.ceo/api/breeds/image/random'

        async with self.bot.session.get(decide_source(), headers=self.agent) as shibe_get:
            if shibe_get.status == 200:
                if shibe_get.host == 'random.dog':
                    shibe_img = await shibe_get.text()
                    shibe_url = shibe_get.host + '/' + shibe_img
                elif shibe_get.host == 'dog.ceo':
                    shibe_img = await shibe_get.json()
                    shibe_url = shibe_img['message']

                if '.mp4' in shibe_url:
                    await ctx.send('mp4 file: ' + shibe_url)
                else:
                    shibe_em = discord.Embed(colour=0x690E8)
                    shibe_em.set_image(url=shibe_url)
                    await ctx.send(embed=shibe_em)
            else:
                raise utils.errors.ServiceError(f'could not fetch pupper :( (http {shibe_get.status})')

    @commands.command()
    async def lizard(self, ctx):
        """Shows a random lizard picture"""
        async with self.bot.session.get('https://nekos.life/api/lizard', headers=self.agent) as lizr:
            if lizr.status == 200:
                img = await lizr.json()
                liz_em = discord.Embed(colour=0x690E8)
                liz_em.set_image(url=img['url'])
                await ctx.send(embed=liz_em)
            else:
                raise utils.errors.ServiceError(f'something went boom (http {lizr.status})')

    @commands.command()
    async def why(self, ctx):
        """Why _____?"""
        async with self.bot.session.get('https://nekos.life/api/why', headers=self.agent) as why:
            if why.status == 200:
                why_js = await why.json()
                why_em = discord.Embed(title=f'{ctx.author.name} wonders...',
                                      description=why_js['why'], colour=0x690E8)
                await ctx.send(embed=why_em)
            else:
                raise utils.errors.ServiceError(f'something went boom (http {why.status})')

    @commands.command(aliases=['rhash', 'robothash', 'rh', 'rohash'])
    async def robohash(self, ctx, *, meme: str):
        """Generates a picture of some bot from some text"""
        try:
            e = discord.Embed(colour=0x690E8)
            meme = urllib.parse.quote_plus(meme)
            e.set_image(url=f'https://robohash.org/{meme}.png')
            await ctx.send(embed=e)
        except Exception as e:
            raise utils.errors.ServiceError(f'something broke: {e!s}')

    @commands.command()
    async def k(self, ctx):
        """k"""
        await ctx.send('k')

    @commands.command()
    async def fuck(self, ctx):
        """fuck"""
        await ctx.send('fuck')

    @commands.command(name='8ball')
    async def an8ball(self, ctx, *, question: str):
        pool = ['It is certain', 'Outlook good', 'You may rely on it', 'Ask again '
                                                                       'later', 'Concentrate and ask again',
                'Reply hazy, try again', 'My reply is '
                                         'no', 'My sources say no']
        ans = random.choice(pool)
        emb = discord.Embed(title='The Magic 8-ball', description='**Question: ' +
                                                                  str(question) + '**\nAnswer: ' + str(ans),
                            colour=0x690E8)
        await ctx.send(embed=emb)

    @commands.command(aliases=['fidget', 'fidgetspinner', 'spinner'])
    async def spin(self, ctx):
        """Spins a fidget spinner!
        The spin time varies from 1 second, to 300 secs (5 mins)."""
        try:
            await locks[ctx.author.id]
            spin_time = random.randint(1, 300)
            land = await ctx.send('You spun a fidget spinner! '
                                  'Let\'s see how long it goes.')
            await asyncio.sleep(spin_time)
            e = discord.Embed(description=f'Your fidget spinner spun for '
                                          f'**{spin_time}** seconds!',
                              colour=0x690E8)
            await land.edit(content='The results are in!', embed=e)
        finally:
            locks[ctx.author.id].release()

    async def get_answer(self, ans: str):
        if ans == 'yes':
            return 'Yes.'
        elif ans == 'no':
            return 'NOPE'
        elif ans == 'maybe':
            return 'maaaaaaybe?'
        else:
            raise commands.BadArgument('internal error: invalid answer lmaoo')

    @commands.command(aliases=['shouldi', 'ask'])
    async def yesno(self, ctx, *, question: str):
        """Why not make your decisions with a bot?"""
        async with ctx.bot.session.get('https://yesno.wtf/api', headers=self.agent) as meme:
            if meme.status == 200:
                mj = await meme.json()
                ans = await self.get_answer(mj['answer'])
                em = discord.Embed(title=ans, description=f'And the answer to {question} is this', colour=0x690E8)
                em.set_image(url=mj['image'])
                await ctx.send(embed=em)
            else:
                raise utils.errors.ServiceError(f'oof (http {meme.status})')

    @commands.command(aliases=['dadjoke', 'awdad', 'dadpls', 'shitjoke', 'badjoke'])
    async def joke(self, ctx):
        """Dad joke simulator 3017, basically"""
        async with ctx.bot.session.get('https://icanhazdadjoke.com', headers=self.dadjoke) as jok:
            if jok.status == 200:
                res = await jok.text()
                await ctx.send(f'`{res}`')
            else:
                raise utils.errors.ServiceError(f'rip dad (http {jok.status})')

    @commands.command(aliases=['ph', 'porn'])
    @commands.is_nsfw()
    async def pornhub(self, ctx, *, query: str):
        """Searches for porn on pornhub"""
        lol = await ctx.send('Searching...')
        await asyncio.sleep(1.7)
        pranked = discord.Embed(title='Pranked!', description='I can\'t really search PornHub. '
                                                              'BUT, some bots do.', colour=0x690E8)
        pranked.add_field(name='BoobBot', value='BoobBot can actually search PornHub. '
                     'To invite this bot [click here](https://discordapp.com/oauth2/authorize'
                     '?client_id=285480424904327179&scope=bot)!')
        await lol.edit(content=None, embed=pranked)
        del query

    @commands.command()
    async def coolpeople(self, ctx):
        """Displays cool people"""
        if self.bot.config['dbl'] and self.bot.config['dbotsorg']:
            async with ctx.bot.session.post(f'https://discordbots.org/api/bots/{ctx.me.id}/votes') as v:

def setup(bot):
    bot.add_cog(Fun(bot))
<|endoftext|>


<commit_before>#!/usr/bin/env python
"""A small script that can act as a trust root for installing pip 8

Embed this in your project, and your VCS checkout is all you have to trust. In
a post-peep era, this lets you claw your way to a hash-checking version of pip,
with which you can install the rest of your dependencies safely. All it assumes
is Python 2.7 or better and *some* version of pip already installed. If
anything goes wrong, it will exit with a non-zero status code.

"""
# This is here so embedded copies are MIT-compliant:
# Copyright (c) 2016 Erik Rose
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
# deal in the Software without restriction, including without limitation the
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
# sell copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
from __future__ import print_function
from hashlib import sha256
from os.path import join
from pipes import quote
from shutil import rmtree
from subprocess import check_output
from sys import exit
from tempfile import mkdtemp
try:
    from urllib2 import build_opener, HTTPHandler, HTTPSHandler
except ImportError:
    from urllib.request import build_opener, HTTPHandler, HTTPSHandler
try:
    from urlparse import urlparse
except ImportError:
    from urllib.parse import urlparse  # 3.4

class HashError(Exception):
    def __str__(self):
        url, path, actual, expected = self.args
        return ('{url} did not match the expected hash {expected}. Instead, '
                'it was {actual}. The file (left at {path}) may have been '
                'tampered with.'.format(**locals()))

def hashed_download(url, temp, digest):
    """Download ``url`` to ``temp``, make sure it has the SHA-256 ``digest``,
    and return its path."""
    # Based on pip 1.4.1's URLOpener but with cert verification removed
    def opener():
        opener = build_opener(HTTPSHandler())
        # Strip out HTTPHandler to prevent MITM spoof:
        for handler in opener.handlers:
            if isinstance(handler, HTTPHandler):
                opener.handlers.remove(handler)
        return opener

    def read_chunks(response, chunk_size):
        while True:
            chunk = response.read(chunk_size)
            if not chunk:
                break
            yield chunk

    response = opener().open(url)
    path = join(temp, urlparse(url).path.split('/')[-1])
    actual_hash = sha256()
    with open(path, 'wb') as file:
        for chunk in read_chunks(response, 4096):
            file.write(chunk)
            actual_hash.update(chunk)

    actual_digest = actual_hash.hexdigest()
    if actual_digest != digest:
        raise HashError(url, path, actual_digest, digest)
    return path

def main():
    temp = mkdtemp(prefix='pipstrap-')
    try:
        packages = [
            # Pip has no dependencies, as it vendors everything:
            ('https://pypi.python.org/packages/source/p/pip/pip-8.0.2.tar.gz',
             '46f4bd0d8dfd51125a554568d646fe4200a3c2c6c36b9f2d06d2212148439521'),
            # This version of setuptools has only optional dependencies:
            ('https://pypi.python.org/packages/source/s/setuptools/setuptools-19.4.tar.gz',
             '214bf29933f47cf25e6faa569f710731728a07a19cae91ea64f826051f68a8cf'),
            # We require Python 2.7 or later because we don't support wheel's
            # conditional dep on argparse. This version of wheel has no other
            # dependencies:
            ('https://pypi.python.org/packages/source/w/wheel/wheel-0.26.0.tar.gz',
             'eaad353805c180a47545a256e6508835b65a8e830ba1093ed8162f19a50a530c')
        ]
        downloads = [hashed_download(package[0], temp, package[1])
                     for package in packages]
        check_output('pip install --no-index --no-deps -U ' +
                         ' '.join(quote(d) for d in downloads),
                     shell=True)
    except HashError as exc:
        print(exc)
    except Exception:
        rmtree(temp)
        raise
    else:
        rmtree(temp)
        return 0
    return 1

if __name__ == '__main__':
    exit(main())
<commit_msg>Remove pipstrap. No longer required.<commit_after><|endoftext|>


<commit_before>#!/usr/bin/env python

import warnings
import os.path as op

from funcargparse import FuncArgParser
from gooey import Gooey
from configupdater import ConfigUpdater

with warnings.catch_warnings():
    warnings.simplefilter("ignore")

    import logging
    logging.basicConfig(level=logging.INFO)
    logger = logging.getLogger('pyAFQ')
    logger.info("Loading AFQ api...")

    from AFQ.api import AFQ
    from AFQ.utils.bin import get_default_args
    import AFQ.segmentation as seg
    import AFQ.tractography as aft

def process_defaults(defaults_dict):
    defaults_list = []
    for k, v in defaults_dict.items():
        if isinstance(v, str):
            defaults_list.append(f"{k} = '{v}'")
        elif isinstance(v, bool):
            if v:
                defaults_list.append(f"{k} = true")
            else:
                defaults_list.append(f"{k} = false")
        elif callable(v):
            defaults_list.append(f"{k} = '{v.__name__}'")
        else:
            defaults_list.append(f"{k} = {v}")
    return defaults_list

track_defaults = get_default_args(aft.track)
track_defaults_list = process_defaults(track_defaults)
seg_defaults = get_default_args(seg.Segmentation.__init__)
seg_defaults_list = process_defaults(seg_defaults)
clean_defaults = get_default_args(seg.clean_bundle)
clean_defaults_list = process_defaults(clean_defaults)

@Gooey
def parse():
    parser = FuncArgParser()
    parser.setup_args(AFQ.__init__)

    parser.append2help(
        'segmentation_params',
        " Parameters Include: \n\t" + "\n\t".join(seg_defaults_list))
    parser.append2help(
        'tracking_params',
        " Parameters Include: \n\t" + "\n\t".join(track_defaults_list))
    parser.append2help(
        'clean_params',
        " Parameters Include: \n\t" + "\n\t".join(clean_defaults_list))

    config_file = "./test.ini"
    cfparser = ConfigUpdater()
    if not op.exists(config_file):
        open(config_file, 'w').close()
    cfparser.read(config_file)

    # updates any arguments not currently in .ini
    for arg, info in parser.unfinished_arguments.items():
        try:
            section, desc = info['help'].split('[')[1].split(']')
        except KeyError:
            logger.warning(
                "You are missing a valid description for the "
                + "AFQ argument " + arg)
            continue
        if cfparser.has_option(section, arg):
            new_default = cfparser[section][arg]
            if new_default is "''":
                new_default = None
            parser.unfinished_arguments[arg]['default'] = new_default

        else:
            if not cfparser.has_section(section):
                cfparser.add_section(section)
            if 'default' in info and info['default'] is not None:
                default = info['default']
            else:
                default = "''"
            cfparser[section][arg] = default

            for desc_line in desc.splitlines():
                cfparser[section][arg].add_before.comment(
                    desc_line, comment_prefix=';')

    cfparser.update_file()
    parser.create_arguments()
    # TODO: cli, gui

if __name__ == '__main__':
    parse()<commit_msg>getting gui to work<commit_after>#!/usr/bin/env pythonw

import warnings
import os.path as op

from funcargparse import FuncArgParser
from argparse import ArgumentParser, FileType
from cli2gui import Cli2Gui
from configupdater import ConfigUpdater

with warnings.catch_warnings():
    warnings.simplefilter("ignore")

    import logging
    logging.basicConfig(level=logging.INFO)
    logger = logging.getLogger('pyAFQ')
    logger.info("Loading AFQ api...")

    import AFQ
    import AFQ.api as api
    from AFQ.utils.bin import get_default_args
    import AFQ.segmentation as seg
    import AFQ.tractography as aft

use_config_gui = True
gui_theme = \
    ["#e7e7e9", "#dfdfe1", "#cacace", "#a0a1a7", "#696c77",
     "#383a42", "#202227", "#090a0b", "#ca1243", "#c18401", "#febb2a",
     "#50a14f", "#0184bc", "#4078f2", "#a626a4", "#986801", "#f0f0f1",
     "#fafafa", "#ec2258", "#f4a701", "#6db76c", "#01a7ef", "#709af5",
     "#d02fcd"]
gui_sizes = \
    {"title_size": 36,
     "label_size": (30, None),
     "input_size": (30, 1),
     "button": (10, 1),
     "padding": (5, 10),
     "helpText_size": 2,  # no effect?
     "text_size": 18},
usage = \
f"""pyAFQ /path/to/afq_config.ini

Runs full AFQ processing as specified in the configuration file.

To not run the CLI with a GUI, use --disable-cli2gui .

To not open a GUI for editing the config file, use --disable-config2gui .

For details about configuration, see instructions in:
https://yeatmanlab.github.io/pyAFQ/usage.html#running-the-pyafq-pipeline
"""

def process_defaults(defaults_dict):
    defaults_list = []
    for k, v in defaults_dict.items():
        if isinstance(v, str):
            defaults_list.append(f"{k} = '{v}'")
        elif isinstance(v, bool):
            if v:
                defaults_list.append(f"{k} = true")
            else:
                defaults_list.append(f"{k} = false")
        elif callable(v):
            defaults_list.append(f"{k} = '{v.__name__}'")
        else:
            defaults_list.append(f"{k} = {v}")
    return defaults_list

@Cli2Gui(
    program_name="pyAFQ CLI",
    program_description=usage,
    image=None,
    sizes=gui_sizes,
    auto_enable=True,
    gui="pysimplegui",
    parser="argparse",
    theme=gui_theme,
    darktheme=None)
def parse_cli():
    # cli_parser parses user arguments from CLI,
    # It is also what gooey uses to make the GUI
    cli_parser = ArgumentParser(usage=usage)

    cli_parser.add_argument(
        dest='config',
        action="store",
        type=FileType('w'),
        help="Path to config file. For example, /path/to/afq_config.ini")

    cli_parser.add_argument(
        '-t', '--notrack', action="store_true", default=False,
        help="Disable the use of pyAFQ being recorded by Google Analytics. ")

    cli_parser.add_argument(
        '--disable-config2gui', action="store_true", default=False,
        help="Disable the GUI for editing the config file. ")

    opts = cli_parser.parse_args()

    if not opts.notrack:
        logger.info(
            "Your use of pyAFQ is being recorded using Google Analytics. "
            "For more information, please refer to the pyAFQ documentation: "
            "https://yeatmanlab.github.io/pyAFQ/usage.html#usage-tracking-with-google-analytics. "  # noqa
            "To turn this off, use the `--notrack` flag when using the pyAFQ CLI")
        import popylar
        popylar.track_event(AFQ._ga_id, "pyAFQ_cli", "CLI called")
    opts.config.close()
    use_config_gui = not opts.disable_config2gui # TODO: make this work

    return opts.config.name

Cli2Gui(
    run_function=parse_doc,
    program_name="pyAFQ Configuration",
    program_description="Set parameters in config file.",
    image=None,
    sizes={
		"title_size": 36,
		"label_size": (30, None),
		"input_size": (30, 1),
		"button":(10, 1),
		"padding":(5, 10),
		"helpText_size": 2, # no effect?
		"text_size": 18},
    auto_enable=use_config_gui,
    gui="pysimplegui",
    parser="argparse",
    theme=gui_theme,
    darktheme=None)
def parse_doc():
    # doc_parser organizes the docstring for AFQ.api.AFQ
    docstr_parser = FuncArgParser()
    docstr_parser.setup_args(api.AFQ.__init__)

    track_defaults = get_default_args(aft.track)
    track_defaults_list = process_defaults(track_defaults)
    seg_defaults = get_default_args(seg.Segmentation.__init__)
    seg_defaults_list = process_defaults(seg_defaults)
    clean_defaults = get_default_args(seg.clean_bundle)
    clean_defaults_list = process_defaults(clean_defaults)

    docstr_parser.append2help(
        'segmentation_params',
        " Parameters Include: \n\t" + "\n\t".join(seg_defaults_list))
    docstr_parser.append2help(
        'tracking_params',
        " Parameters Include: \n\t" + "\n\t".join(track_defaults_list))
    docstr_parser.append2help(
        'clean_params',
        " Parameters Include: \n\t" + "\n\t".join(clean_defaults_list))

    docstr_parser.create_arguments()
    opts = docstr_parser.parse_args()

    return docstr_parser.unfinished_arguments, opts # TODO: or between opts and unfinished args

def parse_config(config_file, doc_args):
    # cfparser parses the config .ini file
    cfparser = ConfigUpdater()
    if not op.exists(config_file):
        open(config_file, 'w').close()
    cfparser.read(config_file)

    # updates any arguments not currently in .ini
    for arg, info in doc_args.items():
        try:
            section, desc = info['help'].split('[')[1].split(']')
        except KeyError:
            logger.warning(
                "We are missing a valid description for the "
                + "AFQ argument " + arg)
            continue
        if cfparser.has_option(section, arg):
            new_default = cfparser[section][arg]
            if new_default is "''":
                new_default = None
            doc_args[arg]['default'] = new_default

        else:
            if not cfparser.has_section(section):
                cfparser.add_section(section)
            if 'default' in info and info['default'] is not None:
                default = info['default']
            else:
                default = "''"
            cfparser[section][arg] = default

            for desc_line in desc.splitlines():
                cfparser[section][arg].add_before.comment(
                    desc_line, comment_prefix=';')

    cfparser.update_file()

    breakpoint()
    # TODO: from config, call AFQ

if __name__ == '__main__':
    config_file = parse_cli()
    doc_args = parse_doc()
    parse_config(config_file, doc_args)
<|endoftext|>


<commit_before># Copyright (c) 2010-2011, GEM Foundation.
#
# OpenQuake is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License version 3
# only, as published by the Free Software Foundation.
#
# OpenQuake is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Lesser General Public License version 3 for more details
# (a copy is included in the LICENSE file that accompanied this code).
#
# You should have received a copy of the GNU Lesser General Public License
# version 3 along with OpenQuake.  If not, see
# <http://www.gnu.org/licenses/lgpl-3.0.txt> for a copy of the LGPLv3 License.

"""Hazard calculator and task functionality."""
<commit_msg>Remove the now-unused hazard/ package. Hooray\!<commit_after><|endoftext|>


<commit_before>#! /usr/bin/env python

import requests
import fnmatch
import subprocess
import argparse
import json

def get_header_string():
    buf = '''AUTOMATIC LINT RESULTS DO NOT EDIT\n'''
    return buf

def get_lint_comment(base, api_key, pr_num):
    url = base + '/issues/{num}/comments?access_token={api_key}'.format(num=pr_num,
                                                                       api_key=api_key)
    headers = {}
    headers['Accept'] = 'application/json'
    comment_id = None
    req = requests.get(url, headers=headers)
    for comment in req.json():
        if comment['body'].startswith(get_header_string()):
            comment_id = comment['id']
    return comment_id

def create_or_update_lint_comment(base, api_key, pr_num, errors):
    body = get_header_string() + '\n' + generate_buf(errors)
    comment_id = get_lint_comment(base, api_key, pr_num)
    data = {'body': body}
    if comment_id:
        url = base + '/issues/comments/{id}?access_token={api_key}'.format(num=pr_num,
                                                                                id=comment_id,
                                                                                api_key=api_key)
        requests.patch(url, headers=get_headers(), data=json.dumps(data))
    else:
        url = base + '/issues/{num}/comments?access_token={api_key}'.format(num=pr_num,
                                                                            api_key=api_key)
        requests.post(url, headers=get_headers(), data=json.dumps(data))

def get_headers():
    return {'Accept': 'application/json'}

def post_result(base, failed_files, api_key, sha):
    url = base + '/statuses/{sha}?access_token={api_key}'.format(sha=sha,
                                                                 api_key=api_key)
    if any(failed_files):
        status = 'failure'
        description = 'Lint failed'
        # Sad Panda
        link = 'http://fc08.deviantart.net/fs70/f/2010/149/a/7/Sad_Panda_Chibi_by_mongrelssister.png'
    else:
        status = 'success'
        description = 'Lint passed'
        link = 'http://i.imgur.com/DPVM1.png'
    data = {"state": status, "target_url": link,
            "description": description, "context": "lint"}
    headers = {}
    headers['Accept'] = 'application/json'
    requests.post(url, data=json.dumps(data), headers=headers)

def generate_buf(errors):
    if errors:
        msg = []
        for fname, errors in errors.iteritems():
            msg += ['Lint Errors for {}'.format(fname)]
            for error in errors:
                line_num, errstr = error
                msg.append('\t{}:\t{}'.format(line_num, errstr))
        msg = '\n'.join(msg)
    else:
        msg = 'Lint all good :shipit:'
    return msg

def post_errors(errors, base, api_key, sha):
    url = base + '/commits/{sha}/comments?access_token={api_key}'.format(sha=sha,
                                                                         api_key=api_key)
    for fname, errors in errors.iteritems():
        msg = generate_buf(errors)
        data = {'body': msg,
                'path': fname,
                'position': 1,
                'line': None}
        headers = {}
        headers['Accept'] = 'application/json'
        requests.post(url, data=json.dumps(data), headers=headers)

def get_errors(lint_output):
    errors = {}
    for line in lint_output:
        if line:
            #  lib/deepy/jobs_daemon.py:7: 'foo' imported but unused
            fname, num, errstr = line.split(':')
            errors.setdefault(fname, [])
            errors[fname].append((num, errstr))
    return errors

def run_lint(path, files, lint='pyflakes', pattern='*.py'):
    failed = []
    output = []
    for fname in files:
        if not fnmatch.fnmatch(fname, pattern):
            continue
        try:
            subprocess.check_output([lint + " " + fname], shell=True, cwd=path)
        except subprocess.CalledProcessError as e:
            output += e.output.split('\n')
            failed.append(fname)
    return failed, output

def get_changed_files(api_key, repo_base, pr_num):
    '''
    Retrieve the list of changed files for a pull request
    '''
    "https://api.github.com/repos/deepfield/pipedream/statuses/$bamboo_pull_sha?access_token={api_key}"
    url = repo_base + "/pulls/{num}/files?access_token={api_key}".format(num=pr_num, api_key=api_key)
    req = requests.get(url)
    data = req.json()
    files = [v['filename'] for v in data]
    return files

def parse_args():
    p = argparse.ArgumentParser(description='''
    Get changed files from a pull-request and check for lint errors
    ''')
    p.add_argument('--pr-num', help='pull-request num', required=True)
    p.add_argument('--repo-base', help='repo-base-url', required=True)
    p.add_argument('--path', help='path to repo', required=True)
    p.add_argument('--gh-api-write', help='gh api key used to post comments/status', required=True)
    p.add_argument('--gh-api-read', help='gh api key used to read changed files (defaults to write if not specified)')
    p.add_argument('--sha', help='commit hash', required=True)
    return p.parse_args()

def main():
    args = parse_args()
    write_key = args.gh_api_write
    if args.gh_api_read:
        read_key = args.gh_api_read
    else:
        read_key = args.gh_api_write
    files = get_changed_files(read_key, args.repo_base, args.pr_num)
    failed, errors = run_lint(args.path, files)
    errors = get_errors(errors)
    create_or_update_lint_comment(args.repo_base, read_key,
                                  args.pr_num, errors)
    post_result(args.repo_base, failed, write_key, args.sha)

if __name__ == '__main__':
    main()
<commit_msg>remove most of the PEP8 violations<commit_after>#! /usr/bin/env python

import requests
import fnmatch
import subprocess
import argparse
import json

def get_header_string():
    ''' The string that we use to identify comments written by the linter '''
    buf = '''AUTOMATIC LINT RESULTS DO NOT EDIT\n'''
    return buf

def get_lint_comment(base, api_key, pr_num):
    '''
    Retrieves all comments on an issue from github and searches for a
    comment starting with the string returned by get_header_string()
    '''
    template = '/issues/{num}/comments?access_token={api_key}'
    url = base + template.format(num=pr_num, api_key=api_key)
    headers = {}
    headers['Accept'] = 'application/json'
    comment_id = None
    req = requests.get(url, headers=headers)
    for comment in req.json():
        if comment['body'].startswith(get_header_string()):
            comment_id = comment['id']
    return comment_id

def create_or_update_lint_comment(base, api_key, pr_num, errors):
    '''
    If we haven't already made a comment on a pull request then make
    a new one. Otherwise update that comment with the current error set.
    '''
    body = get_header_string() + '\n' + generate_buf(errors)
    comment_id = get_lint_comment(base, api_key, pr_num)
    data = {'body': body}
    if comment_id:
        template = '/issues/comments/{comment_id}?access_token={api_key}'
        url = base + template.format(num=pr_num,
                                     comment_id=comment_id, api_key=api_key)
        requests.patch(url, headers=get_headers(), data=json.dumps(data))
    else:
        template = '/issues/{num}/comments?access_token={api_key}'
        url = base + template.format(num=pr_num, api_key=api_key)
        requests.post(url, headers=get_headers(), data=json.dumps(data))

def get_headers():
    '''
    General set of headers used in requests to github
    '''
    return {'Accept': 'application/json'}

def post_result(base, failed_files, api_key, sha):
    template = '/statuses/{sha}?access_token={api_key}'
    url = base + template.format(sha=sha, api_key=api_key)
    if any(failed_files):
        status = 'failure'
        description = 'Lint failed'
        # Sad Panda
        link = 'http://fc08.deviantart.net/fs70/f/2010/149/a/7/Sad_Panda_Chibi_by_mongrelssister.png'
    else:
        status = 'success'
        description = 'Lint passed'
        link = 'http://i.imgur.com/DPVM1.png'
    data = {"state": status, "target_url": link,
            "description": description, "context": "lint"}
    headers = {}
    headers['Accept'] = 'application/json'
    requests.post(url, data=json.dumps(data), headers=headers)

def generate_buf(errors):
    if errors:
        msg = []
        for fname, errors in errors.iteritems():
            msg += ['Lint Errors for {}'.format(fname)]
            for error in errors:
                line_num, errstr = error
                msg.append('\t{}:\t{}'.format(line_num, errstr))
        msg = '\n'.join(msg)
    else:
        msg = 'Lint all good :shipit:'
    return msg

def post_errors(errors, base, api_key, sha):
    template = '/commits/{sha}/comments?access_token={api_key}'
    url = base + template.format(sha=sha, api_key=api_key)
    for fname, errors in errors.iteritems():
        msg = generate_buf(errors)
        data = {'body': msg,
                'path': fname,
                'position': 1,
                'line': None}
        headers = {}
        headers['Accept'] = 'application/json'
        requests.post(url, data=json.dumps(data), headers=headers)

def get_errors(lint_output):
    errors = {}
    for line in lint_output:
        if line:
            fname, num, errstr = line.split(':')
            errors.setdefault(fname, [])
            errors[fname].append((num, errstr))
    return errors

def run_lint(path, files, lint='pyflakes', pattern='*.py'):
    failed = []
    output = []
    for fname in files:
        if not fnmatch.fnmatch(fname, pattern):
            continue
        try:
            subprocess.check_output([lint + " " + fname], shell=True, cwd=path)
        except subprocess.CalledProcessError as e:
            output += e.output.split('\n')
            failed.append(fname)
    return failed, output

def get_changed_files(api_key, repo_base, pr_num):
    '''
    Retrieve the list of changed files for a pull request
    '''
    template = "/pulls/{num}/files?access_token={api_key}"
    url = repo_base + template.format(num=pr_num, api_key=api_key)
    req = requests.get(url)
    data = req.json()
    files = [v['filename'] for v in data]
    return files

def parse_args():
    p = argparse.ArgumentParser(description='''
    Get changed files from a pull-request and check for lint errors
    ''')
    p.add_argument('--pr-num', help='pull-request num', required=True)
    p.add_argument('--repo-base', help='repo-base-url', required=True)
    p.add_argument('--path', help='path to repo', required=True)
    p.add_argument('--gh-api-write',
                   help='gh api key used to post comments/status',
                   required=True)
    p.add_argument('--gh-api-read',
                   help='gh api key used to read changed files ' +
                        '(defaults to write if not specified)')
    p.add_argument('--sha', help='commit hash', required=True)
    return p.parse_args()

def main():
    args = parse_args()
    write_key = args.gh_api_write
    if args.gh_api_read:
        read_key = args.gh_api_read
    else:
        read_key = args.gh_api_write
    files = get_changed_files(read_key, args.repo_base, args.pr_num)
    failed, errors = run_lint(args.path, files)
    errors = get_errors(errors)
    create_or_update_lint_comment(args.repo_base, read_key,
                                  args.pr_num, errors)
    post_result(args.repo_base, failed, write_key, args.sha)

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