Esempio n. 1
0
def register_families_folder(folder_path: str):
    """Register all family class files contained in a directory.

    @param folder_path: The path of a folder containing family files.
        The families may also be inside a zip archive structure.
    @raises NotADirectoryError: folder_path is not a directory
    """
    suffix = '_family.py'
    if os.path.isdir(folder_path):
        for file_name in os.listdir(folder_path):
            if file_name.endswith(suffix):
                family_name = removesuffix(file_name, suffix)
                family_files[family_name] = os.path.join(
                    folder_path, file_name)
        return

    # probably there is a zip file chain (T278076)
    # find the parent zip folder
    path = Path(folder_path)
    if not is_zipfile(path):
        for path in path.parents:
            if is_zipfile(path):
                break
        else:
            raise NotADirectoryError('20', 'Not a directory', folder_path)

    # read the family files from zip folder
    # assume that all files ending with suffix reside in family folder
    zip_file = ZipFile(path)
    for file_name in zip_file.namelist():
        if file_name.endswith(suffix):
            file_path = Path(file_name)
            family_name = removesuffix(file_path.name, suffix)
            family_files[family_name] = os.path.join(folder_path,
                                                     file_path.name)
Esempio n. 2
0
def register_families_folder(folder_path: str,
                             not_exists_ok: bool = False) -> None:
    """Register all family class files contained in a directory.

    .. versionadded:: 7.0
       The *not_exists_ok* parameter

    :param folder_path: The path of a folder containing family files.
        The families may also be inside a zip archive structure.
    :param not_exists_ok: When true, ignore FileNotFoundError
    :raises FileNotFoundError: Family folder does not exist
    :raises NotADirectoryError: folder_path is not a directory
    """
    suffix = '_family.py'

    if not os.path.exists(folder_path):
        if not_exists_ok:
            return
        raise FileNotFoundError(
            'Family folder {!r} does not exist'.format(folder_path))

    if os.path.isdir(folder_path):
        for file_name in os.listdir(folder_path):
            if file_name.endswith(suffix):
                family_name = removesuffix(file_name, suffix)
                family_files[family_name] = os.path.join(
                    folder_path, file_name)
        return

    # probably there is a zip file chain (T278076)
    # find the parent zip folder
    path = Path(folder_path)
    if not is_zipfile(path):
        for path in path.parents:
            if is_zipfile(path):
                break
        else:
            raise NotADirectoryError('20', 'Not a directory', folder_path)

    # read the family files from zip folder
    # assume that all files ending with suffix reside in family folder
    zip_file = ZipFile(path)
    for file_name in zip_file.namelist():
        if file_name.endswith(suffix):
            file_path = Path(file_name)
            family_name = removesuffix(file_path.name, suffix)
            family_files[family_name] = os.path.join(folder_path,
                                                     file_path.name)
Esempio n. 3
0
def _code_fam_from_url(url: str, name: Optional[str] = None):
    """Set url to cache and get code and family from cache.

    Site helper method.
    @param url: The site URL to get code and family
    @param name: A family name used by AutoFamily
    """
    matched_sites = []
    # Iterate through all families and look, which does apply to
    # the given URL
    for fam in config.family_files:
        family = Family.load(fam)
        code = family.from_url(url)
        if code is not None:
            matched_sites.append((code, family))

    if not matched_sites:
        if not name:  # create a name from url
            name = urlparse(url).netloc.split('.')[-2]
            name = removesuffix(name, 'wiki')
        family = AutoFamily(name, url)
        matched_sites.append((family.code, family))

    if len(matched_sites) > 1:
        warning('Found multiple matches for URL "{}": {} (use first)'.format(
            url, ', '.join(str(s) for s in matched_sites)))
    return matched_sites[0]
Esempio n. 4
0
def register_families_folder(folder_path):
    """Register all family class files contained in a directory."""
    suffix = '_family.py'
    for file_name in os.listdir(folder_path):
        if file_name.endswith(suffix):
            family_name = removesuffix(file_name, suffix)
            family_files[family_name] = os.path.join(folder_path, file_name)
Esempio n. 5
0
def mysql_query(query: str, params=None,
                dbname: Optional[str] = None,
                verbose: Optional[bool] = None):
    """Yield rows from a MySQL query.

    An example query that yields all ns0 pages might look like::

        SELECT
         page_namespace,
         page_title,
        FROM page
        WHERE page_namespace = 0;

    Supported MediaWiki projects use Unicode (UTF-8) character encoding.
    Cursor charset is utf8.

    :param query: MySQL query to execute
    :param params: input parameters for the query, if needed
        if list or tuple, %s shall be used as placeholder in the query string.
        if a dict, %(key)s shall be used as placeholder in the query string.
    :type params: tuple, list or dict of str
    :param dbname: db name
    :param verbose: if True, print query to be executed;
        if None, config.verbose_output will be used.
    :return: generator which yield tuples
    """
    # These are specified in config.py or user-config.py
    if verbose is None:
        verbose = config.verbose_output

    if config.db_connect_file is None:
        credentials = {'user': config.db_username,
                       'password': config.db_password}
    else:
        credentials = {'read_default_file': config.db_connect_file}

    pymysql_version = pkg_resources.parse_version(
        removesuffix(pymysql.__version__, '.None'))
    args = {
        'host': config.db_hostname_format.format(dbname),
        'database': config.db_name_format.format(dbname),
        'port': config.db_port,
        'charset': 'utf8',
        'defer_connect': query == 'test',  # for tests
    }

    if pymysql_version < pkg_resources.parse_version('0.7.11'):
        issue_deprecation_warning(
            'pymysql package release {}'.format(pymysql_version),
            instead='pymysql >= 0.7.11', since='7.0.0')
        connection = _OldConnection(**args, **credentials)
    else:
        connection = pymysql.connect(**args, **credentials)

    if pymysql_version < pkg_resources.parse_version('1.0.0'):
        from contextlib import closing
        connection = closing(connection)

    with connection as conn, conn.cursor() as cursor:
        if verbose:
            _query = cursor.mogrify(query, params)

            if not isinstance(_query, str):
                _query = str(_query, encoding='utf-8')
            _query = _query.strip()
            _query = '\n'.join('    {}'.format(line)
                               for line in _query.splitlines())
            pywikibot.output('Executing query:\n' + _query)

        if query == 'test':  # for tests only
            yield query

        cursor.execute(query, params)
        yield from cursor