diff --git a/docs/build/html/.buildinfo b/docs/build/html/.buildinfo deleted file mode 100644 index 11e5427..0000000 --- a/docs/build/html/.buildinfo +++ /dev/null @@ -1,4 +0,0 @@ -# Sphinx build info version 1 -# This file records the configuration used when building these files. When it is not found, a full rebuild will be done. -config: 5f692cdea773b403afcc7068483ecb67 -tags: 645f666f9bcd5a90fca523b33c5a78b7 diff --git a/docs/build/html/.doctrees/advanced_usage.doctree b/docs/build/html/.doctrees/advanced_usage.doctree deleted file mode 100644 index d0ea96a..0000000 Binary files a/docs/build/html/.doctrees/advanced_usage.doctree and /dev/null differ diff --git a/docs/build/html/.doctrees/api.doctree b/docs/build/html/.doctrees/api.doctree deleted file mode 100644 index d6c0590..0000000 Binary files a/docs/build/html/.doctrees/api.doctree and /dev/null differ diff --git a/docs/build/html/.doctrees/configuration.doctree b/docs/build/html/.doctrees/configuration.doctree deleted file mode 100644 index 7bd42dc..0000000 Binary files a/docs/build/html/.doctrees/configuration.doctree and /dev/null differ diff --git a/docs/build/html/.doctrees/environment.pickle b/docs/build/html/.doctrees/environment.pickle deleted file mode 100644 index 33b1262..0000000 Binary files a/docs/build/html/.doctrees/environment.pickle and /dev/null differ diff --git a/docs/build/html/.doctrees/examples.doctree b/docs/build/html/.doctrees/examples.doctree deleted file mode 100644 index c74edaa..0000000 Binary files a/docs/build/html/.doctrees/examples.doctree and /dev/null differ diff --git a/docs/build/html/.doctrees/formats.doctree b/docs/build/html/.doctrees/formats.doctree deleted file mode 100644 index 54c5ad1..0000000 Binary files a/docs/build/html/.doctrees/formats.doctree and /dev/null differ diff --git a/docs/build/html/.doctrees/index.doctree b/docs/build/html/.doctrees/index.doctree deleted file mode 100644 index a9480cf..0000000 Binary files a/docs/build/html/.doctrees/index.doctree and /dev/null differ diff --git a/docs/build/html/.doctrees/installation.doctree b/docs/build/html/.doctrees/installation.doctree deleted file mode 100644 index 052e4ba..0000000 Binary files a/docs/build/html/.doctrees/installation.doctree and /dev/null differ diff --git a/docs/build/html/.doctrees/quickstart.doctree b/docs/build/html/.doctrees/quickstart.doctree deleted file mode 100644 index dd611b1..0000000 Binary files a/docs/build/html/.doctrees/quickstart.doctree and /dev/null differ diff --git a/docs/build/html/_modules/atio/core.html b/docs/build/html/_modules/atio/core.html deleted file mode 100644 index 210fbdd..0000000 --- a/docs/build/html/_modules/atio/core.html +++ /dev/null @@ -1,600 +0,0 @@ - - - - - - - - atio.core — Atio 2.0.0 문서 - - - - - - - - - - - - - - - - -
- - -
- -
-
-
- -
-
-
-
- -

atio.core의 소스 코드

-"""progress 적용 후 write 함수"""
-import os
-import tempfile
-import threading
-import time
-import numpy as np
-from queue import Queue
-from .plugins import get_writer
-from .utils import setup_logger, ProgressBar
-
-
-[문서] -def write(obj, target_path=None, format=None, show_progress=False, verbose=False, **kwargs): - """ - 데이터 객체(obj)를 안전하게 target_path 또는 데이터베이스에 저장합니다. - - - 파일 기반 쓰기 (format: 'csv', 'parquet', 'excel' 등): - - target_path (str): 필수. 데이터가 저장될 파일 경로입니다. - - 롤백 기능이 있는 원자적 쓰기를 수행합니다. - - - 데이터베이스 기반 쓰기 (format: 'sql', 'database'): - - target_path: 사용되지 않습니다. - - kwargs (dict): 데이터베이스 쓰기에 필요한 추가 인자들입니다. - - pandas.to_sql: 'name'(테이블명), 'con'(커넥션 객체)가 필수입니다. - - polars.write_database: 'table_name', 'connection_uri'가 필수입니다. - - Args: - obj: 저장할 데이터 객체 (e.g., pandas.DataFrame, polars.DataFrame, np.ndarray). - target_path (str, optional): 파일 저장 경로. 파일 기반 쓰기 시 필수. Defaults to None. - format (str, optional): 저장할 포맷. Defaults to None. - show_progress (bool): 진행도 표시 여부. Defaults to False. - verbose (bool): 상세한 성능 진단 정보 출력 여부. Defaults to False. - **kwargs: 각 쓰기 함수에 전달될 추가 키워드 인자. - """ - logger = setup_logger(debug_level=verbose) - t0 = time.perf_counter() - - # --- 1. 데이터베이스 쓰기 특별 처리 --- - # 데이터베이스 쓰기는 파일 경로 기반의 원자적 쓰기 로직을 따르지 않습니다. - if format in ('sql', 'database'): - logger.info(f"데이터베이스 쓰기 모드 시작 (format: {format})") - writer_method_name = get_writer(obj, format) - - if writer_method_name is None: - err_msg = f"객체 타입 {type(obj).__name__}에 대해 지원하지 않는 format: {format}" - logger.error(err_msg) - raise ValueError(err_msg) - - try: - writer_func = getattr(obj, writer_method_name) - - # 각 데이터베이스 쓰기 함수에 필요한 필수 인자 확인 - if format == 'sql': # Pandas - if 'name' not in kwargs or 'con' not in kwargs: - raise ValueError("'name'(테이블명)과 'con'(DB 커넥션) 인자는 'sql' 포맷에 필수입니다.") - elif format == 'database': # Polars - if 'table_name' not in kwargs or 'connection_uri' not in kwargs: - raise ValueError("'table_name'과 'connection_uri' 인자는 'database' 포맷에 필수입니다.") - - # target_path는 무시하고 **kwargs로 받은 인자들을 사용하여 DB에 직접 씁니다. - writer_func(**kwargs) - - t_end = time.perf_counter() - logger.info(f"✅ 데이터베이스 쓰기 완료 (총 소요 시간: {t_end - t0:.4f}s)") - return # DB 쓰기 완료 후 함수 종료 - - except Exception as e: - t_err = time.perf_counter() - logger.error(f"데이터베이스 쓰기 중 예외 발생: {e}") - logger.info(f"데이터베이스 쓰기 실패 (소요 시간: {t_err - t0:.4f}s, 에러: {type(e).__name__})") - raise e - - # --- 2. 파일 기반 원자적 쓰기 --- - if target_path is None: - raise ValueError("파일 기반 쓰기(예: 'csv', 'parquet')에는 'target_path' 인자가 필수입니다.") - - dir_name = os.path.dirname(os.path.abspath(target_path)) - base_name = os.path.basename(target_path) - os.makedirs(dir_name, exist_ok=True) - - # 롤백을 위한 백업 경로 설정 - backup_path = target_path + "._backup" - original_exists = os.path.exists(target_path) - - with tempfile.TemporaryDirectory(dir=dir_name) as tmpdir: - tmp_path = os.path.join(tmpdir, base_name) - logger.info(f"임시 디렉토리 생성: {tmpdir}") - logger.info(f"임시 파일 경로: {tmp_path}") - - t1 = time.perf_counter() - - writer = get_writer(obj, format) - if writer is None: - logger.error(f"지원하지 않는 format: {format}") - if verbose: - logger.debug(f"Atomic write step timings (FAILED at setup): " - f"setup={t1-t0:.4f}s, total={time.perf_counter()-t0:.4f}s") - logger.info(f"Atomic write failed at setup stage (took {time.perf_counter()-t0:.4f}s)") - raise ValueError(f"지원하지 않는 format: {format}") - logger.info(f"사용할 writer: {writer} (format: {format})") - - try: - if not show_progress: - _execute_write(writer, obj, tmp_path, **kwargs) - else: - _execute_write_with_progress(writer, obj, tmp_path, **kwargs) - - t2 = time.perf_counter() - logger.info(f"데이터 임시 파일에 저장 완료: {tmp_path}") - - except Exception as e: - # 쓰기 실패 시에는 롤백할 필요가 없음 (원본 파일은 그대로 있음) - t_error = time.perf_counter() - logger.error(f"임시 파일 저장 중 예외 발생: {e}") - if verbose: - logger.debug(f"Atomic write step timings (ERROR during write): " - f"setup={t1-t0:.4f}s, write_call={t_error-t1:.4f}s (실패), " - f"total={t_error-t0:.4f}s, error_type={type(e).__name__}") - logger.info(f"Atomic write failed during write stage (took {t_error-t0:.4f}s, error: {type(e).__name__})") - raise e - - # [롤백 STEP 1] 기존 파일 백업 - if original_exists: - logger.info(f"기존 파일 백업: {target_path} -> {backup_path}") - try: - # rename은 atomic 연산이므로 백업 과정도 안전합니다. - os.rename(target_path, backup_path) - except Exception as e: - logger.error(f"백업 생성 실패. 작업을 중단합니다: {e}") - # 백업 실패 시 더 이상 진행하면 안 되므로 예외를 발생시킵니다. - raise IOError(f"Failed to create backup for {target_path}") from e - - try: - # [롤백 STEP 2] 원자적 교체 - os.replace(tmp_path, target_path) - t3 = time.perf_counter() - logger.info(f"원자적 교체 완료: {tmp_path} -> {target_path}") - - # [롤백 STEP 3] _SUCCESS 플래그 생성 - success_path = os.path.join(os.path.dirname(target_path), f".{os.path.basename(target_path)}._SUCCESS") - with open(success_path, "w") as f: - f.write("OK\n") - t4 = time.perf_counter() - logger.info(f"_SUCCESS 플래그 파일 생성: {success_path}") - - # [롤백 STEP 4] 성공 시 백업 파일 삭제 - if original_exists: - os.remove(backup_path) - logger.info(f"작업 성공, 백업 파일 삭제 완료: {backup_path}") - - if verbose: - logger.debug(f"Atomic write step timings (SUCCESS): " - f"setup={t1-t0:.4f}s, write_call={t2-t1:.4f}s, " - f"replace={t3-t2:.4f}s, success_flag={t4-t3:.4f}s, " - f"total={t4-t0:.4f}s") - logger.info(f"✅ Atomic write completed successfully (took {t4-t0:.4f}s)") - - except Exception as e: - # [롤백 STEP 5] 교체 또는 플래그 생성 실패 시 롤백 실행 - t_final_error = time.perf_counter() - logger.error(f"최종 저장 단계에서 오류 발생. 롤백을 시작합니다. 원인: {e}") - - if original_exists: - try: - # 새로 쓴 불완전한 파일이 있다면 삭제 - if os.path.exists(target_path): - os.remove(target_path) - - # 백업해둔 원본 파일을 다시 복구 - os.rename(backup_path, target_path) - logger.info(f"롤백 성공: 원본 파일 복구 완료 ({backup_path} -> {target_path})") - - except Exception as rollback_e: - logger.critical(f"치명적 오류: 롤백 실패! {rollback_e}") - logger.critical(f"시스템이 불안정한 상태일 수 있습니다. 수동 확인이 필요합니다.") - logger.critical(f"남아있는 파일: (새 데이터) {target_path}, (원본 백업) {backup_path}") - - if verbose: - logger.debug(f"Atomic write step timings (FAILED AND ROLLED BACK): " - f"setup={t1-t0:.4f}s, write_call={t2-t1:.4f}s, " - f"final_stage_fail_time={t_final_error-t2:.4f}s, " - f"total={t_final_error-t0:.4f}s, error_type={type(e).__name__}") - logger.info(f"Atomic write failed and rolled back (took {t_final_error-t0:.4f}s, error: {type(e).__name__})") - - # 원본 예외를 다시 발생시켜 사용자에게 알립니다. - raise e
- - -def _execute_write(writer, obj, path, **kwargs): - """ - 내부 쓰기 실행 함수. 핸들러 타입에 따라 분기하여 실제 쓰기 작업을 수행합니다. - - callable(writer): `np.save`와 같은 함수 핸들러 - - str(writer): `to_csv`와 같은 객체의 메소드 핸들러 - """ - # 1. writer가 호출 가능한 '함수'인 경우 (e.g., np.save, np.savetxt) - if callable(writer): - # 1a. np.savez, np.savez_compressed 특별 처리: 여러 배열을 dict로 받아 저장 - if writer in (np.savez, np.savez_compressed): - if not isinstance(obj, dict): - raise TypeError( - f"'{writer.__name__}'로 여러 배열을 저장하려면, " - f"데이터 객체는 dict 타입이어야 합니다. (현재: {type(obj).__name__})" - ) - writer(path, **obj) - # 1b. 그 외 일반적인 함수 핸들러 처리 - else: - writer(path, obj, **kwargs) - - # 2. writer가 '메소드 이름(문자열)'인 경우 (e.g., 'to_csv', 'to_excel') - # 이 경우, obj.to_csv(path, **kwargs) 와 같이 호출됩니다. - else: - getattr(obj, writer)(path, **kwargs) - -def _execute_write_with_progress(writer, obj, path, **kwargs): - """멀티스레딩으로 쓰기 작업과 진행도 표시를 함께 실행하는 내부 함수""" - stop_event = threading.Event() - exception_queue = Queue() - - # 실제 쓰기 작업을 수행할 '작업 스레드'의 목표 함수 - def worker_task(): - try: - _execute_write(writer, obj, path, **kwargs) - except Exception as e: - exception_queue.put(e) - - # 스레드 생성 - worker_thread = threading.Thread(target=worker_task) - progress_bar = ProgressBar(filepath=path, stop_event=stop_event, description="Writing") - monitor_thread = threading.Thread(target=progress_bar.run) - - # 스레드 시작 - worker_thread.start() - monitor_thread.start() - - # 작업 스레드가 끝날 때까지 대기 - worker_thread.join() - - # 모니터 스레드에 중지 신호 전송 및 종료 대기 - stop_event.set() - monitor_thread.join() - - # 작업 스레드에서 예외가 발생했는지 확인하고, 있었다면 다시 발생시킴 - if not exception_queue.empty(): - raise exception_queue.get_nowait() - -import uuid -from .utils import read_json, write_json - -
-[문서] -def write_snapshot(obj, table_path, mode='overwrite', format='parquet', **kwargs): - logger = setup_logger(debug_level=False) - - # 1. 경로 설정 및 폴더 생성 - os.makedirs(os.path.join(table_path, 'data'), exist_ok=True) - os.makedirs(os.path.join(table_path, 'metadata'), exist_ok=True) - - # 2. 현재 버전 확인 - pointer_path = os.path.join(table_path, '_current_version.json') - current_version = 0 - if os.path.exists(pointer_path): - current_version = read_json(pointer_path)['version_id'] - new_version = current_version + 1 - - # 3. 임시 디렉토리 내에서 모든 작업 수행 - with tempfile.TemporaryDirectory() as tmpdir: - # 3a. 새 데이터 파일 쓰기 - writer = get_writer(obj, format) - data_filename = f"{uuid.uuid4()}.{format}" - tmp_data_path = os.path.join(tmpdir, data_filename) - _execute_write(writer, obj, tmp_data_path, **kwargs) - - # 3. 임시 디렉토리 내에서 모든 작업 수행 - with tempfile.TemporaryDirectory() as tmpdir: - # 3a. 새 데이터 파일 쓰기 - writer = get_writer(obj, format) - if writer is None: - raise ValueError(f"지원하지 않는 format: {format} for object type {type(obj)}") - - data_filename = f"{uuid.uuid4()}.{format}" - tmp_data_path = os.path.join(tmpdir, data_filename) - _execute_write(writer, obj, tmp_data_path, **kwargs) - - # 3b. 새 manifest 생성 - new_manifest = { - 'files': [{'path': os.path.join('data', data_filename), 'format': format}] - } - manifest_filename = f"manifest-{uuid.uuid4()}.json" - write_json(new_manifest, os.path.join(tmpdir, manifest_filename)) - - # 3c. 새 snapshot 생성을 위한 준비 - all_manifests = [os.path.join('metadata', manifest_filename)] - - if mode.lower() == 'append' and current_version > 0: - try: - prev_metadata_path = os.path.join(table_path, 'metadata', f'v{current_version}.metadata.json') - prev_metadata = read_json(prev_metadata_path) - prev_snapshot_filename = prev_metadata['snapshot_filename'] - - prev_snapshot_path = os.path.join(table_path, prev_snapshot_filename) - prev_snapshot = read_json(prev_snapshot_path) - existing_manifests = prev_snapshot['manifests'] - - all_manifests.extend(existing_manifests) - except (FileNotFoundError, KeyError): - logger.warning(f"Append mode: 이전 버전(v{current_version})의 메타데이터를 찾을 수 없거나 형식이 올바르지 않습니다. Overwrite 모드로 동작합니다.") - - # 3d. 최종 manifest 목록으로 새 snapshot 생성 - snapshot_id = int(time.time()) - snapshot_filename = f"snapshot-{snapshot_id}-{uuid.uuid4()}.json" - - new_snapshot = { - 'snapshot_id': snapshot_id, - 'timestamp': time.time(), - 'manifests': all_manifests - } - write_json(new_snapshot, os.path.join(tmpdir, snapshot_filename)) - - # 3e. 새 version metadata 생성 - new_metadata = { - 'version_id': new_version, - 'snapshot_id': snapshot_id, - 'snapshot_filename': os.path.join('metadata', snapshot_filename) - } - metadata_filename = f"v{new_version}.metadata.json" - write_json(new_metadata, os.path.join(tmpdir, metadata_filename)) - - # 3f. 새 포인터 파일 생성 - new_pointer = {'version_id': new_version} - tmp_pointer_path = os.path.join(tmpdir, '_current_version.json') - write_json(new_pointer, tmp_pointer_path) - - # 4. 최종 커밋 - os.rename(tmp_data_path, os.path.join(table_path, 'data', data_filename)) - os.rename(os.path.join(tmpdir, manifest_filename), os.path.join(table_path, 'metadata', manifest_filename)) - os.rename(os.path.join(tmpdir, snapshot_filename), os.path.join(table_path, 'metadata', snapshot_filename)) - os.rename(os.path.join(tmpdir, metadata_filename), os.path.join(table_path, 'metadata', metadata_filename)) - os.replace(tmp_pointer_path, pointer_path) - logger.info(f"스냅샷 쓰기 완료! '{table_path}'가 버전 {new_version}으로 업데이트되었습니다.")
- - - - -
-[문서] -def read_table(table_path, version=None, output_as='pandas'): - # 1. 읽을 버전 결정 및 진입점(metadata.json) 찾기 - pointer_path = os.path.join(table_path, '_current_version.json') - if version is None: - version_id = read_json(pointer_path)['version_id'] - else: - version_id = version - - metadata_path = os.path.join(table_path, 'metadata', f'v{version_id}.metadata.json') - metadata = read_json(metadata_path) - snapshot_filepath = metadata['snapshot_filename'] - - # 2. metadata -> snapshot -> manifest 순으로 파싱 - snapshot_path = os.path.join(table_path, snapshot_filepath) # 정확한 경로 사용 - snapshot = read_json(snapshot_path) - - # 3. 모든 manifest를 읽어 최종 데이터 파일 목록 취합 - all_data_files = [] - for manifest_ref in snapshot['manifests']: - manifest_path = os.path.join(table_path, manifest_ref) - manifest = read_json(manifest_path) - for file_info in manifest['files']: - # file_info 에는 path, format 등의 정보가 있음 - all_data_files.append(os.path.join(table_path, file_info['path'])) - - # 4. output_as 옵션에 따라 최종 데이터 객체 생성 - if not all_data_files: - # 데이터가 없는 경우 처리 - return None # 또는 빈 DataFrame - - if output_as == 'pandas': - import pandas as pd - return pd.read_parquet(all_data_files) - elif output_as == 'polars': - import polars as pl - return pl.read_parquet(all_data_files) - # NumPy 등의 다른 형식 처리 로직 추가 - - raise ValueError(f"지원하지 않는 출력 형식: {output_as}")
- - - -from datetime import datetime, timedelta - -
-[문서] -def expire_snapshots(table_path, keep_for=timedelta(days=7), dry_run=True): - """ - 설정된 보관 기간(keep_for)보다 오래된 스냅샷과 - 더 이상 참조되지 않는 데이터 파일을 삭제합니다. - """ - logger = setup_logger() - now = datetime.now() - metadata_dir = os.path.join(table_path, 'metadata') - - if not os.path.isdir(metadata_dir): - logger.info("정리할 테이블이 없거나 메타데이터 폴더를 찾을 수 없습니다.") - return - - # --- 1. 모든 메타데이터 정보와 파일명 수집 --- - all_versions_meta = {} # version_id -> version_meta - all_snapshots_meta = {} # snapshot_id -> snapshot_meta - all_manifest_paths = set() # 모든 manifest 파일 경로 - - for filename in os.listdir(metadata_dir): - path = os.path.join(metadata_dir, filename) - if filename.startswith('v') and filename.endswith('.metadata.json'): - meta = read_json(path) - all_versions_meta[meta['version_id']] = meta - elif filename.startswith('snapshot-'): - snap = read_json(path) - all_snapshots_meta[snap['snapshot_id']] = snap - elif filename.startswith('manifest-'): - all_manifest_paths.add(os.path.join('metadata', filename)) - - # --- 2. "살아있는" 객체 식별 --- - live_snapshot_ids = set() - live_manifests = set() - live_data_files = set() - - # 현재 버전을 포함하여 보관 기간 내의 모든 버전을 "살아있는" 것으로 간주 - for version_meta in all_versions_meta.values(): - snapshot_id = version_meta['snapshot_id'] - snapshot = all_snapshots_meta.get(snapshot_id) - - if snapshot and (now - datetime.fromtimestamp(snapshot['timestamp'])) < keep_for: - live_snapshot_ids.add(snapshot_id) - for manifest_ref in snapshot.get('manifests', []): - live_manifests.add(manifest_ref) - manifest_path = os.path.join(table_path, manifest_ref) - if os.path.exists(manifest_path): - manifest_data = read_json(manifest_path) - for file_info in manifest_data.get('files', []): - live_data_files.add(file_info['path']) - - # --- 3. 삭제할 "고아" 객체 식별 --- - files_to_delete = [] - - # 고아 데이터 파일 찾기 - data_dir = os.path.join(table_path, 'data') - if os.path.isdir(data_dir): - for data_file in os.listdir(data_dir): - relative_path = os.path.join('data', data_file) - if relative_path not in live_data_files: - files_to_delete.append(os.path.join(table_path, relative_path)) - - # 고아 매니페스트 파일 찾기 - manifests_to_delete = all_manifest_paths - live_manifests - for manifest_path in manifests_to_delete: - files_to_delete.append(os.path.join(table_path, manifest_path)) - - # 고아 스냅샷 및 버전 메타데이터 파일 찾기 - for version_id, version_meta in all_versions_meta.items(): - snapshot_id = version_meta['snapshot_id'] - if snapshot_id not in live_snapshot_ids: - # vX.metadata.json 파일 삭제 대상 추가 - files_to_delete.append(os.path.join(metadata_dir, f"v{version_id}.metadata.json")) - # snapshot-X.json 파일 삭제 대상 추가 - snapshot_filename = version_meta.get('snapshot_filename') # 이전 단계에서 이 키를 추가했었음 - if snapshot_filename: - files_to_delete.append(os.path.join(table_path, snapshot_filename)) - - # 중복 제거 - files_to_delete = sorted(list(set(files_to_delete))) - - # --- 4. 최종 삭제 실행 --- - if not files_to_delete: - logger.info("삭제할 오래된 파일이 없습니다.") - return - - logger.info(f"총 {len(files_to_delete)}개의 오래된 파일을 찾았습니다.") - if dry_run: - logger.info("[Dry Run] 아래 파일들이 삭제될 예정입니다:") - for f in files_to_delete: - print(f" - {f}") - else: - logger.info("오래된 파일들을 삭제합니다...") - for f in files_to_delete: - try: - os.remove(f) - logger.debug(f" - 삭제됨: {f}") - except OSError as e: - logger.error(f" - 삭제 실패: {f}, 오류: {e}") - logger.info("삭제 작업이 완료되었습니다.")
- -
- -
-
- -
-
-
-
- - - - \ No newline at end of file diff --git a/docs/build/html/_modules/atio/plugins.html b/docs/build/html/_modules/atio/plugins.html deleted file mode 100644 index c45d8a7..0000000 --- a/docs/build/html/_modules/atio/plugins.html +++ /dev/null @@ -1,229 +0,0 @@ - - - - - - - - atio.plugins — Atio 2.0.0 문서 - - - - - - - - - - - - - - - - -
- - -
- -
-
-
- -
-
-
-
- -

atio.plugins의 소스 코드

-from .utils import setup_logger
-# 추후 Pandas, Polars, Numpy 등 확장 지원을 위한 플러그인 구조
-
-logger = setup_logger()
-
-# { 객체 타입: { 포맷: 핸들러 } }
-# 핸들러는 '메소드 이름(str)' 또는 '호출 가능한 함수'가 될 수 있습니다.
-WRITER_MAPPING = {}
-
-
-[문서] -def register_writer(obj_type, fmt, handler): - """(객체 타입, 포맷) 쌍으로 쓰기 핸들러를 등록""" - if obj_type not in WRITER_MAPPING: - WRITER_MAPPING[obj_type] = {} - WRITER_MAPPING[obj_type][fmt] = handler - logger.debug(f"Writer registered: type={obj_type.__name__}, format={fmt}, handler={handler}")
- - -
-[문서] -def get_writer(obj, fmt): - """객체의 타입과 포맷에 맞는 핸들러를 조회""" - obj_type = type(obj) - handler = WRITER_MAPPING.get(obj_type, {}).get(fmt) - if handler is None: - logger.warning(f"No writer found for type {obj_type.__name__} and format '{fmt}'") - return handler
- - -# --------------------------------------------------------------------------- -# 1. Pandas 쓰기 방법 등록 -# --------------------------------------------------------------------------- -try: - import pandas as pd - - PANDAS_DF_TYPE = pd.DataFrame - - # Pandas DataFrame에 대한 쓰기 핸들러 등록 - # 값은 DataFrame 객체의 메소드 이름(문자열)입니다. - # 예: format='csv' -> df.to_csv(...) 호출 - register_writer(PANDAS_DF_TYPE, "csv", "to_csv") - register_writer(PANDAS_DF_TYPE, "parquet", "to_parquet") - register_writer(PANDAS_DF_TYPE, "json", "to_json") - register_writer(PANDAS_DF_TYPE, "pickle", "to_pickle") - register_writer(PANDAS_DF_TYPE, "html", "to_html") - - # Excel 쓰기. `openpyxl` 라이브러리가 필요합니다. - # pip install openpyxl - register_writer(PANDAS_DF_TYPE, "excel", "to_excel") - - # SQL 쓰기. `sqlalchemy` 라이브러리가 필요합니다. - # 이 핸들러는 core.py에서 특별 처리됩니다 (파일 시스템을 사용하지 않음). - # pip install sqlalchemy - register_writer(PANDAS_DF_TYPE, "sql", "to_sql") - - logger.info("Pandas writers registered successfully.") - -except ImportError: - logger.info("Pandas not found. Skipping pandas writer registration.") - pass - -# --------------------------------------------------------------------------- -# 2. Polars 쓰기 방법 등록 -# --------------------------------------------------------------------------- -try: - import polars as pl - - POLARS_DF_TYPE = pl.DataFrame - - # Polars DataFrame에 대한 쓰기 핸들러 등록 - register_writer(POLARS_DF_TYPE, "csv", "write_csv") - register_writer(POLARS_DF_TYPE, "parquet", "write_parquet") - register_writer(POLARS_DF_TYPE, "json", "write_json") - register_writer(POLARS_DF_TYPE, "ipc", "write_ipc") - register_writer(POLARS_DF_TYPE, "avro", "write_avro") - - # Polars Excel 쓰기. `xlsx2csv`와 `openpyxl`이 필요할 수 있습니다. - # pip install xlsx2csv openpyxl - register_writer(POLARS_DF_TYPE, "excel", "write_excel") - - # Polars 데이터베이스 쓰기. connector-x 가 필요합니다. - # pip install connectorx - # 이 핸들러는 core.py에서 특별 처리됩니다. - register_writer(POLARS_DF_TYPE, "database", "write_database") - - logger.info("Polars writers registered successfully.") - -except ImportError: - logger.info("Polars not found. Skipping polars writer registration.") - pass - -# --------------------------------------------------------------------------- -# 3. NumPy 쓰기 방법 등록 -# --------------------------------------------------------------------------- -try: - import numpy as np - - NUMPY_NDARRAY_TYPE = np.ndarray - - # NumPy는 저장 방식이 메소드와 함수가 섞여있어 구분이 중요합니다. - # 값: 실제 '함수 객체' (호출 방식: np.save(path, arr)) - register_writer(NUMPY_NDARRAY_TYPE, "npy", np.save) - register_writer(NUMPY_NDARRAY_TYPE, "npz", np.savez) - register_writer(NUMPY_NDARRAY_TYPE, "npz_compressed", np.savez_compressed) - register_writer(NUMPY_NDARRAY_TYPE, "csv", np.savetxt) - - # 값: '메소드 이름(문자열)' (호출 방식: arr.tofile(path)) - register_writer(NUMPY_NDARRAY_TYPE, "bin", "tofile") - - # 여러 배열을 한 번에 저장하기 위해 dict 타입도 지원 - register_writer(dict, "npz", np.savez) - register_writer(dict, "npz_compressed", np.savez_compressed) - - logger.info("NumPy writers registered successfully.") - -except ImportError: - logger.info("NumPy not found. Skipping numpy writer registration.") - pass -
- -
-
- -
-
-
-
- - - - \ No newline at end of file diff --git a/docs/build/html/_modules/atio/utils.html b/docs/build/html/_modules/atio/utils.html deleted file mode 100644 index cc30da0..0000000 --- a/docs/build/html/_modules/atio/utils.html +++ /dev/null @@ -1,248 +0,0 @@ - - - - - - - - atio.utils — Atio 2.0.0 문서 - - - - - - - - - - - - - - - - -
- - -
- -
-
-
- -
-
-
-
- -

atio.utils의 소스 코드

-import logging
-import os
-
-
-
-[문서] -def setup_logger(name="atio", debug_level=False): - logger = logging.getLogger(name) - if not logger.handlers: - handler = logging.StreamHandler() - formatter = logging.Formatter("[%(levelname)s] %(message)s") - handler.setFormatter(formatter) - logger.addHandler(handler) - - # debug_level이 True이면 DEBUG 레벨로 설정, 아니면 INFO 레벨 - if debug_level: - logger.setLevel(logging.DEBUG) - else: - logger.setLevel(logging.INFO) - - return logger
- - - -
-[문서] -def check_file_exists(path): - return os.path.exists(path)
- - - -import time -import threading - - -
-[문서] -class ProgressBar: - """ - 파일 쓰기 진행 상황을 콘솔에 표시하는 클래스. - 스피너, 처리된 용량, 처리 속도, 경과 시간을 표시합니다. - """ - -
-[문서] - def __init__(self, filepath: str, stop_event: threading.Event, description: str = "Writing"): - self.filepath = filepath - self.stop_event = stop_event - self.description = description - - self.spinner_chars = "⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏" - self.start_time = time.time()
- - - def _format_size(self, size_bytes: int) -> str: - """바이트를 KB, MB, GB 등 읽기 좋은 형태로 변환합니다.""" - if size_bytes < 1024: - return f"{size_bytes} B" - elif size_bytes < 1024**2: - return f"{size_bytes/1024:.1f} KB" - elif size_bytes < 1024**3: - return f"{size_bytes/1024**2:.1f} MB" - else: - return f"{size_bytes/1024**3:.1f} GB" - -
-[문서] - def run(self): - """ - 진행도 막대를 실행하는 메인 루프. - 이 함수가 모니터링 스레드에서 실행됩니다. - """ - spinner_index = 0 - while not self.stop_event.is_set(): - spinner_char = self.spinner_chars[spinner_index % len(self.spinner_chars)] - - try: - current_size = os.path.getsize(self.filepath) - except FileNotFoundError: - current_size = 0 - - elapsed_time = time.time() - self.start_time - - # 0으로 나누기 방지 - speed = current_size / elapsed_time if elapsed_time > 0 else 0 - - # 시간 포맷팅 (MM:SS) - mins, secs = divmod(int(elapsed_time), 60) - time_str = f"{mins:02d}:{secs:02d}" - - # 최종 출력 문자열 생성 - progress_line = ( - f"\r{spinner_char} {self.description} {os.path.basename(self.filepath)}... " - f"[ {self._format_size(current_size)} | {self._format_size(speed)}/s | {time_str} ]" - ) - - # 콘솔에 한 줄 출력 (덮어쓰기) - print(progress_line, end="", flush=True) - - spinner_index += 1 - time.sleep(0.1) # 0.1초마다 업데이트하여 CPU 사용 최소화 - - # 루프가 끝나면 마지막 완료 메시지를 출력 - self._finish()
- - - def _finish(self): - """작업 완료 후 깔끔한 최종 메시지를 출력합니다.""" - final_size = os.path.getsize(self.filepath) - elapsed_time = time.time() - self.start_time - time_str = f"{int(elapsed_time)}s" - - # 기존 줄을 지우기 위해 공백으로 덮어씁니다. - clear_line = "\r" + " " * 80 + "\r" - - finish_message = ( - f"✔︎ Finished {self.description} {os.path.basename(self.filepath)}. " - f"({self._format_size(final_size)} in {time_str})" - ) - print(clear_line + finish_message, flush=True)
- - - -import json - -
-[문서] -def read_json(path: str): - with open(path, 'r', encoding='utf-8') as f: - return json.load(f)
- - -
-[문서] -def write_json(data: dict, path: str): - with open(path, 'w', encoding='utf-8') as f: - json.dump(data, f, indent=4)
- -
- -
-
- -
-
-
-
- - - - \ No newline at end of file diff --git a/docs/build/html/_modules/index.html b/docs/build/html/_modules/index.html deleted file mode 100644 index 4ce3508..0000000 --- a/docs/build/html/_modules/index.html +++ /dev/null @@ -1,112 +0,0 @@ - - - - - - - - 개요: 모듈 코드 — Atio 2.0.0 문서 - - - - - - - - - - - - - - - - -
- - -
- -
-
-
-
    -
  • - -
  • -
  • -
-
-
-
-
- -

코드를 확인할 수 있는 모든 모듈

- - -
-
- -
-
-
-
- - - - \ No newline at end of file diff --git a/docs/build/html/_sources/advanced_usage.rst.txt b/docs/build/html/_sources/advanced_usage.rst.txt deleted file mode 100644 index f8eafc9..0000000 --- a/docs/build/html/_sources/advanced_usage.rst.txt +++ /dev/null @@ -1,323 +0,0 @@ -고급 사용법 -========== - -이 섹션에서는 Atio의 고급 기능들을 다룹니다. - -스냅샷 기반 버전 관리 --------------------- - -Atio는 데이터의 버전을 관리할 수 있는 스냅샷 시스템을 제공합니다. - -기본 스냅샷 쓰기 -~~~~~~~~~~~~~~~ - -.. code-block:: python - - import atio - import pandas as pd - - # 데이터 생성 - df = pd.DataFrame({ - "id": [1, 2, 3], - "name": ["Alice", "Bob", "Charlie"] - }) - - # 스냅샷으로 저장 (버전 관리) - atio.write_snapshot(df, "users_table", format="parquet") - - # 새로운 데이터로 업데이트 - df_new = pd.DataFrame({ - "id": [1, 2, 3, 4], - "name": ["Alice", "Bob", "Charlie", "David"] - }) - - # append 모드로 스냅샷 추가 - atio.write_snapshot(df_new, "users_table", mode="append", format="parquet") - -스냅샷 읽기 -~~~~~~~~~~ - -.. code-block:: python - - # 최신 버전 읽기 - latest_data = atio.read_table("users_table") - - # 특정 버전 읽기 - version_1_data = atio.read_table("users_table", version=1) - - # Polars로 읽기 - polars_data = atio.read_table("users_table", output_as="polars") - -스냅샷 정리 -~~~~~~~~~~ - -.. code-block:: python - - from datetime import timedelta - - # 7일 이상 된 스냅샷 삭제 (dry run) - atio.expire_snapshots("users_table", keep_for=timedelta(days=7), dry_run=True) - - # 실제 삭제 실행 - atio.expire_snapshots("users_table", keep_for=timedelta(days=7), dry_run=False) - -데이터베이스 연동 ----------------- - -Pandas와 Polars를 사용하여 데이터베이스에 안전하게 데이터를 저장할 수 있습니다. - -Pandas SQL 연동 -~~~~~~~~~~~~~~ - -.. code-block:: python - - import atio - import pandas as pd - from sqlalchemy import create_engine - - # 데이터베이스 연결 - engine = create_engine('postgresql://user:password@localhost/dbname') - - df = pd.DataFrame({ - "id": [1, 2, 3], - "name": ["Alice", "Bob", "Charlie"] - }) - - # SQL 데이터베이스에 저장 - atio.write(df, format="sql", name="users", con=engine) - -Polars 데이터베이스 연동 -~~~~~~~~~~~~~~~~~~~~~~ - -.. code-block:: python - - import atio - import polars as pl - - df = pl.DataFrame({ - "id": [1, 2, 3], - "name": ["Alice", "Bob", "Charlie"] - }) - - # 데이터베이스에 저장 - atio.write(df, format="database", - table_name="users", - connection_uri="postgresql://user:password@localhost/dbname") - -성능 최적화 ------------ - -진행도 표시 -~~~~~~~~~~ - -대용량 파일 처리 시 진행 상황을 실시간으로 확인할 수 있습니다. - -.. code-block:: python - - import atio - import pandas as pd - import numpy as np - - # 대용량 데이터 생성 - large_df = pd.DataFrame(np.random.randn(1000000, 10)) - - # 진행도 표시와 함께 저장 - atio.write(large_df, "large_data.parquet", - format="parquet", - show_progress=True) - -상세 로깅 -~~~~~~~~~ - -성능 진단을 위한 상세한 로깅을 활성화할 수 있습니다. - -.. code-block:: python - - # 상세한 성능 정보 출력 - atio.write(df, "data.parquet", format="parquet", verbose=True) - -이를 통해 다음과 같은 정보를 확인할 수 있습니다: - -- 각 단계별 소요 시간 -- 임시 파일 생성 및 교체 과정 -- 백업 및 롤백 과정 -- 성능 병목점 분석 - -에러 처리 ---------- - -Atio는 다양한 에러 상황에 대해 안전하게 처리합니다. - -파일 시스템 에러 -~~~~~~~~~~~~~~~ - -.. code-block:: python - - import atio - import pandas as pd - - df = pd.DataFrame({"a": [1, 2, 3]}) - - try: - # 권한이 없는 디렉토리에 저장 시도 - atio.write(df, "/root/data.parquet", format="parquet") - except PermissionError as e: - print(f"권한 에러: {e}") - # 원본 파일은 그대로 보존됨 - -포맷 에러 -~~~~~~~~~ - -.. code-block:: python - - try: - # 지원하지 않는 포맷 사용 - atio.write(df, "data.unknown", format="unknown") - except ValueError as e: - print(f"지원하지 않는 포맷: {e}") - -데이터베이스 에러 -~~~~~~~~~~~~~~~ - -.. code-block:: python - - try: - # 잘못된 데이터베이스 연결 정보 - atio.write(df, format="sql", - name="users", - con="invalid_connection") - except Exception as e: - print(f"데이터베이스 에러: {e}") - -플러그인 확장 ------------- - -Atio는 플러그인 아키텍처를 통해 새로운 형식을 쉽게 추가할 수 있습니다. - -커스텀 형식 등록 -~~~~~~~~~~~~~~~ - -.. code-block:: python - - from atio.plugins import register_writer - import pandas as pd - - # 커스텀 형식 등록 - def custom_writer(df, path, **kwargs): - # 커스텀 저장 로직 - with open(path, 'w') as f: - f.write("Custom format\n") - f.write(df.to_string()) - - # Pandas DataFrame에 대한 커스텀 형식 등록 - register_writer(pd.DataFrame, "custom", custom_writer) - - # 사용 - df = pd.DataFrame({"a": [1, 2, 3]}) - atio.write(df, "data.custom", format="custom") - -NumPy 배열 처리 --------------- - -NumPy 배열의 다양한 저장 방식을 지원합니다. - -단일 배열 저장 -~~~~~~~~~~~~~ - -.. code-block:: python - - import atio - import numpy as np - - arr = np.array([[1, 2, 3], [4, 5, 6]]) - - # .npy 파일로 저장 - atio.write(arr, "array.npy", format="npy") - - # .csv 파일로 저장 - atio.write(arr, "array.csv", format="csv") - -여러 배열 저장 -~~~~~~~~~~~~~ - -.. code-block:: python - - # 여러 배열을 딕셔너리로 저장 - arrays = { - "features": np.random.randn(1000, 10), - "labels": np.random.randint(0, 2, 1000), - "metadata": np.array([1, 2, 3, 4, 5]) - } - - # 압축된 .npz 파일로 저장 - atio.write(arrays, "data.npz", format="npz_compressed") - -실제 사용 사례 -------------- - -머신러닝 파이프라인 -~~~~~~~~~~~~~~~~~ - -.. code-block:: python - - import atio - import pandas as pd - from sklearn.model_selection import train_test_split - from sklearn.ensemble import RandomForestClassifier - - # 데이터 로드 및 전처리 - df = pd.read_csv("raw_data.csv") - - # 전처리된 데이터를 안전하게 저장 - atio.write(df, "processed_data.parquet", format="parquet") - - # 학습/테스트 분할 - X_train, X_test, y_train, y_test = train_test_split( - df.drop('target', axis=1), df['target'], test_size=0.2 - ) - - # 분할된 데이터를 스냅샷으로 저장 - atio.write_snapshot(X_train, "training_data", format="parquet") - atio.write_snapshot(X_test, "test_data", format="parquet") - - # 모델 학습 - model = RandomForestClassifier() - model.fit(X_train, y_train) - - # 예측 결과를 안전하게 저장 - predictions = model.predict(X_test) - results_df = pd.DataFrame({ - 'actual': y_test, - 'predicted': predictions - }) - - atio.write(results_df, "predictions.parquet", format="parquet") - -ETL 파이프라인 -~~~~~~~~~~~~~ - -.. code-block:: python - - import atio - import pandas as pd - from sqlalchemy import create_engine - - # 1. 원본 데이터 로드 - raw_data = pd.read_csv("source_data.csv") - - # 2. 데이터 정제 - cleaned_data = raw_data.dropna() - cleaned_data = cleaned_data[cleaned_data['value'] > 0] - - # 3. 안전하게 정제된 데이터 저장 - atio.write(cleaned_data, "cleaned_data.parquet", format="parquet") - - # 4. 데이터베이스에 저장 - engine = create_engine('postgresql://user:password@localhost/warehouse') - atio.write(cleaned_data, format="sql", - name="processed_table", - con=engine, - if_exists='replace') - - # 5. 스냅샷으로 버전 관리 - atio.write_snapshot(cleaned_data, "daily_processed", format="parquet") \ No newline at end of file diff --git a/docs/build/html/_sources/api.rst.txt b/docs/build/html/_sources/api.rst.txt deleted file mode 100644 index 2e0f4f9..0000000 --- a/docs/build/html/_sources/api.rst.txt +++ /dev/null @@ -1,222 +0,0 @@ -API 참조 -======== - -Atio의 모든 함수와 클래스에 대한 상세한 API 문서입니다. - -주요 함수 --------- - -.. automodule:: atio - :members: - :undoc-members: - :show-inheritance: - -Core 모듈 --------- - -.. automodule:: atio.core - :members: - :undoc-members: - :show-inheritance: - -write() -------- - -안전한 원자적 파일 쓰기를 수행하는 메인 함수입니다. - -.. function:: atio.write(obj, target_path=None, format='parquet', **kwargs) - - :param obj: 저장할 데이터 객체 (pandas.DataFrame, polars.DataFrame, numpy.ndarray) - :param target_path: 저장할 파일 경로 (파일 저장 시 필수) - :param format: 저장 형식 ('csv', 'parquet', 'excel', 'json', 'sql', 'database') - :param show_progress: 진행률 표시 여부 (기본값: False) - :param verbose: 상세 성능 정보 출력 여부 (기본값: False) - :param **kwargs: 형식별 추가 매개변수 - - :returns: None - - :raises: ValueError, IOError, DatabaseError - - **사용 예제:** - - .. code-block:: python - - import atio - import pandas as pd - - df = pd.DataFrame({"a": [1, 2, 3]}) - - # 기본 사용법 - atio.write(df, "data.parquet", format="parquet") - - # 진행률 표시 - atio.write(df, "data.parquet", format="parquet", show_progress=True) - - # 성능 정보 출력 - atio.write(df, "data.parquet", format="parquet", verbose=True) - -write_snapshot() ---------------- - -데이터 스냅샷을 생성하여 버전 관리를 수행합니다. - -.. function:: atio.write_snapshot(obj, table_name, format='parquet', **kwargs) - - :param obj: 저장할 데이터 객체 - :param table_name: 테이블 이름 (스냅샷 디렉토리명) - :param format: 저장 형식 - :param **kwargs: 추가 매개변수 - - :returns: 생성된 스냅샷 ID - - **사용 예제:** - - .. code-block:: python - - # 스냅샷 생성 - snapshot_id = atio.write_snapshot(df, "users", format="parquet") - print(f"생성된 스냅샷 ID: {snapshot_id}") - -read_table() ------------ - -스냅샷에서 데이터를 읽어옵니다. - -.. function:: atio.read_table(table_name, snapshot_id='latest', format='parquet', **kwargs) - - :param table_name: 테이블 이름 - :param snapshot_id: 스냅샷 ID (기본값: 'latest') - :param format: 읽을 형식 - :param **kwargs: 추가 매개변수 - - :returns: 데이터 객체 - - **사용 예제:** - - .. code-block:: python - - # 최신 스냅샷 읽기 - df = atio.read_table("users", format="parquet") - - # 특정 스냅샷 읽기 - df = atio.read_table("users", snapshot_id="20240101_120000", format="parquet") - -expire_snapshots() ------------------ - -오래된 스냅샷을 정리합니다. - -.. function:: atio.expire_snapshots(table_name, days=30, format='parquet') - - :param table_name: 테이블 이름 - :param days: 보관할 일수 (기본값: 30) - :param format: 형식 - - :returns: 삭제된 스냅샷 수 - - **사용 예제:** - - .. code-block:: python - - # 30일 이상 된 스냅샷 정리 - deleted_count = atio.expire_snapshots("users", days=30) - print(f"삭제된 스냅샷 수: {deleted_count}") - -Plugins 모듈 ------------ - -.. automodule:: atio.plugins - :members: - :undoc-members: - :show-inheritance: - -Utils 모듈 ---------- - -.. automodule:: atio.utils - :members: - :undoc-members: - :show-inheritance: - -지원하는 형식 ------------ - -CSV 형식 -~~~~~~~ - -.. code-block:: python - - atio.write(df, "data.csv", format="csv", index=False, encoding='utf-8') - -**지원 매개변수:** -- `index`: 인덱스 포함 여부 -- `encoding`: 인코딩 방식 -- `sep`: 구분자 -- `na_rep`: NA 값 표현 - -Parquet 형식 -~~~~~~~~~~~ - -.. code-block:: python - - atio.write(df, "data.parquet", format="parquet", compression='snappy') - -**지원 매개변수:** -- `compression`: 압축 방식 ('snappy', 'gzip', 'brotli') -- `engine`: 엔진 ('pyarrow', 'fastparquet') - -Excel 형식 -~~~~~~~~~ - -.. code-block:: python - - atio.write(df, "data.xlsx", format="excel", sheet_name="Sheet1") - -**지원 매개변수:** -- `sheet_name`: 시트 이름 -- `engine`: 엔진 ('openpyxl', 'xlsxwriter') - -JSON 형식 -~~~~~~~~~ - -.. code-block:: python - - atio.write(df, "data.json", format="json", orient="records") - -**지원 매개변수:** -- `orient`: 방향 ('records', 'split', 'index', 'columns', 'values', 'table') - -SQL 형식 -~~~~~~~~ - -.. code-block:: python - - atio.write(df, format="sql", name="table_name", con=engine, if_exists="replace") - -**지원 매개변수:** -- `name`: 테이블 이름 -- `con`: 데이터베이스 연결 -- `if_exists`: 테이블 존재 시 동작 ('fail', 'replace', 'append') - -예외 처리 --------- - -Atio는 다음과 같은 예외를 발생시킬 수 있습니다: - -- **ValueError**: 잘못된 매개변수나 형식 -- **IOError**: 파일 시스템 오류 -- **DatabaseError**: 데이터베이스 연결 오류 -- **ImportError**: 필요한 패키지가 설치되지 않은 경우 - -**예외 처리 예제:** - -.. code-block:: python - - try: - atio.write(df, "data.parquet", format="parquet") - except ValueError as e: - print(f"매개변수 오류: {e}") - except IOError as e: - print(f"파일 시스템 오류: {e}") - except Exception as e: - print(f"예상치 못한 오류: {e}") \ No newline at end of file diff --git a/docs/build/html/_sources/configuration.rst.txt b/docs/build/html/_sources/configuration.rst.txt deleted file mode 100644 index 6d805cc..0000000 --- a/docs/build/html/_sources/configuration.rst.txt +++ /dev/null @@ -1,491 +0,0 @@ -설정 및 구성 -============ - -Atio의 다양한 설정 옵션과 구성 방법을 설명합니다. - -로깅 설정 --------- - -Atio는 상세한 로깅을 통해 작업 과정을 추적할 수 있습니다. - -기본 로깅 -~~~~~~~~~ - -.. code-block:: python - - import atio - import pandas as pd - - df = pd.DataFrame({"a": [1, 2, 3]}) - - # 기본 로깅 (INFO 레벨) - atio.write(df, "data.parquet", format="parquet") - -**출력 예시:** -``` -[INFO] 임시 디렉토리 생성: /tmp/tmp12345 -[INFO] 임시 파일 경로: /tmp/tmp12345/data.parquet -[INFO] 사용할 writer: to_parquet (format: parquet) -[INFO] 데이터 임시 파일에 저장 완료: /tmp/tmp12345/data.parquet -[INFO] 원자적 교체 완료: /tmp/tmp12345/data.parquet -> data.parquet -[INFO] _SUCCESS 플래그 파일 생성: .data.parquet._SUCCESS -[INFO] ✅ Atomic write completed successfully (took 0.1234s) -``` - -상세 로깅 -~~~~~~~~~ - -.. code-block:: python - - # 상세한 성능 정보 출력 (DEBUG 레벨) - atio.write(df, "data.parquet", format="parquet", verbose=True) - -**출력 예시:** -``` -[INFO] 임시 디렉토리 생성: /tmp/tmp12345 -[INFO] 임시 파일 경로: /tmp/tmp12345/data.parquet -[INFO] 사용할 writer: to_parquet (format: parquet) -[INFO] 데이터 임시 파일에 저장 완료: /tmp/tmp12345/data.parquet -[INFO] 원자적 교체 완료: /tmp/tmp12345/data.parquet -> data.parquet -[INFO] _SUCCESS 플래그 파일 생성: .data.parquet._SUCCESS -[DEBUG] Atomic write step timings (SUCCESS): setup=0.0012s, write_call=0.0987s, replace=0.0001s, success_flag=0.0001s, total=0.1001s -[INFO] ✅ Atomic write completed successfully (took 0.1001s) -``` - -진행도 표시 ----------- - -대용량 파일 처리 시 진행 상황을 실시간으로 확인할 수 있습니다. - -기본 진행도 표시 -~~~~~~~~~~~~~~~ - -.. code-block:: python - - import atio - import pandas as pd - import numpy as np - - # 대용량 데이터 생성 - large_df = pd.DataFrame(np.random.randn(1000000, 10)) - - # 진행도 표시와 함께 저장 - atio.write(large_df, "large_data.parquet", - format="parquet", - show_progress=True) - -**출력 예시:** -``` -⠋ Writing large_data.parquet... [ 45.2 MB | 12.3 MB/s | 00:03 ] -⠙ Writing large_data.parquet... [ 67.8 MB | 11.9 MB/s | 00:05 ] -⠹ Writing large_data.parquet... [ 89.1 MB | 12.1 MB/s | 00:07 ] -✅ Writing completed successfully (89.1 MB in 7s) -``` - -진행도 표시 옵션 -~~~~~~~~~~~~~~~ - -진행도 표시는 다음과 같은 정보를 제공합니다: - -- **스피너**: 작업 진행 상태를 시각적으로 표시 -- **파일 크기**: 현재까지 저장된 데이터 크기 -- **처리 속도**: 초당 처리되는 데이터 양 -- **경과 시간**: 작업 시작 후 경과한 시간 - -성능 최적화 설정 ----------------- - -메모리 사용량 최적화 -~~~~~~~~~~~~~~~~~~~ - -.. code-block:: python - - # 대용량 데이터 처리 시 메모리 효율적인 설정 - atio.write(large_df, "data.parquet", format="parquet", - compression='snappy', # 빠른 압축 - index=False) # 인덱스 제외로 메모리 절약 - -압축 설정 -~~~~~~~~~ - -.. code-block:: python - - # 속도 우선 (압축 없음) - atio.write(df, "data.parquet", format="parquet", compression=None) - - # 균형 (snappy 압축) - atio.write(df, "data.parquet", format="parquet", compression='snappy') - - # 용량 우선 (gzip 압축) - atio.write(df, "data.parquet", format="parquet", compression='gzip') - -임시 디렉토리 설정 ------------------ - -기본적으로 Atio는 시스템의 임시 디렉토리를 사용합니다. - -사용자 정의 임시 디렉토리 -~~~~~~~~~~~~~~~~~~~~~~~ - -.. code-block:: python - - import os - import tempfile - - # 임시 디렉토리 설정 - tempfile.tempdir = "/path/to/custom/temp" - - # 또는 환경 변수 설정 - os.environ['TMPDIR'] = "/path/to/custom/temp" - -**주의사항:** -- 임시 디렉토리는 충분한 디스크 공간이 있어야 합니다 -- 쓰기 권한이 있어야 합니다 -- 빠른 I/O 성능을 위해 SSD를 권장합니다 - -에러 처리 설정 --------------- - -Atio는 다양한 에러 상황에 대해 안전하게 처리합니다. - -롤백 동작 -~~~~~~~~~ - -.. code-block:: python - - # 기본적으로 롤백이 자동으로 수행됩니다 - try: - atio.write(df, "data.parquet", format="parquet") - except Exception as e: - # 에러 발생 시 원본 파일은 보존됩니다 - print(f"저장 실패: {e}") - # 임시 파일은 자동으로 정리됩니다 - -백업 파일 관리 -~~~~~~~~~~~~~ - -.. code-block:: python - - # 백업 파일은 작업 성공 시 자동으로 삭제됩니다 - # 실패 시에는 롤백 후 삭제됩니다 - - # 백업 파일이 남아있는 경우 수동으로 확인 - import os - backup_file = "data.parquet._backup" - if os.path.exists(backup_file): - print("백업 파일이 존재합니다. 수동 확인이 필요할 수 있습니다.") - -완료 플래그 시스템 ------------------- - -Atio는 작업 완료를 확인할 수 있는 플래그 파일을 생성합니다. - -플래그 파일 확인 -~~~~~~~~~~~~~~~ - -.. code-block:: python - - import os - - # 저장 완료 후 플래그 파일 확인 - atio.write(df, "data.parquet", format="parquet") - - # 플래그 파일 경로 - flag_file = ".data.parquet._SUCCESS" - - if os.path.exists(flag_file): - print("저장이 성공적으로 완료되었습니다.") - else: - print("저장이 완료되지 않았거나 실패했습니다.") - -플래그 파일 활용 -~~~~~~~~~~~~~~~ - -.. code-block:: python - - # 배치 처리에서 완료 여부 확인 - files_to_process = ["data1.parquet", "data2.parquet", "data3.parquet"] - - for file in files_to_process: - flag_file = f".{file}._SUCCESS" - if not os.path.exists(flag_file): - print(f"{file} 처리가 완료되지 않았습니다.") - # 재처리 로직 - -스냅샷 설정 ----------- - -스냅샷 시스템의 다양한 설정 옵션을 설명합니다. - -스냅샷 모드 -~~~~~~~~~~ - -.. code-block:: python - - # overwrite 모드 (기본값) - atio.write_snapshot(df, "table_path", mode="overwrite", format="parquet") - - # append 모드 (기존 데이터에 추가) - atio.write_snapshot(df, "table_path", mode="append", format="parquet") - -스냅샷 정리 설정 -~~~~~~~~~~~~~~~ - -.. code-block:: python - - from datetime import timedelta - - # 7일 이상 된 스냅샷 삭제 - atio.expire_snapshots("table_path", - keep_for=timedelta(days=7), - dry_run=True) # 실제 삭제 전 확인 - - # 30일 이상 된 스냅샷 삭제 - atio.expire_snapshots("table_path", - keep_for=timedelta(days=30), - dry_run=False) # 실제 삭제 - -환경 변수 설정 -------------- - -Atio의 동작을 제어하는 환경 변수들을 설정할 수 있습니다. - -로깅 레벨 설정 -~~~~~~~~~~~~~ - -.. code-block:: python - - import os - - # DEBUG 레벨로 로깅 설정 - os.environ['ATIO_LOG_LEVEL'] = 'DEBUG' - - # INFO 레벨로 로깅 설정 (기본값) - os.environ['ATIO_LOG_LEVEL'] = 'INFO' - -임시 디렉토리 설정 -~~~~~~~~~~~~~~~~~ - -.. code-block:: python - - # 임시 디렉토리 경로 설정 - os.environ['ATIO_TEMP_DIR'] = '/path/to/temp' - - # 또는 시스템 임시 디렉토리 설정 - os.environ['TMPDIR'] = '/path/to/temp' - -성능 모니터링 설정 -~~~~~~~~~~~~~~~~~ - -.. code-block:: python - - # 성능 모니터링 활성화 - os.environ['ATIO_PERFORMANCE_MONITORING'] = 'true' - - # 성능 모니터링 비활성화 - os.environ['ATIO_PERFORMANCE_MONITORING'] = 'false' - -플러그인 설정 ------------- - -커스텀 플러그인을 등록하여 새로운 형식을 지원할 수 있습니다. - -플러그인 등록 -~~~~~~~~~~~~ - -.. code-block:: python - - from atio.plugins import register_writer - import pandas as pd - - # 커스텀 형식 등록 - def custom_writer(df, path, **kwargs): - # 커스텀 저장 로직 - with open(path, 'w') as f: - f.write("Custom format\n") - f.write(df.to_string()) - - # 등록 - register_writer(pd.DataFrame, "custom", custom_writer) - -플러그인 확인 -~~~~~~~~~~~~ - -.. code-block:: python - - from atio.plugins import WRITER_MAPPING - - # 등록된 플러그인 확인 - for obj_type, formats in WRITER_MAPPING.items(): - print(f"Object type: {obj_type.__name__}") - for fmt, handler in formats.items(): - print(f" - {fmt}: {handler}") - -설정 파일 사용 -------------- - -설정을 파일로 관리하여 일관된 설정을 유지할 수 있습니다. - -JSON 설정 파일 -~~~~~~~~~~~~~~ - -.. code-block:: python - - import json - - # 설정 파일 생성 - config = { - "default_format": "parquet", - "compression": "snappy", - "show_progress": True, - "verbose": False, - "temp_dir": "/path/to/temp" - } - - with open("atio_config.json", "w") as f: - json.dump(config, f, indent=2) - - # 설정 파일 읽기 - with open("atio_config.json", "r") as f: - config = json.load(f) - - # 설정 적용 - atio.write(df, "data.parquet", - format=config.get("default_format", "parquet"), - compression=config.get("compression", "snappy"), - show_progress=config.get("show_progress", False), - verbose=config.get("verbose", False)) - -YAML 설정 파일 -~~~~~~~~~~~~~ - -.. code-block:: python - - import yaml - - # 설정 파일 생성 - config = { - "default_format": "parquet", - "compression": "snappy", - "show_progress": True, - "verbose": False, - "temp_dir": "/path/to/temp" - } - - with open("atio_config.yaml", "w") as f: - yaml.dump(config, f) - - # 설정 파일 읽기 - with open("atio_config.yaml", "r") as f: - config = yaml.safe_load(f) - -모범 사례 --------- - -프로덕션 환경 설정 -~~~~~~~~~~~~~~~~~ - -.. code-block:: python - - # 프로덕션 환경을 위한 설정 - import os - import tempfile - - # 1. 전용 임시 디렉토리 설정 - tempfile.tempdir = "/var/tmp/atio" - os.makedirs(tempfile.tempdir, exist_ok=True) - - # 2. 로깅 레벨 설정 - os.environ['ATIO_LOG_LEVEL'] = 'INFO' - - # 3. 성능 최적화 설정 - def safe_write(df, path, **kwargs): - return atio.write(df, path, - format="parquet", - compression="snappy", - show_progress=True, - verbose=False, - **kwargs) - -개발 환경 설정 -~~~~~~~~~~~~~ - -.. code-block:: python - - # 개발 환경을 위한 설정 - import os - - # 1. 상세 로깅 활성화 - os.environ['ATIO_LOG_LEVEL'] = 'DEBUG' - - # 2. 성능 모니터링 활성화 - os.environ['ATIO_PERFORMANCE_MONITORING'] = 'true' - - # 3. 개발용 설정 - def dev_write(df, path, **kwargs): - return atio.write(df, path, - format="parquet", - compression=None, # 압축 없음으로 빠른 처리 - show_progress=True, - verbose=True, # 상세 정보 출력 - **kwargs) - -설정 검증 --------- - -설정이 올바르게 적용되었는지 확인하는 방법을 설명합니다. - -기본 검증 -~~~~~~~~~ - -.. code-block:: python - - import atio - import pandas as pd - import tempfile - - # 테스트 데이터 생성 - df = pd.DataFrame({"test": [1, 2, 3]}) - - # 설정 테스트 - def test_config(): - # 임시 디렉토리 확인 - print(f"임시 디렉토리: {tempfile.gettempdir()}") - - # 로깅 테스트 - atio.write(df, "test.parquet", format="parquet", verbose=True) - - # 플래그 파일 확인 - import os - if os.path.exists(".test.parquet._SUCCESS"): - print("설정이 올바르게 작동합니다.") - else: - print("설정에 문제가 있을 수 있습니다.") - -성능 테스트 -~~~~~~~~~~ - -.. code-block:: python - - import time - import pandas as pd - import numpy as np - - # 성능 테스트 - def performance_test(): - # 대용량 데이터 생성 - large_df = pd.DataFrame(np.random.randn(100000, 10)) - - # 성능 측정 - start_time = time.time() - atio.write(large_df, "performance_test.parquet", - format="parquet", - show_progress=True) - end_time = time.time() - - print(f"처리 시간: {end_time - start_time:.2f}초") - - # 파일 크기 확인 - import os - file_size = os.path.getsize("performance_test.parquet") - print(f"파일 크기: {file_size / 1024 / 1024:.2f} MB") \ No newline at end of file diff --git a/docs/build/html/_sources/examples.rst.txt b/docs/build/html/_sources/examples.rst.txt deleted file mode 100644 index 64cd264..0000000 --- a/docs/build/html/_sources/examples.rst.txt +++ /dev/null @@ -1,395 +0,0 @@ -사용 예제 -========= - -Atio의 다양한 사용 사례와 고급 기능을 살펴보세요. - -기본 예제 --------- - -간단한 데이터 저장 -~~~~~~~~~~~~~~~~~ - -.. code-block:: python - - import atio - import pandas as pd - - # 샘플 데이터 생성 - data = { - "id": [1, 2, 3, 4, 5], - "name": ["Alice", "Bob", "Charlie", "Diana", "Eve"], - "age": [25, 30, 35, 28, 32], - "city": ["Seoul", "Busan", "Incheon", "Daegu", "Daejeon"], - "salary": [50000, 60000, 70000, 55000, 65000] - } - - df = pd.DataFrame(data) - - # 다양한 형식으로 저장 - atio.write(df, "employees.parquet", format="parquet") - atio.write(df, "employees.csv", format="csv", index=False) - atio.write(df, "employees.xlsx", format="excel", sheet_name="Employees") - -대용량 데이터 처리 ----------------- - -진행률 표시와 성능 모니터링 -~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. code-block:: python - - import numpy as np - import pandas as pd - import atio - - # 대용량 데이터 생성 (100만 행) - large_data = { - "id": range(1, 1000001), - "value": np.random.randn(1000000), - "category": np.random.choice(["A", "B", "C"], 1000000), - "timestamp": pd.date_range("2024-01-01", periods=1000000, freq="S") - } - - large_df = pd.DataFrame(large_data) - - # 진행률 표시와 성능 모니터링 활성화 - atio.write( - large_df, - "large_dataset.parquet", - format="parquet", - show_progress=True, - verbose=True, - compression='snappy' - ) - -데이터베이스 연동 ---------------- - -PostgreSQL 데이터베이스 저장 -~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. code-block:: python - - import atio - import pandas as pd - from sqlalchemy import create_engine - - # 데이터베이스 연결 - engine = create_engine('postgresql://username:password@localhost:5432/mydb') - - # 샘플 데이터 - sales_data = { - "order_id": [1001, 1002, 1003, 1004, 1005], - "product_name": ["Laptop", "Mouse", "Keyboard", "Monitor", "Headphones"], - "quantity": [1, 2, 1, 1, 3], - "price": [1200, 25, 75, 300, 150], - "order_date": pd.date_range("2024-01-01", periods=5) - } - - sales_df = pd.DataFrame(sales_data) - - # 데이터베이스에 안전하게 저장 - atio.write( - sales_df, - format="sql", - name="sales_orders", - con=engine, - if_exists="replace", - index=False - ) - -스냅샷 기반 버전 관리 -------------------- - -데이터 버전 관리 -~~~~~~~~~~~~~~~ - -.. code-block:: python - - import atio - import pandas as pd - from datetime import datetime, timedelta - - # 초기 데이터 - initial_data = { - "user_id": [1, 2, 3], - "name": ["Alice", "Bob", "Charlie"], - "status": ["active", "active", "inactive"] - } - - df = pd.DataFrame(initial_data) - - # 초기 스냅샷 생성 - snapshot_id_1 = atio.write_snapshot(df, "users", format="parquet") - print(f"초기 스냅샷 생성: {snapshot_id_1}") - - # 데이터 업데이트 - df.loc[df['user_id'] == 3, 'status'] = 'active' - df = df.append({"user_id": 4, "name": "Diana", "status": "active"}, ignore_index=True) - - # 업데이트된 스냅샷 생성 - snapshot_id_2 = atio.write_snapshot(df, "users", format="parquet") - print(f"업데이트 스냅샷 생성: {snapshot_id_2}") - - # 최신 데이터 읽기 - latest_df = atio.read_table("users", format="parquet") - print("최신 데이터:") - print(latest_df) - - # 특정 스냅샷 읽기 - initial_df = atio.read_table("users", snapshot_id=snapshot_id_1, format="parquet") - print("초기 데이터:") - print(initial_df) - - # 오래된 스냅샷 정리 (7일 이상) - deleted_count = atio.expire_snapshots("users", days=7, format="parquet") - print(f"삭제된 스냅샷 수: {deleted_count}") - -Polars DataFrame 활용 -------------------- - -고성능 데이터 처리 -~~~~~~~~~~~~~~~~~ - -.. code-block:: python - - import atio - import polars as pl - import numpy as np - - # Polars DataFrame 생성 - polars_data = { - "id": range(1, 10001), - "value": np.random.randn(10000), - "category": np.random.choice(["A", "B", "C", "D"], 10000), - "score": np.random.uniform(0, 100, 10000) - } - - polars_df = pl.DataFrame(polars_data) - - # Polars DataFrame 저장 - atio.write( - polars_df, - "polars_data.parquet", - format="parquet", - compression='snappy', - show_progress=True - ) - - # 데이터 변환 후 저장 - filtered_df = polars_df.filter(pl.col("score") > 50) - aggregated_df = filtered_df.group_by("category").agg( - pl.col("value").mean().alias("avg_value"), - pl.col("score").mean().alias("avg_score") - ) - - atio.write(aggregated_df, "aggregated_data.parquet", format="parquet") - -에러 처리 및 복구 ---------------- - -안전한 데이터 처리 -~~~~~~~~~~~~~~~~~ - -.. code-block:: python - - import atio - import pandas as pd - import os - - def safe_data_processing(): - try: - # 원본 파일이 있는지 확인 - if os.path.exists("important_data.parquet"): - print("원본 파일이 존재합니다.") - - # 데이터 처리 및 저장 - df = pd.DataFrame({ - "id": [1, 2, 3], - "data": ["important", "data", "here"] - }) - - atio.write(df, "important_data.parquet", format="parquet") - print("데이터가 안전하게 저장되었습니다.") - - # SUCCESS 파일 확인 - if os.path.exists("important_data.parquet_SUCCESS"): - print("저장 완료 플래그가 생성되었습니다.") - - except Exception as e: - print(f"오류 발생: {e}") - print("원본 파일이 보존되었습니다.") - - # 임시 파일 정리 - temp_files = [f for f in os.listdir(".") if f.startswith("important_data.parquet.tmp")] - for temp_file in temp_files: - try: - os.remove(temp_file) - print(f"임시 파일 정리: {temp_file}") - except: - pass - - # 안전한 데이터 처리 실행 - safe_data_processing() - -배치 처리 -------- - -여러 파일 동시 처리 -~~~~~~~~~~~~~~~~~ - -.. code-block:: python - - import atio - import pandas as pd - import os - from pathlib import Path - - def process_multiple_files(): - # 처리할 파일 목록 - files_to_process = [ - {"name": "users", "data": pd.DataFrame({"id": [1, 2], "name": ["Alice", "Bob"]})}, - {"name": "products", "data": pd.DataFrame({"id": [1, 2], "product": ["Laptop", "Mouse"]})}, - {"name": "orders", "data": pd.DataFrame({"id": [1, 2], "amount": [100, 200]})} - ] - - # 각 파일을 안전하게 처리 - for file_info in files_to_process: - try: - file_path = f"{file_info['name']}.parquet" - atio.write( - file_info['data'], - file_path, - format="parquet", - show_progress=True - ) - print(f"{file_info['name']} 파일 처리 완료") - - except Exception as e: - print(f"{file_info['name']} 파일 처리 실패: {e}") - continue - - # 배치 처리 실행 - process_multiple_files() - -성능 최적화 ---------- - -압축 및 최적화 설정 -~~~~~~~~~~~~~~~~~ - -.. code-block:: python - - import atio - import pandas as pd - import numpy as np - - # 대용량 데이터 생성 - large_df = pd.DataFrame({ - "id": range(1, 100001), - "value": np.random.randn(100000), - "text": ["sample text"] * 100000 - }) - - # 다양한 압축 설정으로 성능 비교 - compression_settings = [ - ("snappy", "fast_compression.parquet"), - ("gzip", "balanced_compression.parquet"), - ("brotli", "high_compression.parquet") - ] - - for compression, filename in compression_settings: - print(f"\n{compression} 압축으로 저장 중...") - atio.write( - large_df, - filename, - format="parquet", - compression=compression, - show_progress=True, - verbose=True - ) - - # 파일 크기 확인 - file_size = os.path.getsize(filename) / (1024 * 1024) # MB - print(f"파일 크기: {file_size:.2f} MB") - -실제 사용 사례 ------------- - -데이터 파이프라인 -~~~~~~~~~~~~~~~ - -.. code-block:: python - - import atio - import pandas as pd - from datetime import datetime, timedelta - - class DataPipeline: - def __init__(self, base_path="data"): - self.base_path = Path(base_path) - self.base_path.mkdir(exist_ok=True) - - def extract_data(self): - """데이터 추출 (시뮬레이션)""" - # 실제로는 API나 데이터베이스에서 데이터를 가져옴 - data = { - "timestamp": pd.date_range(datetime.now(), periods=1000, freq="H"), - "value": np.random.randn(1000), - "source": ["api"] * 1000 - } - return pd.DataFrame(data) - - def transform_data(self, df): - """데이터 변환""" - # 시간별 집계 - df['hour'] = df['timestamp'].dt.hour - df['day'] = df['timestamp'].dt.date - - # 일별 통계 - daily_stats = df.groupby('day').agg({ - 'value': ['mean', 'std', 'min', 'max'] - }).round(2) - - return daily_stats - - def load_data(self, df, table_name): - """데이터 로드""" - # 스냅샷 생성 - snapshot_id = atio.write_snapshot( - df, - table_name, - format="parquet" - ) - - # 최신 데이터도 별도 저장 - latest_path = self.base_path / f"{table_name}_latest.parquet" - atio.write(df, str(latest_path), format="parquet") - - return snapshot_id - - def run_pipeline(self): - """파이프라인 실행""" - print("데이터 파이프라인 시작...") - - # 1. 데이터 추출 - raw_data = self.extract_data() - print(f"추출된 데이터: {len(raw_data)} 행") - - # 2. 데이터 변환 - processed_data = self.transform_data(raw_data) - print(f"처리된 데이터: {len(processed_data)} 행") - - # 3. 데이터 로드 - snapshot_id = self.load_data(processed_data, "daily_stats") - print(f"스냅샷 생성 완료: {snapshot_id}") - - # 4. 오래된 스냅샷 정리 - deleted_count = atio.expire_snapshots("daily_stats", days=30) - print(f"정리된 스냅샷: {deleted_count}개") - - print("파이프라인 완료!") - - # 파이프라인 실행 - pipeline = DataPipeline() - pipeline.run_pipeline() \ No newline at end of file diff --git a/docs/build/html/_sources/formats.rst.txt b/docs/build/html/_sources/formats.rst.txt deleted file mode 100644 index 488620c..0000000 --- a/docs/build/html/_sources/formats.rst.txt +++ /dev/null @@ -1,456 +0,0 @@ -지원하는 파일 형식 -================== - -Atio는 다양한 데이터 형식을 지원합니다. 각 형식별로 지원하는 라이브러리와 사용법을 설명합니다. - -Pandas DataFrame 형식 --------------------- - -Pandas DataFrame은 가장 많은 형식을 지원합니다. - -CSV (Comma-Separated Values) -~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. code-block:: python - - import atio - import pandas as pd - - df = pd.DataFrame({ - "name": ["Alice", "Bob", "Charlie"], - "age": [25, 30, 35], - "city": ["Seoul", "Busan", "Incheon"] - }) - - # 기본 CSV 저장 - atio.write(df, "users.csv", format="csv") - - # 추가 옵션과 함께 저장 - atio.write(df, "users.csv", format="csv", - index=False, - encoding='utf-8', - sep=';') - -**지원 옵션:** -- `index`: 인덱스 포함 여부 (기본값: True) -- `encoding`: 인코딩 방식 (기본값: 'utf-8') -- `sep`: 구분자 (기본값: ',') -- `header`: 헤더 포함 여부 (기본값: True) - -Parquet -~~~~~~~ - -.. code-block:: python - - # Parquet 형식으로 저장 - atio.write(df, "users.parquet", format="parquet") - - # 압축 옵션과 함께 저장 - atio.write(df, "users.parquet", format="parquet", - compression='snappy') - -**지원 옵션:** -- `compression`: 압축 방식 ('snappy', 'gzip', 'brotli', None) -- `index`: 인덱스 포함 여부 (기본값: True) - -Excel -~~~~~ - -.. code-block:: python - - # Excel 파일로 저장 - atio.write(df, "users.xlsx", format="excel") - - # 시트명과 옵션 지정 - atio.write(df, "users.xlsx", format="excel", - sheet_name="Users", - index=False) - -**지원 옵션:** -- `sheet_name`: 시트 이름 (기본값: 'Sheet1') -- `index`: 인덱스 포함 여부 (기본값: True) -- `engine`: 엔진 ('openpyxl', 'xlsxwriter') - -**필요 라이브러리:** `pip install openpyxl` - -JSON -~~~~ - -.. code-block:: python - - # JSON 형식으로 저장 - atio.write(df, "users.json", format="json") - - # 들여쓰기와 함께 저장 - atio.write(df, "users.json", format="json", - indent=2, - orient='records') - -**지원 옵션:** -- `orient`: JSON 구조 ('split', 'records', 'index', 'columns', 'values', 'table') -- `indent`: 들여쓰기 크기 -- `date_format`: 날짜 형식 - -Pickle -~~~~~~ - -.. code-block:: python - - # Pickle 형식으로 저장 - atio.write(df, "users.pkl", format="pickle") - - # 압축과 함께 저장 - atio.write(df, "users.pkl", format="pickle", - compression='gzip') - -**지원 옵션:** -- `compression`: 압축 방식 ('gzip', 'bz2', 'xz', None) - -HTML -~~~~ - -.. code-block:: python - - # HTML 테이블로 저장 - atio.write(df, "users.html", format="html") - - # 스타일과 함께 저장 - atio.write(df, "users.html", format="html", - index=False, - classes='table table-striped') - -**지원 옵션:** -- `classes`: CSS 클래스 -- `index`: 인덱스 포함 여부 (기본값: True) - -SQL -~~~ - -.. code-block:: python - - import atio - import pandas as pd - from sqlalchemy import create_engine - - # 데이터베이스 연결 - engine = create_engine('postgresql://user:password@localhost/dbname') - - df = pd.DataFrame({ - "id": [1, 2, 3], - "name": ["Alice", "Bob", "Charlie"] - }) - - # SQL 데이터베이스에 저장 - atio.write(df, format="sql", - name="users", - con=engine, - if_exists='replace') - -**지원 옵션:** -- `name`: 테이블 이름 (필수) -- `con`: 데이터베이스 연결 객체 (필수) -- `if_exists`: 테이블이 존재할 때 동작 ('fail', 'replace', 'append') -- `index`: 인덱스를 컬럼으로 저장 여부 (기본값: True) - -**필요 라이브러리:** `pip install sqlalchemy` - -Polars DataFrame 형식 --------------------- - -Polars는 빠른 데이터 처리를 위한 현대적인 DataFrame 라이브러리입니다. - -CSV -~~~ - -.. code-block:: python - - import atio - import polars as pl - - df = pl.DataFrame({ - "name": ["Alice", "Bob", "Charlie"], - "age": [25, 30, 35], - "city": ["Seoul", "Busan", "Incheon"] - }) - - # CSV 저장 - atio.write(df, "users.csv", format="csv") - - # 구분자와 함께 저장 - atio.write(df, "users.csv", format="csv", - separator=';') - -**지원 옵션:** -- `separator`: 구분자 (기본값: ',') -- `include_header`: 헤더 포함 여부 (기본값: True) - -Parquet -~~~~~~~ - -.. code-block:: python - - # Parquet 저장 - atio.write(df, "users.parquet", format="parquet") - - # 압축과 함께 저장 - atio.write(df, "users.parquet", format="parquet", - compression="snappy") - -**지원 옵션:** -- `compression`: 압축 방식 ('snappy', 'gzip', 'brotli', 'lz4raw', 'zstd', None) - -JSON -~~~~ - -.. code-block:: python - - # JSON 저장 - atio.write(df, "users.json", format="json") - - # 파일별 저장 - atio.write(df, "users.json", format="json", - file=True) - -**지원 옵션:** -- `file`: 파일별 저장 여부 (기본값: False) - -IPC (Arrow) -~~~~~~~~~~~ - -.. code-block:: python - - # IPC (Arrow) 형식으로 저장 - atio.write(df, "users.arrow", format="ipc") - - # 압축과 함께 저장 - atio.write(df, "users.arrow", format="ipc", - compression="lz4") - -**지원 옵션:** -- `compression`: 압축 방식 ('lz4', 'zstd', None) - -Avro -~~~~ - -.. code-block:: python - - # Avro 형식으로 저장 - atio.write(df, "users.avro", format="avro") - -**필요 라이브러리:** `pip install fastavro` - -Excel -~~~~~ - -.. code-block:: python - - # Excel 저장 - atio.write(df, "users.xlsx", format="excel") - -**필요 라이브러리:** `pip install xlsx2csv openpyxl` - -Database -~~~~~~~~ - -.. code-block:: python - - # 데이터베이스에 저장 - atio.write(df, format="database", - table_name="users", - connection_uri="postgresql://user:password@localhost/dbname") - -**지원 옵션:** -- `table_name`: 테이블 이름 (필수) -- `connection_uri`: 데이터베이스 연결 URI (필수) - -**필요 라이브러리:** `pip install connectorx` - -NumPy 배열 형식 --------------- - -NumPy 배열은 수치 데이터 처리에 최적화된 형식을 지원합니다. - -NPY (NumPy Binary) -~~~~~~~~~~~~~~~~~~ - -.. code-block:: python - - import atio - import numpy as np - - arr = np.array([[1, 2, 3], [4, 5, 6]]) - - # .npy 파일로 저장 - atio.write(arr, "array.npy", format="npy") - -**특징:** -- 단일 배열을 효율적으로 저장 -- 메타데이터와 함께 저장 -- 빠른 읽기/쓰기 속도 - -NPZ (NumPy Compressed) -~~~~~~~~~~~~~~~~~~~~~~ - -.. code-block:: python - - # 여러 배열을 딕셔너리로 저장 - arrays = { - "features": np.random.randn(1000, 10), - "labels": np.random.randint(0, 2, 1000), - "metadata": np.array([1, 2, 3, 4, 5]) - } - - # 압축되지 않은 .npz 파일로 저장 - atio.write(arrays, "data.npz", format="npz") - - # 압축된 .npz 파일로 저장 - atio.write(arrays, "data.npz", format="npz_compressed") - -**특징:** -- 여러 배열을 하나의 파일에 저장 -- 압축 옵션으로 저장 공간 절약 -- 딕셔너리 형태로 데이터 구조화 - -CSV -~~~ - -.. code-block:: python - - # CSV로 저장 - atio.write(arr, "array.csv", format="csv") - - # 구분자와 함께 저장 - atio.write(arr, "array.csv", format="csv", - delimiter=';', - fmt='%.2f') - -**지원 옵션:** -- `delimiter`: 구분자 (기본값: ',') -- `fmt`: 숫자 형식 (예: '%.2f', '%.4e') -- `header`: 헤더 포함 여부 -- `comments`: 주석 문자 - -형식별 성능 비교 ----------------- - -다양한 형식의 성능 특성을 비교해보겠습니다. - -속도 비교 -~~~~~~~~~ - -1. **가장 빠른 형식:** - - NumPy: `.npy`, `.npz` - - Polars: `.ipc` (Arrow) - - Pandas: `.parquet` (snappy 압축) - -2. **중간 속도:** - - CSV (단순한 구조) - - JSON (중간 복잡도) - -3. **상대적으로 느린 형식:** - - Excel (복잡한 구조) - - Pickle (Python 특화) - -용량 비교 -~~~~~~~~~ - -1. **가장 작은 용량:** - - `.parquet` (컬럼 기반 압축) - - `.npz_compressed` (압축된 NumPy) - - `.ipc` (Arrow 압축) - -2. **중간 용량:** - - `.npy` (단일 배열) - - JSON (텍스트 기반) - -3. **상대적으로 큰 용량:** - - CSV (텍스트 기반) - - Excel (복잡한 구조) - -호환성 비교 -~~~~~~~~~~~ - -1. **최고 호환성:** - - CSV (모든 시스템에서 지원) - - JSON (웹 표준) - -2. **좋은 호환성:** - - Excel (비즈니스 환경) - - Parquet (빅데이터 생태계) - -3. **제한적 호환성:** - - `.npy`/`.npz` (Python/NumPy 특화) - - `.ipc` (Arrow 생태계) - -권장 사용 사례 -------------- - -데이터 분석 및 머신러닝 -~~~~~~~~~~~~~~~~~~~~~~ - -.. code-block:: python - - # 학습 데이터: 빠른 읽기/쓰기를 위해 Parquet 사용 - atio.write(training_data, "train.parquet", format="parquet") - - # 모델 가중치: NumPy 배열로 저장 - atio.write(model_weights, "weights.npy", format="npy") - - # 실험 결과: JSON으로 저장 (가독성) - atio.write(results, "experiment_results.json", format="json") - -웹 애플리케이션 -~~~~~~~~~~~~~~ - -.. code-block:: python - - # API 응답: JSON 형식 - atio.write(api_data, "response.json", format="json") - - # 대용량 데이터: Parquet 형식 - atio.write(large_dataset, "dataset.parquet", format="parquet") - -데이터 파이프라인 -~~~~~~~~~~~~~~~~ - -.. code-block:: python - - # 중간 결과: 빠른 처리를 위해 IPC 사용 - atio.write(intermediate_data, "step1.arrow", format="ipc") - - # 최종 결과: 호환성을 위해 CSV 사용 - atio.write(final_data, "output.csv", format="csv") - -비즈니스 보고서 -~~~~~~~~~~~~~~ - -.. code-block:: python - - # 엑셀 보고서 - atio.write(report_data, "monthly_report.xlsx", format="excel") - - # HTML 대시보드 - atio.write(dashboard_data, "dashboard.html", format="html") - -형식 확장하기 ------------- - -새로운 형식을 추가하려면 플러그인 시스템을 사용하세요. - -.. code-block:: python - - from atio.plugins import register_writer - import pandas as pd - - # 커스텀 형식 등록 - def yaml_writer(df, path, **kwargs): - import yaml - data = df.to_dict('records') - with open(path, 'w') as f: - yaml.dump(data, f, **kwargs) - - # 등록 - register_writer(pd.DataFrame, "yaml", yaml_writer) - - # 사용 - atio.write(df, "data.yaml", format="yaml") \ No newline at end of file diff --git a/docs/build/html/_sources/index.rst.txt b/docs/build/html/_sources/index.rst.txt deleted file mode 100644 index b078eb6..0000000 --- a/docs/build/html/_sources/index.rst.txt +++ /dev/null @@ -1,165 +0,0 @@ -Atio Documentation -================== - -**Atio** 🛡️는 안전하고 원자적인 파일 쓰기를 지원하는 경량 Python 라이브러리입니다. - -Pandas, Polars, NumPy 등 데이터 객체 저장 시 **파일 손상 없이**, **트랜잭션처럼 안전하게 처리**할 수 있습니다. - -주요 기능 ---------- - -🔒 **Atomic File Writing** - Safe writing using temporary files - -📊 **Multiple Format Support** - CSV, Parquet, Excel, JSON, etc. - -🗄️ **Database Support** - Direct SQL and Database writing - -📈 **Progress Display** - Progress monitoring for large data processing - -🔄 **Rollback Function** - Automatic recovery when errors occur - -🎯 **Simple API** - Intuitive and easy-to-use interface - -📋 **Version Management** - Snapshot-based data version management - -🧹 **Auto Cleanup** - Automatic deletion of old data - -빠른 시작 ---------- - -.. code-block:: python - - import atio - import pandas as pd - - # 간단한 DataFrame 생성 - df = pd.DataFrame({ - "name": ["Alice", "Bob", "Charlie"], - "age": [25, 30, 35], - "city": ["Seoul", "Busan", "Incheon"] - }) - - # 안전한 파일 쓰기 - atio.write(df, "users.parquet", format="parquet") - - # 진행도 표시와 함께 저장 - atio.write(df, "users.csv", format="csv", show_progress=True) - -지원하는 형식 ------------- - -.. list-table:: 지원하는 파일 형식 - :widths: 20 20 20 20 - :header-rows: 1 - - * - 형식 - - Pandas - - Polars - - NumPy - * - CSV - - ✅ - - ✅ - - ✅ - * - Parquet - - ✅ - - ✅ - - ❌ - * - Excel - - ✅ - - ✅ - - ❌ - * - JSON - - ✅ - - ✅ - - ❌ - * - Pickle - - ✅ - - ❌ - - ❌ - * - HTML - - ✅ - - ❌ - - ❌ - * - SQL - - ✅ - - ❌ - - ❌ - * - Database - - ❌ - - ✅ - - ❌ - * - NPY/NPZ - - ❌ - - ❌ - - ✅ - -사용 사례 --------- - -🔹 **데이터 파이프라인** - ETL 과정에서 중간 데이터 안전하게 저장 - -🔹 **실험 데이터 관리** - 머신러닝 실험 결과의 버전 관리 - -🔹 **대용량 데이터 처리** - 대용량 파일의 안전한 저장 및 진행도 모니터링 - -🔹 **데이터베이스 연동** - Pandas/Polars 데이터를 SQL/NoSQL DB에 안전하게 저장 - -목차 ----- - -.. toctree:: - :maxdepth: 2 - :caption: 사용자 가이드: - - installation - quickstart - examples - advanced_usage - -.. toctree:: - :maxdepth: 2 - :caption: API 참조: - - api - configuration - -API Reference -============= - -핵심 함수들 ------------ - -.. automodule:: atio - :members: - :undoc-members: - -.. automodule:: atio.core - :members: - :undoc-members: - -.. automodule:: atio.plugins - :members: - :undoc-members: - -.. automodule:: atio.utils - :members: - :undoc-members: - -Indices and tables -================== - -* :ref:`genindex` -* :ref:`modindex` -* :ref:`search` diff --git a/docs/build/html/_sources/installation.rst.txt b/docs/build/html/_sources/installation.rst.txt deleted file mode 100644 index eb0162b..0000000 --- a/docs/build/html/_sources/installation.rst.txt +++ /dev/null @@ -1,199 +0,0 @@ -설치 가이드 -========== - -Atio를 설치하는 방법을 안내합니다. - -PyPI를 통한 설치 ----------------- - -가장 간단한 설치 방법은 PyPI를 사용하는 것입니다: - -.. code-block:: bash - - pip install atio - -특정 버전 설치 -~~~~~~~~~~~~~ - -특정 버전을 설치하려면: - -.. code-block:: bash - - pip install atio==2.0.0 - -개발 버전 설치 -~~~~~~~~~~~~~ - -최신 개발 버전을 설치하려면: - -.. code-block:: bash - - pip install git+https://github.com/seojaeohcode/atio.git - -의존성 ------- - -필수 의존성 -~~~~~~~~~~ - -- Python 3.8+ -- pandas -- numpy - -선택적 의존성 -~~~~~~~~~~~~ - -특정 형식을 사용하려면 추가 라이브러리가 필요합니다: - -**Parquet 형식:** -.. code-block:: bash - - pip install pyarrow - # 또는 - pip install fastparquet - -**Excel 형식:** -.. code-block:: bash - - pip install openpyxl - # 또는 - pip install xlsxwriter - -**SQL 데이터베이스:** -.. code-block:: bash - - pip install sqlalchemy - -**Polars 지원:** -.. code-block:: bash - - pip install polars - -**Avro 형식 (Polars):** -.. code-block:: bash - - pip install fastavro - -**Polars Excel 지원:** -.. code-block:: bash - - pip install xlsx2csv openpyxl - -**Polars 데이터베이스 지원:** -.. code-block:: bash - - pip install connectorx - -모든 의존성 설치 -~~~~~~~~~~~~~~~ - -모든 기능을 사용하려면: - -.. code-block:: bash - - pip install atio[all] - -또는 개별적으로: - -.. code-block:: bash - - pip install atio - pip install pyarrow openpyxl sqlalchemy polars fastavro xlsx2csv connectorx - -환경 확인 ---------- - -설치가 완료되었는지 확인하려면: - -.. code-block:: python - - import atio - print(f"Atio 버전: {atio.__version__}") - - # 기본 기능 테스트 - import pandas as pd - df = pd.DataFrame({"test": [1, 2, 3]}) - atio.write(df, "test.parquet", format="parquet") - print("설치가 성공적으로 완료되었습니다!") - -가상환경 사용 권장 ------------------ - -프로젝트별로 독립적인 환경을 유지하기 위해 가상환경 사용을 권장합니다: - -.. code-block:: bash - - # 가상환경 생성 - python -m venv atio_env - - # 가상환경 활성화 (Windows) - atio_env\Scripts\activate - - # 가상환경 활성화 (macOS/Linux) - source atio_env/bin/activate - - # Atio 설치 - pip install atio - -Conda 사용 ---------- - -Conda를 사용하는 경우: - -.. code-block:: bash - - # Conda 환경 생성 - conda create -n atio_env python=3.8 - conda activate atio_env - - # Atio 설치 - pip install atio - -문제 해결 ---------- - -설치 중 문제가 발생하는 경우: - -**권한 오류:** -.. code-block:: bash - - pip install atio --user - -**캐시 문제:** -.. code-block:: bash - - pip install atio --no-cache-dir - -**의존성 충돌:** -.. code-block:: bash - - pip install atio --force-reinstall - -**특정 Python 버전:** -.. code-block:: bash - - python3.8 -m pip install atio - -업그레이드 ----------- - -최신 버전으로 업그레이드: - -.. code-block:: bash - - pip install --upgrade atio - -특정 버전으로 다운그레이드: - -.. code-block:: bash - - pip install atio==1.0.0 - -제거 ----- - -Atio를 제거하려면: - -.. code-block:: bash - - pip uninstall atio \ No newline at end of file diff --git a/docs/build/html/_sources/quickstart.rst.txt b/docs/build/html/_sources/quickstart.rst.txt deleted file mode 100644 index 12b7060..0000000 --- a/docs/build/html/_sources/quickstart.rst.txt +++ /dev/null @@ -1,126 +0,0 @@ -빠른 시작 -========== - -Atio를 사용하여 안전한 파일 쓰기를 시작해보세요. - -기본 사용법 ----------- - -가장 간단한 사용법부터 시작해보겠습니다: - -.. code-block:: python - - import atio - import pandas as pd - - # 샘플 데이터 생성 - df = pd.DataFrame({ - "name": ["Alice", "Bob", "Charlie"], - "age": [25, 30, 35], - "city": ["Seoul", "Busan", "Incheon"] - }) - - # 안전한 파일 쓰기 - atio.write(df, "users.parquet", format="parquet") - -이 코드는 다음과 같은 안전장치를 제공합니다: - -- ✅ 임시 파일에 먼저 저장 -- ✅ 저장 완료 후 원자적으로 파일 교체 -- ✅ 실패 시 원본 파일 보존 -- ✅ `_SUCCESS` 플래그 파일 생성 - -다양한 형식 지원 ---------------- - -Atio는 다양한 데이터 형식을 지원합니다: - -.. code-block:: python - - # CSV 형식 - atio.write(df, "users.csv", format="csv", index=False) - - # Excel 형식 - atio.write(df, "users.xlsx", format="excel", sheet_name="Users") - - # JSON 형식 - atio.write(df, "users.json", format="json", orient="records") - - # Parquet 형식 (권장) - atio.write(df, "users.parquet", format="parquet") - -진행률 표시 ----------- - -대용량 데이터 처리 시 진행률을 확인할 수 있습니다: - -.. code-block:: python - - # 진행률 표시 활성화 - atio.write(large_df, "big_data.parquet", format="parquet", show_progress=True) - -성능 모니터링 ------------- - -상세한 성능 정보를 확인하려면: - -.. code-block:: python - - # 성능 정보 출력 - atio.write(df, "data.parquet", format="parquet", verbose=True) - -Polars DataFrame 지원 -------------------- - -Polars DataFrame도 지원합니다: - -.. code-block:: python - - import polars as pl - - # Polars DataFrame 생성 - polars_df = pl.DataFrame({ - "a": [1, 2, 3], - "b": [4, 5, 6] - }) - - # Polars DataFrame 저장 - atio.write(polars_df, "data.parquet", format="parquet") - -데이터베이스 저장 ---------------- - -SQL 데이터베이스에 직접 저장할 수도 있습니다: - -.. code-block:: python - - from sqlalchemy import create_engine - - # 데이터베이스 연결 - engine = create_engine('postgresql://user:password@localhost/dbname') - - # 데이터베이스에 저장 - atio.write(df, format="sql", name="users", con=engine, if_exists="replace") - -스냅샷 기능 ----------- - -데이터 버전 관리를 위한 스냅샷 기능: - -.. code-block:: python - - # 스냅샷 생성 - atio.write_snapshot(df, "users", format="parquet") - - # 스냅샷 읽기 - df = atio.read_table("users", snapshot_id="latest") - - # 오래된 스냅샷 정리 - atio.expire_snapshots("users", days=30) - -다음 단계 --------- - -- :doc:`api` - 전체 API 참조 -- :doc:`examples` - 고급 사용 예제 -- :doc:`installation` - 설치 가이드 \ No newline at end of file diff --git a/docs/build/html/_static/_sphinx_javascript_frameworks_compat.js b/docs/build/html/_static/_sphinx_javascript_frameworks_compat.js deleted file mode 100644 index 8141580..0000000 --- a/docs/build/html/_static/_sphinx_javascript_frameworks_compat.js +++ /dev/null @@ -1,123 +0,0 @@ -/* Compatability shim for jQuery and underscores.js. - * - * Copyright Sphinx contributors - * Released under the two clause BSD licence - */ - -/** - * small helper function to urldecode strings - * - * See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/decodeURIComponent#Decoding_query_parameters_from_a_URL - */ -jQuery.urldecode = function(x) { - if (!x) { - return x - } - return decodeURIComponent(x.replace(/\+/g, ' ')); -}; - -/** - * small helper function to urlencode strings - */ -jQuery.urlencode = encodeURIComponent; - -/** - * This function returns the parsed url parameters of the - * current request. Multiple values per key are supported, - * it will always return arrays of strings for the value parts. - */ -jQuery.getQueryParameters = function(s) { - if (typeof s === 'undefined') - s = document.location.search; - var parts = s.substr(s.indexOf('?') + 1).split('&'); - var result = {}; - for (var i = 0; i < parts.length; i++) { - var tmp = parts[i].split('=', 2); - var key = jQuery.urldecode(tmp[0]); - var value = jQuery.urldecode(tmp[1]); - if (key in result) - result[key].push(value); - else - result[key] = [value]; - } - return result; -}; - -/** - * highlight a given string on a jquery object by wrapping it in - * span elements with the given class name. - */ -jQuery.fn.highlightText = function(text, className) { - function highlight(node, addItems) { - if (node.nodeType === 3) { - var val = node.nodeValue; - var pos = val.toLowerCase().indexOf(text); - if (pos >= 0 && - !jQuery(node.parentNode).hasClass(className) && - !jQuery(node.parentNode).hasClass("nohighlight")) { - var span; - var isInSVG = jQuery(node).closest("body, svg, foreignObject").is("svg"); - if (isInSVG) { - span = document.createElementNS("http://www.w3.org/2000/svg", "tspan"); - } else { - span = document.createElement("span"); - span.className = className; - } - span.appendChild(document.createTextNode(val.substr(pos, text.length))); - node.parentNode.insertBefore(span, node.parentNode.insertBefore( - document.createTextNode(val.substr(pos + text.length)), - node.nextSibling)); - node.nodeValue = val.substr(0, pos); - if (isInSVG) { - var rect = document.createElementNS("http://www.w3.org/2000/svg", "rect"); - var bbox = node.parentElement.getBBox(); - rect.x.baseVal.value = bbox.x; - rect.y.baseVal.value = bbox.y; - rect.width.baseVal.value = bbox.width; - rect.height.baseVal.value = bbox.height; - rect.setAttribute('class', className); - addItems.push({ - "parent": node.parentNode, - "target": rect}); - } - } - } - else if (!jQuery(node).is("button, select, textarea")) { - jQuery.each(node.childNodes, function() { - highlight(this, addItems); - }); - } - } - var addItems = []; - var result = this.each(function() { - highlight(this, addItems); - }); - for (var i = 0; i < addItems.length; ++i) { - jQuery(addItems[i].parent).before(addItems[i].target); - } - return result; -}; - -/* - * backward compatibility for jQuery.browser - * This will be supported until firefox bug is fixed. - */ -if (!jQuery.browser) { - jQuery.uaMatch = function(ua) { - ua = ua.toLowerCase(); - - var match = /(chrome)[ \/]([\w.]+)/.exec(ua) || - /(webkit)[ \/]([\w.]+)/.exec(ua) || - /(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) || - /(msie) ([\w.]+)/.exec(ua) || - ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) || - []; - - return { - browser: match[ 1 ] || "", - version: match[ 2 ] || "0" - }; - }; - jQuery.browser = {}; - jQuery.browser[jQuery.uaMatch(navigator.userAgent).browser] = true; -} diff --git a/docs/build/html/_static/basic.css b/docs/build/html/_static/basic.css deleted file mode 100644 index 4738b2e..0000000 --- a/docs/build/html/_static/basic.css +++ /dev/null @@ -1,906 +0,0 @@ -/* - * Sphinx stylesheet -- basic theme. - */ - -/* -- main layout ----------------------------------------------------------- */ - -div.clearer { - clear: both; -} - -div.section::after { - display: block; - content: ''; - clear: left; -} - -/* -- relbar ---------------------------------------------------------------- */ - -div.related { - width: 100%; - font-size: 90%; -} - -div.related h3 { - display: none; -} - -div.related ul { - margin: 0; - padding: 0 0 0 10px; - list-style: none; -} - -div.related li { - display: inline; -} - -div.related li.right { - float: right; - margin-right: 5px; -} - -/* -- sidebar --------------------------------------------------------------- */ - -div.sphinxsidebarwrapper { - padding: 10px 5px 0 10px; -} - -div.sphinxsidebar { - float: left; - width: 230px; - margin-left: -100%; - font-size: 90%; - word-wrap: break-word; - overflow-wrap : break-word; -} - -div.sphinxsidebar ul { - list-style: none; -} - -div.sphinxsidebar ul ul, -div.sphinxsidebar ul.want-points { - margin-left: 20px; - list-style: square; -} - -div.sphinxsidebar ul ul { - margin-top: 0; - margin-bottom: 0; -} - -div.sphinxsidebar form { - margin-top: 10px; -} - -div.sphinxsidebar input { - border: 1px solid #98dbcc; - font-family: sans-serif; - font-size: 1em; -} - -div.sphinxsidebar #searchbox form.search { - overflow: hidden; -} - -div.sphinxsidebar #searchbox input[type="text"] { - float: left; - width: 80%; - padding: 0.25em; - box-sizing: border-box; -} - -div.sphinxsidebar #searchbox input[type="submit"] { - float: left; - width: 20%; - border-left: none; - padding: 0.25em; - box-sizing: border-box; -} - - -img { - border: 0; - max-width: 100%; -} - -/* -- search page ----------------------------------------------------------- */ - -ul.search { - margin-top: 10px; -} - -ul.search li { - padding: 5px 0; -} - -ul.search li a { - font-weight: bold; -} - -ul.search li p.context { - color: #888; - margin: 2px 0 0 30px; - text-align: left; -} - -ul.keywordmatches li.goodmatch a { - font-weight: bold; -} - -/* -- index page ------------------------------------------------------------ */ - -table.contentstable { - width: 90%; - margin-left: auto; - margin-right: auto; -} - -table.contentstable p.biglink { - line-height: 150%; -} - -a.biglink { - font-size: 1.3em; -} - -span.linkdescr { - font-style: italic; - padding-top: 5px; - font-size: 90%; -} - -/* -- general index --------------------------------------------------------- */ - -table.indextable { - width: 100%; -} - -table.indextable td { - text-align: left; - vertical-align: top; -} - -table.indextable ul { - margin-top: 0; - margin-bottom: 0; - list-style-type: none; -} - -table.indextable > tbody > tr > td > ul { - padding-left: 0em; -} - -table.indextable tr.pcap { - height: 10px; -} - -table.indextable tr.cap { - margin-top: 10px; - background-color: #f2f2f2; -} - -img.toggler { - margin-right: 3px; - margin-top: 3px; - cursor: pointer; -} - -div.modindex-jumpbox { - border-top: 1px solid #ddd; - border-bottom: 1px solid #ddd; - margin: 1em 0 1em 0; - padding: 0.4em; -} - -div.genindex-jumpbox { - border-top: 1px solid #ddd; - border-bottom: 1px solid #ddd; - margin: 1em 0 1em 0; - padding: 0.4em; -} - -/* -- domain module index --------------------------------------------------- */ - -table.modindextable td { - padding: 2px; - border-collapse: collapse; -} - -/* -- general body styles --------------------------------------------------- */ - -div.body { - min-width: 360px; - max-width: 800px; -} - -div.body p, div.body dd, div.body li, div.body blockquote { - -moz-hyphens: auto; - -ms-hyphens: auto; - -webkit-hyphens: auto; - hyphens: auto; -} - -a.headerlink { - visibility: hidden; -} - -a:visited { - color: #551A8B; -} - -h1:hover > a.headerlink, -h2:hover > a.headerlink, -h3:hover > a.headerlink, -h4:hover > a.headerlink, -h5:hover > a.headerlink, -h6:hover > a.headerlink, -dt:hover > a.headerlink, -caption:hover > a.headerlink, -p.caption:hover > a.headerlink, -div.code-block-caption:hover > a.headerlink { - visibility: visible; -} - -div.body p.caption { - text-align: inherit; -} - -div.body td { - text-align: left; -} - -.first { - margin-top: 0 !important; -} - -p.rubric { - margin-top: 30px; - font-weight: bold; -} - -img.align-left, figure.align-left, .figure.align-left, object.align-left { - clear: left; - float: left; - margin-right: 1em; -} - -img.align-right, figure.align-right, .figure.align-right, object.align-right { - clear: right; - float: right; - margin-left: 1em; -} - -img.align-center, figure.align-center, .figure.align-center, object.align-center { - display: block; - margin-left: auto; - margin-right: auto; -} - -img.align-default, figure.align-default, .figure.align-default { - display: block; - margin-left: auto; - margin-right: auto; -} - -.align-left { - text-align: left; -} - -.align-center { - text-align: center; -} - -.align-default { - text-align: center; -} - -.align-right { - text-align: right; -} - -/* -- sidebars -------------------------------------------------------------- */ - -div.sidebar, -aside.sidebar { - margin: 0 0 0.5em 1em; - border: 1px solid #ddb; - padding: 7px; - background-color: #ffe; - width: 40%; - float: right; - clear: right; - overflow-x: auto; -} - -p.sidebar-title { - font-weight: bold; -} - -nav.contents, -aside.topic, -div.admonition, div.topic, blockquote { - clear: left; -} - -/* -- topics ---------------------------------------------------------------- */ - -nav.contents, -aside.topic, -div.topic { - border: 1px solid #ccc; - padding: 7px; - margin: 10px 0 10px 0; -} - -p.topic-title { - font-size: 1.1em; - font-weight: bold; - margin-top: 10px; -} - -/* -- admonitions ----------------------------------------------------------- */ - -div.admonition { - margin-top: 10px; - margin-bottom: 10px; - padding: 7px; -} - -div.admonition dt { - font-weight: bold; -} - -p.admonition-title { - margin: 0px 10px 5px 0px; - font-weight: bold; -} - -div.body p.centered { - text-align: center; - margin-top: 25px; -} - -/* -- content of sidebars/topics/admonitions -------------------------------- */ - -div.sidebar > :last-child, -aside.sidebar > :last-child, -nav.contents > :last-child, -aside.topic > :last-child, -div.topic > :last-child, -div.admonition > :last-child { - margin-bottom: 0; -} - -div.sidebar::after, -aside.sidebar::after, -nav.contents::after, -aside.topic::after, -div.topic::after, -div.admonition::after, -blockquote::after { - display: block; - content: ''; - clear: both; -} - -/* -- tables ---------------------------------------------------------------- */ - -table.docutils { - margin-top: 10px; - margin-bottom: 10px; - border: 0; - border-collapse: collapse; -} - -table.align-center { - margin-left: auto; - margin-right: auto; -} - -table.align-default { - margin-left: auto; - margin-right: auto; -} - -table caption span.caption-number { - font-style: italic; -} - -table caption span.caption-text { -} - -table.docutils td, table.docutils th { - padding: 1px 8px 1px 5px; - border-top: 0; - border-left: 0; - border-right: 0; - border-bottom: 1px solid #aaa; -} - -th { - text-align: left; - padding-right: 5px; -} - -table.citation { - border-left: solid 1px gray; - margin-left: 1px; -} - -table.citation td { - border-bottom: none; -} - -th > :first-child, -td > :first-child { - margin-top: 0px; -} - -th > :last-child, -td > :last-child { - margin-bottom: 0px; -} - -/* -- figures --------------------------------------------------------------- */ - -div.figure, figure { - margin: 0.5em; - padding: 0.5em; -} - -div.figure p.caption, figcaption { - padding: 0.3em; -} - -div.figure p.caption span.caption-number, -figcaption span.caption-number { - font-style: italic; -} - -div.figure p.caption span.caption-text, -figcaption span.caption-text { -} - -/* -- field list styles ----------------------------------------------------- */ - -table.field-list td, table.field-list th { - border: 0 !important; -} - -.field-list ul { - margin: 0; - padding-left: 1em; -} - -.field-list p { - margin: 0; -} - -.field-name { - -moz-hyphens: manual; - -ms-hyphens: manual; - -webkit-hyphens: manual; - hyphens: manual; -} - -/* -- hlist styles ---------------------------------------------------------- */ - -table.hlist { - margin: 1em 0; -} - -table.hlist td { - vertical-align: top; -} - -/* -- object description styles --------------------------------------------- */ - -.sig { - font-family: 'Consolas', 'Menlo', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; -} - -.sig-name, code.descname { - background-color: transparent; - font-weight: bold; -} - -.sig-name { - font-size: 1.1em; -} - -code.descname { - font-size: 1.2em; -} - -.sig-prename, code.descclassname { - background-color: transparent; -} - -.optional { - font-size: 1.3em; -} - -.sig-paren { - font-size: larger; -} - -.sig-param.n { - font-style: italic; -} - -/* C++ specific styling */ - -.sig-inline.c-texpr, -.sig-inline.cpp-texpr { - font-family: unset; -} - -.sig.c .k, .sig.c .kt, -.sig.cpp .k, .sig.cpp .kt { - color: #0033B3; -} - -.sig.c .m, -.sig.cpp .m { - color: #1750EB; -} - -.sig.c .s, .sig.c .sc, -.sig.cpp .s, .sig.cpp .sc { - color: #067D17; -} - - -/* -- other body styles ----------------------------------------------------- */ - -ol.arabic { - list-style: decimal; -} - -ol.loweralpha { - list-style: lower-alpha; -} - -ol.upperalpha { - list-style: upper-alpha; -} - -ol.lowerroman { - list-style: lower-roman; -} - -ol.upperroman { - list-style: upper-roman; -} - -:not(li) > ol > li:first-child > :first-child, -:not(li) > ul > li:first-child > :first-child { - margin-top: 0px; -} - -:not(li) > ol > li:last-child > :last-child, -:not(li) > ul > li:last-child > :last-child { - margin-bottom: 0px; -} - -ol.simple ol p, -ol.simple ul p, -ul.simple ol p, -ul.simple ul p { - margin-top: 0; -} - -ol.simple > li:not(:first-child) > p, -ul.simple > li:not(:first-child) > p { - margin-top: 0; -} - -ol.simple p, -ul.simple p { - margin-bottom: 0; -} - -aside.footnote > span, -div.citation > span { - float: left; -} -aside.footnote > span:last-of-type, -div.citation > span:last-of-type { - padding-right: 0.5em; -} -aside.footnote > p { - margin-left: 2em; -} -div.citation > p { - margin-left: 4em; -} -aside.footnote > p:last-of-type, -div.citation > p:last-of-type { - margin-bottom: 0em; -} -aside.footnote > p:last-of-type:after, -div.citation > p:last-of-type:after { - content: ""; - clear: both; -} - -dl.field-list { - display: grid; - grid-template-columns: fit-content(30%) auto; -} - -dl.field-list > dt { - font-weight: bold; - word-break: break-word; - padding-left: 0.5em; - padding-right: 5px; -} - -dl.field-list > dd { - padding-left: 0.5em; - margin-top: 0em; - margin-left: 0em; - margin-bottom: 0em; -} - -dl { - margin-bottom: 15px; -} - -dd > :first-child { - margin-top: 0px; -} - -dd ul, dd table { - margin-bottom: 10px; -} - -dd { - margin-top: 3px; - margin-bottom: 10px; - margin-left: 30px; -} - -.sig dd { - margin-top: 0px; - margin-bottom: 0px; -} - -.sig dl { - margin-top: 0px; - margin-bottom: 0px; -} - -dl > dd:last-child, -dl > dd:last-child > :last-child { - margin-bottom: 0; -} - -dt:target, span.highlighted { - background-color: #fbe54e; -} - -rect.highlighted { - fill: #fbe54e; -} - -dl.glossary dt { - font-weight: bold; - font-size: 1.1em; -} - -.versionmodified { - font-style: italic; -} - -.system-message { - background-color: #fda; - padding: 5px; - border: 3px solid red; -} - -.footnote:target { - background-color: #ffa; -} - -.line-block { - display: block; - margin-top: 1em; - margin-bottom: 1em; -} - -.line-block .line-block { - margin-top: 0; - margin-bottom: 0; - margin-left: 1.5em; -} - -.guilabel, .menuselection { - font-family: sans-serif; -} - -.accelerator { - text-decoration: underline; -} - -.classifier { - font-style: oblique; -} - -.classifier:before { - font-style: normal; - margin: 0 0.5em; - content: ":"; - display: inline-block; -} - -abbr, acronym { - border-bottom: dotted 1px; - cursor: help; -} - -/* -- code displays --------------------------------------------------------- */ - -pre { - overflow: auto; - overflow-y: hidden; /* fixes display issues on Chrome browsers */ -} - -pre, div[class*="highlight-"] { - clear: both; -} - -span.pre { - -moz-hyphens: none; - -ms-hyphens: none; - -webkit-hyphens: none; - hyphens: none; - white-space: nowrap; -} - -div[class*="highlight-"] { - margin: 1em 0; -} - -td.linenos pre { - border: 0; - background-color: transparent; - color: #aaa; -} - -table.highlighttable { - display: block; -} - -table.highlighttable tbody { - display: block; -} - -table.highlighttable tr { - display: flex; -} - -table.highlighttable td { - margin: 0; - padding: 0; -} - -table.highlighttable td.linenos { - padding-right: 0.5em; -} - -table.highlighttable td.code { - flex: 1; - overflow: hidden; -} - -.highlight .hll { - display: block; -} - -div.highlight pre, -table.highlighttable pre { - margin: 0; -} - -div.code-block-caption + div { - margin-top: 0; -} - -div.code-block-caption { - margin-top: 1em; - padding: 2px 5px; - font-size: small; -} - -div.code-block-caption code { - background-color: transparent; -} - -table.highlighttable td.linenos, -span.linenos, -div.highlight span.gp { /* gp: Generic.Prompt */ - user-select: none; - -webkit-user-select: text; /* Safari fallback only */ - -webkit-user-select: none; /* Chrome/Safari */ - -moz-user-select: none; /* Firefox */ - -ms-user-select: none; /* IE10+ */ -} - -div.code-block-caption span.caption-number { - padding: 0.1em 0.3em; - font-style: italic; -} - -div.code-block-caption span.caption-text { -} - -div.literal-block-wrapper { - margin: 1em 0; -} - -code.xref, a code { - background-color: transparent; - font-weight: bold; -} - -h1 code, h2 code, h3 code, h4 code, h5 code, h6 code { - background-color: transparent; -} - -.viewcode-link { - float: right; -} - -.viewcode-back { - float: right; - font-family: sans-serif; -} - -div.viewcode-block:target { - margin: -1px -10px; - padding: 0 10px; -} - -/* -- math display ---------------------------------------------------------- */ - -img.math { - vertical-align: middle; -} - -div.body div.math p { - text-align: center; -} - -span.eqno { - float: right; -} - -span.eqno a.headerlink { - position: absolute; - z-index: 1; -} - -div.math:hover a.headerlink { - visibility: visible; -} - -/* -- printout stylesheet --------------------------------------------------- */ - -@media print { - div.document, - div.documentwrapper, - div.bodywrapper { - margin: 0 !important; - width: 100%; - } - - div.sphinxsidebar, - div.related, - div.footer, - #top-link { - display: none; - } -} \ No newline at end of file diff --git a/docs/build/html/_static/css/badge_only.css b/docs/build/html/_static/css/badge_only.css deleted file mode 100644 index 88ba55b..0000000 --- a/docs/build/html/_static/css/badge_only.css +++ /dev/null @@ -1 +0,0 @@ -.clearfix{*zoom:1}.clearfix:after,.clearfix:before{display:table;content:""}.clearfix:after{clear:both}@font-face{font-family:FontAwesome;font-style:normal;font-weight:400;src:url(fonts/fontawesome-webfont.eot?674f50d287a8c48dc19ba404d20fe713?#iefix) format("embedded-opentype"),url(fonts/fontawesome-webfont.woff2?af7ae505a9eed503f8b8e6982036873e) format("woff2"),url(fonts/fontawesome-webfont.woff?fee66e712a8a08eef5805a46892932ad) format("woff"),url(fonts/fontawesome-webfont.ttf?b06871f281fee6b241d60582ae9369b9) format("truetype"),url(fonts/fontawesome-webfont.svg?912ec66d7572ff821749319396470bde#FontAwesome) format("svg")}.fa:before{font-family:FontAwesome;font-style:normal;font-weight:400;line-height:1}.fa:before,a .fa{text-decoration:inherit}.fa:before,a .fa,li .fa{display:inline-block}li .fa-large:before{width:1.875em}ul.fas{list-style-type:none;margin-left:2em;text-indent:-.8em}ul.fas li .fa{width:.8em}ul.fas li .fa-large:before{vertical-align:baseline}.fa-book:before,.icon-book:before{content:"\f02d"}.fa-caret-down:before,.icon-caret-down:before{content:"\f0d7"}.fa-caret-up:before,.icon-caret-up:before{content:"\f0d8"}.fa-caret-left:before,.icon-caret-left:before{content:"\f0d9"}.fa-caret-right:before,.icon-caret-right:before{content:"\f0da"}.rst-versions{position:fixed;bottom:0;left:0;width:300px;color:#fcfcfc;background:#1f1d1d;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;z-index:400}.rst-versions a{color:#2980b9;text-decoration:none}.rst-versions .rst-badge-small{display:none}.rst-versions .rst-current-version{padding:12px;background-color:#272525;display:block;text-align:right;font-size:90%;cursor:pointer;color:#27ae60}.rst-versions .rst-current-version:after{clear:both;content:"";display:block}.rst-versions .rst-current-version .fa{color:#fcfcfc}.rst-versions .rst-current-version .fa-book,.rst-versions .rst-current-version .icon-book{float:left}.rst-versions .rst-current-version.rst-out-of-date{background-color:#e74c3c;color:#fff}.rst-versions .rst-current-version.rst-active-old-version{background-color:#f1c40f;color:#000}.rst-versions.shift-up{height:auto;max-height:100%;overflow-y:scroll}.rst-versions.shift-up .rst-other-versions{display:block}.rst-versions .rst-other-versions{font-size:90%;padding:12px;color:grey;display:none}.rst-versions .rst-other-versions hr{display:block;height:1px;border:0;margin:20px 0;padding:0;border-top:1px solid #413d3d}.rst-versions .rst-other-versions dd{display:inline-block;margin:0}.rst-versions .rst-other-versions dd a{display:inline-block;padding:6px;color:#fcfcfc}.rst-versions .rst-other-versions .rtd-current-item{font-weight:700}.rst-versions.rst-badge{width:auto;bottom:20px;right:20px;left:auto;border:none;max-width:300px;max-height:90%}.rst-versions.rst-badge .fa-book,.rst-versions.rst-badge .icon-book{float:none;line-height:30px}.rst-versions.rst-badge.shift-up .rst-current-version{text-align:right}.rst-versions.rst-badge.shift-up .rst-current-version .fa-book,.rst-versions.rst-badge.shift-up .rst-current-version .icon-book{float:left}.rst-versions.rst-badge>.rst-current-version{width:auto;height:30px;line-height:30px;padding:0 6px;display:block;text-align:center}@media screen and (max-width:768px){.rst-versions{width:85%;display:none}.rst-versions.shift{display:block}}#flyout-search-form{padding:6px} \ No newline at end of file diff --git a/docs/build/html/_static/css/fonts/Roboto-Slab-Bold.woff b/docs/build/html/_static/css/fonts/Roboto-Slab-Bold.woff deleted file mode 100644 index 6cb6000..0000000 Binary files a/docs/build/html/_static/css/fonts/Roboto-Slab-Bold.woff and /dev/null differ diff --git a/docs/build/html/_static/css/fonts/Roboto-Slab-Bold.woff2 b/docs/build/html/_static/css/fonts/Roboto-Slab-Bold.woff2 deleted file mode 100644 index 7059e23..0000000 Binary files a/docs/build/html/_static/css/fonts/Roboto-Slab-Bold.woff2 and /dev/null differ diff --git a/docs/build/html/_static/css/fonts/Roboto-Slab-Regular.woff b/docs/build/html/_static/css/fonts/Roboto-Slab-Regular.woff deleted file mode 100644 index f815f63..0000000 Binary files a/docs/build/html/_static/css/fonts/Roboto-Slab-Regular.woff and /dev/null differ diff --git a/docs/build/html/_static/css/fonts/Roboto-Slab-Regular.woff2 b/docs/build/html/_static/css/fonts/Roboto-Slab-Regular.woff2 deleted file mode 100644 index f2c76e5..0000000 Binary files a/docs/build/html/_static/css/fonts/Roboto-Slab-Regular.woff2 and /dev/null differ diff --git a/docs/build/html/_static/css/fonts/fontawesome-webfont.eot b/docs/build/html/_static/css/fonts/fontawesome-webfont.eot deleted file mode 100644 index e9f60ca..0000000 Binary files a/docs/build/html/_static/css/fonts/fontawesome-webfont.eot and /dev/null differ diff --git a/docs/build/html/_static/css/fonts/fontawesome-webfont.svg b/docs/build/html/_static/css/fonts/fontawesome-webfont.svg deleted file mode 100644 index 855c845..0000000 --- a/docs/build/html/_static/css/fonts/fontawesome-webfont.svg +++ /dev/null @@ -1,2671 +0,0 @@ - - - - -Created by FontForge 20120731 at Mon Oct 24 17:37:40 2016 - By ,,, -Copyright Dave Gandy 2016. All rights reserved. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/build/html/_static/css/fonts/fontawesome-webfont.ttf b/docs/build/html/_static/css/fonts/fontawesome-webfont.ttf deleted file mode 100644 index 35acda2..0000000 Binary files a/docs/build/html/_static/css/fonts/fontawesome-webfont.ttf and /dev/null differ diff --git a/docs/build/html/_static/css/fonts/fontawesome-webfont.woff b/docs/build/html/_static/css/fonts/fontawesome-webfont.woff deleted file mode 100644 index 400014a..0000000 Binary files a/docs/build/html/_static/css/fonts/fontawesome-webfont.woff and /dev/null differ diff --git a/docs/build/html/_static/css/fonts/fontawesome-webfont.woff2 b/docs/build/html/_static/css/fonts/fontawesome-webfont.woff2 deleted file mode 100644 index 4d13fc6..0000000 Binary files a/docs/build/html/_static/css/fonts/fontawesome-webfont.woff2 and /dev/null differ diff --git a/docs/build/html/_static/css/fonts/lato-bold-italic.woff b/docs/build/html/_static/css/fonts/lato-bold-italic.woff deleted file mode 100644 index 88ad05b..0000000 Binary files a/docs/build/html/_static/css/fonts/lato-bold-italic.woff and /dev/null differ diff --git a/docs/build/html/_static/css/fonts/lato-bold-italic.woff2 b/docs/build/html/_static/css/fonts/lato-bold-italic.woff2 deleted file mode 100644 index c4e3d80..0000000 Binary files a/docs/build/html/_static/css/fonts/lato-bold-italic.woff2 and /dev/null differ diff --git a/docs/build/html/_static/css/fonts/lato-bold.woff b/docs/build/html/_static/css/fonts/lato-bold.woff deleted file mode 100644 index c6dff51..0000000 Binary files a/docs/build/html/_static/css/fonts/lato-bold.woff and /dev/null differ diff --git a/docs/build/html/_static/css/fonts/lato-bold.woff2 b/docs/build/html/_static/css/fonts/lato-bold.woff2 deleted file mode 100644 index bb19504..0000000 Binary files a/docs/build/html/_static/css/fonts/lato-bold.woff2 and /dev/null differ diff --git a/docs/build/html/_static/css/fonts/lato-normal-italic.woff b/docs/build/html/_static/css/fonts/lato-normal-italic.woff deleted file mode 100644 index 76114bc..0000000 Binary files a/docs/build/html/_static/css/fonts/lato-normal-italic.woff and /dev/null differ diff --git a/docs/build/html/_static/css/fonts/lato-normal-italic.woff2 b/docs/build/html/_static/css/fonts/lato-normal-italic.woff2 deleted file mode 100644 index 3404f37..0000000 Binary files a/docs/build/html/_static/css/fonts/lato-normal-italic.woff2 and /dev/null differ diff --git a/docs/build/html/_static/css/fonts/lato-normal.woff b/docs/build/html/_static/css/fonts/lato-normal.woff deleted file mode 100644 index ae1307f..0000000 Binary files a/docs/build/html/_static/css/fonts/lato-normal.woff and /dev/null differ diff --git a/docs/build/html/_static/css/fonts/lato-normal.woff2 b/docs/build/html/_static/css/fonts/lato-normal.woff2 deleted file mode 100644 index 3bf9843..0000000 Binary files a/docs/build/html/_static/css/fonts/lato-normal.woff2 and /dev/null differ diff --git a/docs/build/html/_static/css/theme.css b/docs/build/html/_static/css/theme.css deleted file mode 100644 index 0f14f10..0000000 --- a/docs/build/html/_static/css/theme.css +++ /dev/null @@ -1,4 +0,0 @@ -html{box-sizing:border-box}*,:after,:before{box-sizing:inherit}article,aside,details,figcaption,figure,footer,header,hgroup,nav,section{display:block}audio,canvas,video{display:inline-block;*display:inline;*zoom:1}[hidden],audio:not([controls]){display:none}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:100%;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}body{margin:0}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}blockquote{margin:0}dfn{font-style:italic}ins{background:#ff9;text-decoration:none}ins,mark{color:#000}mark{background:#ff0;font-style:italic;font-weight:700}.rst-content code,.rst-content tt,code,kbd,pre,samp{font-family:monospace,serif;_font-family:courier new,monospace;font-size:1em}pre{white-space:pre}q{quotes:none}q:after,q:before{content:"";content:none}small{font-size:85%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}dl,ol,ul{margin:0;padding:0;list-style:none;list-style-image:none}li{list-style:none}dd{margin:0}img{border:0;-ms-interpolation-mode:bicubic;vertical-align:middle;max-width:100%}svg:not(:root){overflow:hidden}figure,form{margin:0}label{cursor:pointer}button,input,select,textarea{font-size:100%;margin:0;vertical-align:baseline;*vertical-align:middle}button,input{line-height:normal}button,input[type=button],input[type=reset],input[type=submit]{cursor:pointer;-webkit-appearance:button;*overflow:visible}button[disabled],input[disabled]{cursor:default}input[type=search]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}textarea{resize:vertical}table{border-collapse:collapse;border-spacing:0}td{vertical-align:top}.chromeframe{margin:.2em 0;background:#ccc;color:#000;padding:.2em 0}.ir{display:block;border:0;text-indent:-999em;overflow:hidden;background-color:transparent;background-repeat:no-repeat;text-align:left;direction:ltr;*line-height:0}.ir br{display:none}.hidden{display:none!important;visibility:hidden}.visuallyhidden{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.visuallyhidden.focusable:active,.visuallyhidden.focusable:focus{clip:auto;height:auto;margin:0;overflow:visible;position:static;width:auto}.invisible{visibility:hidden}.relative{position:relative}big,small{font-size:100%}@media print{body,html,section{background:none!important}*{box-shadow:none!important;text-shadow:none!important;filter:none!important;-ms-filter:none!important}a,a:visited{text-decoration:underline}.ir a:after,a[href^="#"]:after,a[href^="javascript:"]:after{content:""}blockquote,pre{page-break-inside:avoid}thead{display:table-header-group}img,tr{page-break-inside:avoid}img{max-width:100%!important}@page{margin:.5cm}.rst-content .toctree-wrapper>p.caption,h2,h3,p{orphans:3;widows:3}.rst-content .toctree-wrapper>p.caption,h2,h3{page-break-after:avoid}}.btn,.fa:before,.icon:before,.rst-content .admonition,.rst-content .admonition-title:before,.rst-content .admonition-todo,.rst-content .attention,.rst-content .caution,.rst-content .code-block-caption .headerlink:before,.rst-content .danger,.rst-content .eqno .headerlink:before,.rst-content .error,.rst-content .hint,.rst-content .important,.rst-content .note,.rst-content .seealso,.rst-content .tip,.rst-content .warning,.rst-content code.download span:first-child:before,.rst-content dl dt .headerlink:before,.rst-content h1 .headerlink:before,.rst-content h2 .headerlink:before,.rst-content h3 .headerlink:before,.rst-content h4 .headerlink:before,.rst-content h5 .headerlink:before,.rst-content h6 .headerlink:before,.rst-content p.caption .headerlink:before,.rst-content p .headerlink:before,.rst-content table>caption .headerlink:before,.rst-content tt.download span:first-child:before,.wy-alert,.wy-dropdown .caret:before,.wy-inline-validate.wy-inline-validate-danger .wy-input-context:before,.wy-inline-validate.wy-inline-validate-info .wy-input-context:before,.wy-inline-validate.wy-inline-validate-success .wy-input-context:before,.wy-inline-validate.wy-inline-validate-warning .wy-input-context:before,.wy-menu-vertical li.current>a button.toctree-expand:before,.wy-menu-vertical li.on a button.toctree-expand:before,.wy-menu-vertical li button.toctree-expand:before,input[type=color],input[type=date],input[type=datetime-local],input[type=datetime],input[type=email],input[type=month],input[type=number],input[type=password],input[type=search],input[type=tel],input[type=text],input[type=time],input[type=url],input[type=week],select,textarea{-webkit-font-smoothing:antialiased}.clearfix{*zoom:1}.clearfix:after,.clearfix:before{display:table;content:""}.clearfix:after{clear:both}/*! - * Font Awesome 4.7.0 by @davegandy - http://fontawesome.io - @fontawesome - * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) - */@font-face{font-family:FontAwesome;src:url(fonts/fontawesome-webfont.eot?674f50d287a8c48dc19ba404d20fe713);src:url(fonts/fontawesome-webfont.eot?674f50d287a8c48dc19ba404d20fe713?#iefix&v=4.7.0) format("embedded-opentype"),url(fonts/fontawesome-webfont.woff2?af7ae505a9eed503f8b8e6982036873e) format("woff2"),url(fonts/fontawesome-webfont.woff?fee66e712a8a08eef5805a46892932ad) format("woff"),url(fonts/fontawesome-webfont.ttf?b06871f281fee6b241d60582ae9369b9) format("truetype"),url(fonts/fontawesome-webfont.svg?912ec66d7572ff821749319396470bde#fontawesomeregular) format("svg");font-weight:400;font-style:normal}.fa,.icon,.rst-content .admonition-title,.rst-content .code-block-caption .headerlink,.rst-content .eqno .headerlink,.rst-content code.download span:first-child,.rst-content dl dt .headerlink,.rst-content h1 .headerlink,.rst-content h2 .headerlink,.rst-content h3 .headerlink,.rst-content h4 .headerlink,.rst-content h5 .headerlink,.rst-content h6 .headerlink,.rst-content p.caption .headerlink,.rst-content p .headerlink,.rst-content table>caption .headerlink,.rst-content tt.download span:first-child,.wy-menu-vertical li.current>a button.toctree-expand,.wy-menu-vertical li.on a button.toctree-expand,.wy-menu-vertical li button.toctree-expand{display:inline-block;font:normal normal normal 14px/1 FontAwesome;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fa-lg{font-size:1.33333em;line-height:.75em;vertical-align:-15%}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-fw{width:1.28571em;text-align:center}.fa-ul{padding-left:0;margin-left:2.14286em;list-style-type:none}.fa-ul>li{position:relative}.fa-li{position:absolute;left:-2.14286em;width:2.14286em;top:.14286em;text-align:center}.fa-li.fa-lg{left:-1.85714em}.fa-border{padding:.2em .25em .15em;border:.08em solid #eee;border-radius:.1em}.fa-pull-left{float:left}.fa-pull-right{float:right}.fa-pull-left.icon,.fa.fa-pull-left,.rst-content .code-block-caption .fa-pull-left.headerlink,.rst-content .eqno .fa-pull-left.headerlink,.rst-content .fa-pull-left.admonition-title,.rst-content code.download span.fa-pull-left:first-child,.rst-content dl dt .fa-pull-left.headerlink,.rst-content h1 .fa-pull-left.headerlink,.rst-content h2 .fa-pull-left.headerlink,.rst-content h3 .fa-pull-left.headerlink,.rst-content h4 .fa-pull-left.headerlink,.rst-content h5 .fa-pull-left.headerlink,.rst-content h6 .fa-pull-left.headerlink,.rst-content p .fa-pull-left.headerlink,.rst-content table>caption .fa-pull-left.headerlink,.rst-content tt.download span.fa-pull-left:first-child,.wy-menu-vertical li.current>a button.fa-pull-left.toctree-expand,.wy-menu-vertical li.on a button.fa-pull-left.toctree-expand,.wy-menu-vertical li button.fa-pull-left.toctree-expand{margin-right:.3em}.fa-pull-right.icon,.fa.fa-pull-right,.rst-content .code-block-caption .fa-pull-right.headerlink,.rst-content .eqno .fa-pull-right.headerlink,.rst-content .fa-pull-right.admonition-title,.rst-content code.download span.fa-pull-right:first-child,.rst-content dl dt .fa-pull-right.headerlink,.rst-content h1 .fa-pull-right.headerlink,.rst-content h2 .fa-pull-right.headerlink,.rst-content h3 .fa-pull-right.headerlink,.rst-content h4 .fa-pull-right.headerlink,.rst-content h5 .fa-pull-right.headerlink,.rst-content h6 .fa-pull-right.headerlink,.rst-content p .fa-pull-right.headerlink,.rst-content table>caption .fa-pull-right.headerlink,.rst-content tt.download span.fa-pull-right:first-child,.wy-menu-vertical li.current>a button.fa-pull-right.toctree-expand,.wy-menu-vertical li.on a button.fa-pull-right.toctree-expand,.wy-menu-vertical li button.fa-pull-right.toctree-expand{margin-left:.3em}.pull-right{float:right}.pull-left{float:left}.fa.pull-left,.pull-left.icon,.rst-content .code-block-caption .pull-left.headerlink,.rst-content .eqno .pull-left.headerlink,.rst-content .pull-left.admonition-title,.rst-content code.download span.pull-left:first-child,.rst-content dl dt .pull-left.headerlink,.rst-content h1 .pull-left.headerlink,.rst-content h2 .pull-left.headerlink,.rst-content h3 .pull-left.headerlink,.rst-content h4 .pull-left.headerlink,.rst-content h5 .pull-left.headerlink,.rst-content h6 .pull-left.headerlink,.rst-content p .pull-left.headerlink,.rst-content table>caption .pull-left.headerlink,.rst-content tt.download span.pull-left:first-child,.wy-menu-vertical li.current>a button.pull-left.toctree-expand,.wy-menu-vertical li.on a button.pull-left.toctree-expand,.wy-menu-vertical li button.pull-left.toctree-expand{margin-right:.3em}.fa.pull-right,.pull-right.icon,.rst-content .code-block-caption .pull-right.headerlink,.rst-content .eqno .pull-right.headerlink,.rst-content .pull-right.admonition-title,.rst-content code.download span.pull-right:first-child,.rst-content dl dt .pull-right.headerlink,.rst-content h1 .pull-right.headerlink,.rst-content h2 .pull-right.headerlink,.rst-content h3 .pull-right.headerlink,.rst-content h4 .pull-right.headerlink,.rst-content h5 .pull-right.headerlink,.rst-content h6 .pull-right.headerlink,.rst-content p .pull-right.headerlink,.rst-content table>caption .pull-right.headerlink,.rst-content tt.download span.pull-right:first-child,.wy-menu-vertical li.current>a button.pull-right.toctree-expand,.wy-menu-vertical li.on a button.pull-right.toctree-expand,.wy-menu-vertical li button.pull-right.toctree-expand{margin-left:.3em}.fa-spin{-webkit-animation:fa-spin 2s linear infinite;animation:fa-spin 2s linear infinite}.fa-pulse{-webkit-animation:fa-spin 1s steps(8) infinite;animation:fa-spin 1s steps(8) infinite}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.fa-rotate-90{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=1)";-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2)";-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=3)";-webkit-transform:rotate(270deg);-ms-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)";-webkit-transform:scaleX(-1);-ms-transform:scaleX(-1);transform:scaleX(-1)}.fa-flip-vertical{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)";-webkit-transform:scaleY(-1);-ms-transform:scaleY(-1);transform:scaleY(-1)}:root .fa-flip-horizontal,:root .fa-flip-vertical,:root .fa-rotate-90,:root .fa-rotate-180,:root .fa-rotate-270{filter:none}.fa-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:middle}.fa-stack-1x,.fa-stack-2x{position:absolute;left:0;width:100%;text-align:center}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-glass:before{content:""}.fa-music:before{content:""}.fa-search:before,.icon-search:before{content:""}.fa-envelope-o:before{content:""}.fa-heart:before{content:""}.fa-star:before{content:""}.fa-star-o:before{content:""}.fa-user:before{content:""}.fa-film:before{content:""}.fa-th-large:before{content:""}.fa-th:before{content:""}.fa-th-list:before{content:""}.fa-check:before{content:""}.fa-close:before,.fa-remove:before,.fa-times:before{content:""}.fa-search-plus:before{content:""}.fa-search-minus:before{content:""}.fa-power-off:before{content:""}.fa-signal:before{content:""}.fa-cog:before,.fa-gear:before{content:""}.fa-trash-o:before{content:""}.fa-home:before,.icon-home:before{content:""}.fa-file-o:before{content:""}.fa-clock-o:before{content:""}.fa-road:before{content:""}.fa-download:before,.rst-content code.download span:first-child:before,.rst-content tt.download span:first-child:before{content:""}.fa-arrow-circle-o-down:before{content:""}.fa-arrow-circle-o-up:before{content:""}.fa-inbox:before{content:""}.fa-play-circle-o:before{content:""}.fa-repeat:before,.fa-rotate-right:before{content:""}.fa-refresh:before{content:""}.fa-list-alt:before{content:""}.fa-lock:before{content:""}.fa-flag:before{content:""}.fa-headphones:before{content:""}.fa-volume-off:before{content:""}.fa-volume-down:before{content:""}.fa-volume-up:before{content:""}.fa-qrcode:before{content:""}.fa-barcode:before{content:""}.fa-tag:before{content:""}.fa-tags:before{content:""}.fa-book:before,.icon-book:before{content:""}.fa-bookmark:before{content:""}.fa-print:before{content:""}.fa-camera:before{content:""}.fa-font:before{content:""}.fa-bold:before{content:""}.fa-italic:before{content:""}.fa-text-height:before{content:""}.fa-text-width:before{content:""}.fa-align-left:before{content:""}.fa-align-center:before{content:""}.fa-align-right:before{content:""}.fa-align-justify:before{content:""}.fa-list:before{content:""}.fa-dedent:before,.fa-outdent:before{content:""}.fa-indent:before{content:""}.fa-video-camera:before{content:""}.fa-image:before,.fa-photo:before,.fa-picture-o:before{content:""}.fa-pencil:before{content:""}.fa-map-marker:before{content:""}.fa-adjust:before{content:""}.fa-tint:before{content:""}.fa-edit:before,.fa-pencil-square-o:before{content:""}.fa-share-square-o:before{content:""}.fa-check-square-o:before{content:""}.fa-arrows:before{content:""}.fa-step-backward:before{content:""}.fa-fast-backward:before{content:""}.fa-backward:before{content:""}.fa-play:before{content:""}.fa-pause:before{content:""}.fa-stop:before{content:""}.fa-forward:before{content:""}.fa-fast-forward:before{content:""}.fa-step-forward:before{content:""}.fa-eject:before{content:""}.fa-chevron-left:before{content:""}.fa-chevron-right:before{content:""}.fa-plus-circle:before{content:""}.fa-minus-circle:before{content:""}.fa-times-circle:before,.wy-inline-validate.wy-inline-validate-danger .wy-input-context:before{content:""}.fa-check-circle:before,.wy-inline-validate.wy-inline-validate-success .wy-input-context:before{content:""}.fa-question-circle:before{content:""}.fa-info-circle:before{content:""}.fa-crosshairs:before{content:""}.fa-times-circle-o:before{content:""}.fa-check-circle-o:before{content:""}.fa-ban:before{content:""}.fa-arrow-left:before{content:""}.fa-arrow-right:before{content:""}.fa-arrow-up:before{content:""}.fa-arrow-down:before{content:""}.fa-mail-forward:before,.fa-share:before{content:""}.fa-expand:before{content:""}.fa-compress:before{content:""}.fa-plus:before{content:""}.fa-minus:before{content:""}.fa-asterisk:before{content:""}.fa-exclamation-circle:before,.rst-content .admonition-title:before,.wy-inline-validate.wy-inline-validate-info .wy-input-context:before,.wy-inline-validate.wy-inline-validate-warning .wy-input-context:before{content:""}.fa-gift:before{content:""}.fa-leaf:before{content:""}.fa-fire:before,.icon-fire:before{content:""}.fa-eye:before{content:""}.fa-eye-slash:before{content:""}.fa-exclamation-triangle:before,.fa-warning:before{content:""}.fa-plane:before{content:""}.fa-calendar:before{content:""}.fa-random:before{content:""}.fa-comment:before{content:""}.fa-magnet:before{content:""}.fa-chevron-up:before{content:""}.fa-chevron-down:before{content:""}.fa-retweet:before{content:""}.fa-shopping-cart:before{content:""}.fa-folder:before{content:""}.fa-folder-open:before{content:""}.fa-arrows-v:before{content:""}.fa-arrows-h:before{content:""}.fa-bar-chart-o:before,.fa-bar-chart:before{content:""}.fa-twitter-square:before{content:""}.fa-facebook-square:before{content:""}.fa-camera-retro:before{content:""}.fa-key:before{content:""}.fa-cogs:before,.fa-gears:before{content:""}.fa-comments:before{content:""}.fa-thumbs-o-up:before{content:""}.fa-thumbs-o-down:before{content:""}.fa-star-half:before{content:""}.fa-heart-o:before{content:""}.fa-sign-out:before{content:""}.fa-linkedin-square:before{content:""}.fa-thumb-tack:before{content:""}.fa-external-link:before{content:""}.fa-sign-in:before{content:""}.fa-trophy:before{content:""}.fa-github-square:before{content:""}.fa-upload:before{content:""}.fa-lemon-o:before{content:""}.fa-phone:before{content:""}.fa-square-o:before{content:""}.fa-bookmark-o:before{content:""}.fa-phone-square:before{content:""}.fa-twitter:before{content:""}.fa-facebook-f:before,.fa-facebook:before{content:""}.fa-github:before,.icon-github:before{content:""}.fa-unlock:before{content:""}.fa-credit-card:before{content:""}.fa-feed:before,.fa-rss:before{content:""}.fa-hdd-o:before{content:""}.fa-bullhorn:before{content:""}.fa-bell:before{content:""}.fa-certificate:before{content:""}.fa-hand-o-right:before{content:""}.fa-hand-o-left:before{content:""}.fa-hand-o-up:before{content:""}.fa-hand-o-down:before{content:""}.fa-arrow-circle-left:before,.icon-circle-arrow-left:before{content:""}.fa-arrow-circle-right:before,.icon-circle-arrow-right:before{content:""}.fa-arrow-circle-up:before{content:""}.fa-arrow-circle-down:before{content:""}.fa-globe:before{content:""}.fa-wrench:before{content:""}.fa-tasks:before{content:""}.fa-filter:before{content:""}.fa-briefcase:before{content:""}.fa-arrows-alt:before{content:""}.fa-group:before,.fa-users:before{content:""}.fa-chain:before,.fa-link:before,.icon-link:before{content:""}.fa-cloud:before{content:""}.fa-flask:before{content:""}.fa-cut:before,.fa-scissors:before{content:""}.fa-copy:before,.fa-files-o:before{content:""}.fa-paperclip:before{content:""}.fa-floppy-o:before,.fa-save:before{content:""}.fa-square:before{content:""}.fa-bars:before,.fa-navicon:before,.fa-reorder:before{content:""}.fa-list-ul:before{content:""}.fa-list-ol:before{content:""}.fa-strikethrough:before{content:""}.fa-underline:before{content:""}.fa-table:before{content:""}.fa-magic:before{content:""}.fa-truck:before{content:""}.fa-pinterest:before{content:""}.fa-pinterest-square:before{content:""}.fa-google-plus-square:before{content:""}.fa-google-plus:before{content:""}.fa-money:before{content:""}.fa-caret-down:before,.icon-caret-down:before,.wy-dropdown .caret:before{content:""}.fa-caret-up:before{content:""}.fa-caret-left:before{content:""}.fa-caret-right:before{content:""}.fa-columns:before{content:""}.fa-sort:before,.fa-unsorted:before{content:""}.fa-sort-desc:before,.fa-sort-down:before{content:""}.fa-sort-asc:before,.fa-sort-up:before{content:""}.fa-envelope:before{content:""}.fa-linkedin:before{content:""}.fa-rotate-left:before,.fa-undo:before{content:""}.fa-gavel:before,.fa-legal:before{content:""}.fa-dashboard:before,.fa-tachometer:before{content:""}.fa-comment-o:before{content:""}.fa-comments-o:before{content:""}.fa-bolt:before,.fa-flash:before{content:""}.fa-sitemap:before{content:""}.fa-umbrella:before{content:""}.fa-clipboard:before,.fa-paste:before{content:""}.fa-lightbulb-o:before{content:""}.fa-exchange:before{content:""}.fa-cloud-download:before{content:""}.fa-cloud-upload:before{content:""}.fa-user-md:before{content:""}.fa-stethoscope:before{content:""}.fa-suitcase:before{content:""}.fa-bell-o:before{content:""}.fa-coffee:before{content:""}.fa-cutlery:before{content:""}.fa-file-text-o:before{content:""}.fa-building-o:before{content:""}.fa-hospital-o:before{content:""}.fa-ambulance:before{content:""}.fa-medkit:before{content:""}.fa-fighter-jet:before{content:""}.fa-beer:before{content:""}.fa-h-square:before{content:""}.fa-plus-square:before{content:""}.fa-angle-double-left:before{content:""}.fa-angle-double-right:before{content:""}.fa-angle-double-up:before{content:""}.fa-angle-double-down:before{content:""}.fa-angle-left:before{content:""}.fa-angle-right:before{content:""}.fa-angle-up:before{content:""}.fa-angle-down:before{content:""}.fa-desktop:before{content:""}.fa-laptop:before{content:""}.fa-tablet:before{content:""}.fa-mobile-phone:before,.fa-mobile:before{content:""}.fa-circle-o:before{content:""}.fa-quote-left:before{content:""}.fa-quote-right:before{content:""}.fa-spinner:before{content:""}.fa-circle:before{content:""}.fa-mail-reply:before,.fa-reply:before{content:""}.fa-github-alt:before{content:""}.fa-folder-o:before{content:""}.fa-folder-open-o:before{content:""}.fa-smile-o:before{content:""}.fa-frown-o:before{content:""}.fa-meh-o:before{content:""}.fa-gamepad:before{content:""}.fa-keyboard-o:before{content:""}.fa-flag-o:before{content:""}.fa-flag-checkered:before{content:""}.fa-terminal:before{content:""}.fa-code:before{content:""}.fa-mail-reply-all:before,.fa-reply-all:before{content:""}.fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:""}.fa-location-arrow:before{content:""}.fa-crop:before{content:""}.fa-code-fork:before{content:""}.fa-chain-broken:before,.fa-unlink:before{content:""}.fa-question:before{content:""}.fa-info:before{content:""}.fa-exclamation:before{content:""}.fa-superscript:before{content:""}.fa-subscript:before{content:""}.fa-eraser:before{content:""}.fa-puzzle-piece:before{content:""}.fa-microphone:before{content:""}.fa-microphone-slash:before{content:""}.fa-shield:before{content:""}.fa-calendar-o:before{content:""}.fa-fire-extinguisher:before{content:""}.fa-rocket:before{content:""}.fa-maxcdn:before{content:""}.fa-chevron-circle-left:before{content:""}.fa-chevron-circle-right:before{content:""}.fa-chevron-circle-up:before{content:""}.fa-chevron-circle-down:before{content:""}.fa-html5:before{content:""}.fa-css3:before{content:""}.fa-anchor:before{content:""}.fa-unlock-alt:before{content:""}.fa-bullseye:before{content:""}.fa-ellipsis-h:before{content:""}.fa-ellipsis-v:before{content:""}.fa-rss-square:before{content:""}.fa-play-circle:before{content:""}.fa-ticket:before{content:""}.fa-minus-square:before{content:""}.fa-minus-square-o:before,.wy-menu-vertical li.current>a button.toctree-expand:before,.wy-menu-vertical li.on a button.toctree-expand:before{content:""}.fa-level-up:before{content:""}.fa-level-down:before{content:""}.fa-check-square:before{content:""}.fa-pencil-square:before{content:""}.fa-external-link-square:before{content:""}.fa-share-square:before{content:""}.fa-compass:before{content:""}.fa-caret-square-o-down:before,.fa-toggle-down:before{content:""}.fa-caret-square-o-up:before,.fa-toggle-up:before{content:""}.fa-caret-square-o-right:before,.fa-toggle-right:before{content:""}.fa-eur:before,.fa-euro:before{content:""}.fa-gbp:before{content:""}.fa-dollar:before,.fa-usd:before{content:""}.fa-inr:before,.fa-rupee:before{content:""}.fa-cny:before,.fa-jpy:before,.fa-rmb:before,.fa-yen:before{content:""}.fa-rouble:before,.fa-rub:before,.fa-ruble:before{content:""}.fa-krw:before,.fa-won:before{content:""}.fa-bitcoin:before,.fa-btc:before{content:""}.fa-file:before{content:""}.fa-file-text:before{content:""}.fa-sort-alpha-asc:before{content:""}.fa-sort-alpha-desc:before{content:""}.fa-sort-amount-asc:before{content:""}.fa-sort-amount-desc:before{content:""}.fa-sort-numeric-asc:before{content:""}.fa-sort-numeric-desc:before{content:""}.fa-thumbs-up:before{content:""}.fa-thumbs-down:before{content:""}.fa-youtube-square:before{content:""}.fa-youtube:before{content:""}.fa-xing:before{content:""}.fa-xing-square:before{content:""}.fa-youtube-play:before{content:""}.fa-dropbox:before{content:""}.fa-stack-overflow:before{content:""}.fa-instagram:before{content:""}.fa-flickr:before{content:""}.fa-adn:before{content:""}.fa-bitbucket:before,.icon-bitbucket:before{content:""}.fa-bitbucket-square:before{content:""}.fa-tumblr:before{content:""}.fa-tumblr-square:before{content:""}.fa-long-arrow-down:before{content:""}.fa-long-arrow-up:before{content:""}.fa-long-arrow-left:before{content:""}.fa-long-arrow-right:before{content:""}.fa-apple:before{content:""}.fa-windows:before{content:""}.fa-android:before{content:""}.fa-linux:before{content:""}.fa-dribbble:before{content:""}.fa-skype:before{content:""}.fa-foursquare:before{content:""}.fa-trello:before{content:""}.fa-female:before{content:""}.fa-male:before{content:""}.fa-gittip:before,.fa-gratipay:before{content:""}.fa-sun-o:before{content:""}.fa-moon-o:before{content:""}.fa-archive:before{content:""}.fa-bug:before{content:""}.fa-vk:before{content:""}.fa-weibo:before{content:""}.fa-renren:before{content:""}.fa-pagelines:before{content:""}.fa-stack-exchange:before{content:""}.fa-arrow-circle-o-right:before{content:""}.fa-arrow-circle-o-left:before{content:""}.fa-caret-square-o-left:before,.fa-toggle-left:before{content:""}.fa-dot-circle-o:before{content:""}.fa-wheelchair:before{content:""}.fa-vimeo-square:before{content:""}.fa-try:before,.fa-turkish-lira:before{content:""}.fa-plus-square-o:before,.wy-menu-vertical li button.toctree-expand:before{content:""}.fa-space-shuttle:before{content:""}.fa-slack:before{content:""}.fa-envelope-square:before{content:""}.fa-wordpress:before{content:""}.fa-openid:before{content:""}.fa-bank:before,.fa-institution:before,.fa-university:before{content:""}.fa-graduation-cap:before,.fa-mortar-board:before{content:""}.fa-yahoo:before{content:""}.fa-google:before{content:""}.fa-reddit:before{content:""}.fa-reddit-square:before{content:""}.fa-stumbleupon-circle:before{content:""}.fa-stumbleupon:before{content:""}.fa-delicious:before{content:""}.fa-digg:before{content:""}.fa-pied-piper-pp:before{content:""}.fa-pied-piper-alt:before{content:""}.fa-drupal:before{content:""}.fa-joomla:before{content:""}.fa-language:before{content:""}.fa-fax:before{content:""}.fa-building:before{content:""}.fa-child:before{content:""}.fa-paw:before{content:""}.fa-spoon:before{content:""}.fa-cube:before{content:""}.fa-cubes:before{content:""}.fa-behance:before{content:""}.fa-behance-square:before{content:""}.fa-steam:before{content:""}.fa-steam-square:before{content:""}.fa-recycle:before{content:""}.fa-automobile:before,.fa-car:before{content:""}.fa-cab:before,.fa-taxi:before{content:""}.fa-tree:before{content:""}.fa-spotify:before{content:""}.fa-deviantart:before{content:""}.fa-soundcloud:before{content:""}.fa-database:before{content:""}.fa-file-pdf-o:before{content:""}.fa-file-word-o:before{content:""}.fa-file-excel-o:before{content:""}.fa-file-powerpoint-o:before{content:""}.fa-file-image-o:before,.fa-file-photo-o:before,.fa-file-picture-o:before{content:""}.fa-file-archive-o:before,.fa-file-zip-o:before{content:""}.fa-file-audio-o:before,.fa-file-sound-o:before{content:""}.fa-file-movie-o:before,.fa-file-video-o:before{content:""}.fa-file-code-o:before{content:""}.fa-vine:before{content:""}.fa-codepen:before{content:""}.fa-jsfiddle:before{content:""}.fa-life-bouy:before,.fa-life-buoy:before,.fa-life-ring:before,.fa-life-saver:before,.fa-support:before{content:""}.fa-circle-o-notch:before{content:""}.fa-ra:before,.fa-rebel:before,.fa-resistance:before{content:""}.fa-empire:before,.fa-ge:before{content:""}.fa-git-square:before{content:""}.fa-git:before{content:""}.fa-hacker-news:before,.fa-y-combinator-square:before,.fa-yc-square:before{content:""}.fa-tencent-weibo:before{content:""}.fa-qq:before{content:""}.fa-wechat:before,.fa-weixin:before{content:""}.fa-paper-plane:before,.fa-send:before{content:""}.fa-paper-plane-o:before,.fa-send-o:before{content:""}.fa-history:before{content:""}.fa-circle-thin:before{content:""}.fa-header:before{content:""}.fa-paragraph:before{content:""}.fa-sliders:before{content:""}.fa-share-alt:before{content:""}.fa-share-alt-square:before{content:""}.fa-bomb:before{content:""}.fa-futbol-o:before,.fa-soccer-ball-o:before{content:""}.fa-tty:before{content:""}.fa-binoculars:before{content:""}.fa-plug:before{content:""}.fa-slideshare:before{content:""}.fa-twitch:before{content:""}.fa-yelp:before{content:""}.fa-newspaper-o:before{content:""}.fa-wifi:before{content:""}.fa-calculator:before{content:""}.fa-paypal:before{content:""}.fa-google-wallet:before{content:""}.fa-cc-visa:before{content:""}.fa-cc-mastercard:before{content:""}.fa-cc-discover:before{content:""}.fa-cc-amex:before{content:""}.fa-cc-paypal:before{content:""}.fa-cc-stripe:before{content:""}.fa-bell-slash:before{content:""}.fa-bell-slash-o:before{content:""}.fa-trash:before{content:""}.fa-copyright:before{content:""}.fa-at:before{content:""}.fa-eyedropper:before{content:""}.fa-paint-brush:before{content:""}.fa-birthday-cake:before{content:""}.fa-area-chart:before{content:""}.fa-pie-chart:before{content:""}.fa-line-chart:before{content:""}.fa-lastfm:before{content:""}.fa-lastfm-square:before{content:""}.fa-toggle-off:before{content:""}.fa-toggle-on:before{content:""}.fa-bicycle:before{content:""}.fa-bus:before{content:""}.fa-ioxhost:before{content:""}.fa-angellist:before{content:""}.fa-cc:before{content:""}.fa-ils:before,.fa-shekel:before,.fa-sheqel:before{content:""}.fa-meanpath:before{content:""}.fa-buysellads:before{content:""}.fa-connectdevelop:before{content:""}.fa-dashcube:before{content:""}.fa-forumbee:before{content:""}.fa-leanpub:before{content:""}.fa-sellsy:before{content:""}.fa-shirtsinbulk:before{content:""}.fa-simplybuilt:before{content:""}.fa-skyatlas:before{content:""}.fa-cart-plus:before{content:""}.fa-cart-arrow-down:before{content:""}.fa-diamond:before{content:""}.fa-ship:before{content:""}.fa-user-secret:before{content:""}.fa-motorcycle:before{content:""}.fa-street-view:before{content:""}.fa-heartbeat:before{content:""}.fa-venus:before{content:""}.fa-mars:before{content:""}.fa-mercury:before{content:""}.fa-intersex:before,.fa-transgender:before{content:""}.fa-transgender-alt:before{content:""}.fa-venus-double:before{content:""}.fa-mars-double:before{content:""}.fa-venus-mars:before{content:""}.fa-mars-stroke:before{content:""}.fa-mars-stroke-v:before{content:""}.fa-mars-stroke-h:before{content:""}.fa-neuter:before{content:""}.fa-genderless:before{content:""}.fa-facebook-official:before{content:""}.fa-pinterest-p:before{content:""}.fa-whatsapp:before{content:""}.fa-server:before{content:""}.fa-user-plus:before{content:""}.fa-user-times:before{content:""}.fa-bed:before,.fa-hotel:before{content:""}.fa-viacoin:before{content:""}.fa-train:before{content:""}.fa-subway:before{content:""}.fa-medium:before{content:""}.fa-y-combinator:before,.fa-yc:before{content:""}.fa-optin-monster:before{content:""}.fa-opencart:before{content:""}.fa-expeditedssl:before{content:""}.fa-battery-4:before,.fa-battery-full:before,.fa-battery:before{content:""}.fa-battery-3:before,.fa-battery-three-quarters:before{content:""}.fa-battery-2:before,.fa-battery-half:before{content:""}.fa-battery-1:before,.fa-battery-quarter:before{content:""}.fa-battery-0:before,.fa-battery-empty:before{content:""}.fa-mouse-pointer:before{content:""}.fa-i-cursor:before{content:""}.fa-object-group:before{content:""}.fa-object-ungroup:before{content:""}.fa-sticky-note:before{content:""}.fa-sticky-note-o:before{content:""}.fa-cc-jcb:before{content:""}.fa-cc-diners-club:before{content:""}.fa-clone:before{content:""}.fa-balance-scale:before{content:""}.fa-hourglass-o:before{content:""}.fa-hourglass-1:before,.fa-hourglass-start:before{content:""}.fa-hourglass-2:before,.fa-hourglass-half:before{content:""}.fa-hourglass-3:before,.fa-hourglass-end:before{content:""}.fa-hourglass:before{content:""}.fa-hand-grab-o:before,.fa-hand-rock-o:before{content:""}.fa-hand-paper-o:before,.fa-hand-stop-o:before{content:""}.fa-hand-scissors-o:before{content:""}.fa-hand-lizard-o:before{content:""}.fa-hand-spock-o:before{content:""}.fa-hand-pointer-o:before{content:""}.fa-hand-peace-o:before{content:""}.fa-trademark:before{content:""}.fa-registered:before{content:""}.fa-creative-commons:before{content:""}.fa-gg:before{content:""}.fa-gg-circle:before{content:""}.fa-tripadvisor:before{content:""}.fa-odnoklassniki:before{content:""}.fa-odnoklassniki-square:before{content:""}.fa-get-pocket:before{content:""}.fa-wikipedia-w:before{content:""}.fa-safari:before{content:""}.fa-chrome:before{content:""}.fa-firefox:before{content:""}.fa-opera:before{content:""}.fa-internet-explorer:before{content:""}.fa-television:before,.fa-tv:before{content:""}.fa-contao:before{content:""}.fa-500px:before{content:""}.fa-amazon:before{content:""}.fa-calendar-plus-o:before{content:""}.fa-calendar-minus-o:before{content:""}.fa-calendar-times-o:before{content:""}.fa-calendar-check-o:before{content:""}.fa-industry:before{content:""}.fa-map-pin:before{content:""}.fa-map-signs:before{content:""}.fa-map-o:before{content:""}.fa-map:before{content:""}.fa-commenting:before{content:""}.fa-commenting-o:before{content:""}.fa-houzz:before{content:""}.fa-vimeo:before{content:""}.fa-black-tie:before{content:""}.fa-fonticons:before{content:""}.fa-reddit-alien:before{content:""}.fa-edge:before{content:""}.fa-credit-card-alt:before{content:""}.fa-codiepie:before{content:""}.fa-modx:before{content:""}.fa-fort-awesome:before{content:""}.fa-usb:before{content:""}.fa-product-hunt:before{content:""}.fa-mixcloud:before{content:""}.fa-scribd:before{content:""}.fa-pause-circle:before{content:""}.fa-pause-circle-o:before{content:""}.fa-stop-circle:before{content:""}.fa-stop-circle-o:before{content:""}.fa-shopping-bag:before{content:""}.fa-shopping-basket:before{content:""}.fa-hashtag:before{content:""}.fa-bluetooth:before{content:""}.fa-bluetooth-b:before{content:""}.fa-percent:before{content:""}.fa-gitlab:before,.icon-gitlab:before{content:""}.fa-wpbeginner:before{content:""}.fa-wpforms:before{content:""}.fa-envira:before{content:""}.fa-universal-access:before{content:""}.fa-wheelchair-alt:before{content:""}.fa-question-circle-o:before{content:""}.fa-blind:before{content:""}.fa-audio-description:before{content:""}.fa-volume-control-phone:before{content:""}.fa-braille:before{content:""}.fa-assistive-listening-systems:before{content:""}.fa-american-sign-language-interpreting:before,.fa-asl-interpreting:before{content:""}.fa-deaf:before,.fa-deafness:before,.fa-hard-of-hearing:before{content:""}.fa-glide:before{content:""}.fa-glide-g:before{content:""}.fa-sign-language:before,.fa-signing:before{content:""}.fa-low-vision:before{content:""}.fa-viadeo:before{content:""}.fa-viadeo-square:before{content:""}.fa-snapchat:before{content:""}.fa-snapchat-ghost:before{content:""}.fa-snapchat-square:before{content:""}.fa-pied-piper:before{content:""}.fa-first-order:before{content:""}.fa-yoast:before{content:""}.fa-themeisle:before{content:""}.fa-google-plus-circle:before,.fa-google-plus-official:before{content:""}.fa-fa:before,.fa-font-awesome:before{content:""}.fa-handshake-o:before{content:""}.fa-envelope-open:before{content:""}.fa-envelope-open-o:before{content:""}.fa-linode:before{content:""}.fa-address-book:before{content:""}.fa-address-book-o:before{content:""}.fa-address-card:before,.fa-vcard:before{content:""}.fa-address-card-o:before,.fa-vcard-o:before{content:""}.fa-user-circle:before{content:""}.fa-user-circle-o:before{content:""}.fa-user-o:before{content:""}.fa-id-badge:before{content:""}.fa-drivers-license:before,.fa-id-card:before{content:""}.fa-drivers-license-o:before,.fa-id-card-o:before{content:""}.fa-quora:before{content:""}.fa-free-code-camp:before{content:""}.fa-telegram:before{content:""}.fa-thermometer-4:before,.fa-thermometer-full:before,.fa-thermometer:before{content:""}.fa-thermometer-3:before,.fa-thermometer-three-quarters:before{content:""}.fa-thermometer-2:before,.fa-thermometer-half:before{content:""}.fa-thermometer-1:before,.fa-thermometer-quarter:before{content:""}.fa-thermometer-0:before,.fa-thermometer-empty:before{content:""}.fa-shower:before{content:""}.fa-bath:before,.fa-bathtub:before,.fa-s15:before{content:""}.fa-podcast:before{content:""}.fa-window-maximize:before{content:""}.fa-window-minimize:before{content:""}.fa-window-restore:before{content:""}.fa-times-rectangle:before,.fa-window-close:before{content:""}.fa-times-rectangle-o:before,.fa-window-close-o:before{content:""}.fa-bandcamp:before{content:""}.fa-grav:before{content:""}.fa-etsy:before{content:""}.fa-imdb:before{content:""}.fa-ravelry:before{content:""}.fa-eercast:before{content:""}.fa-microchip:before{content:""}.fa-snowflake-o:before{content:""}.fa-superpowers:before{content:""}.fa-wpexplorer:before{content:""}.fa-meetup:before{content:""}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto}.fa,.icon,.rst-content .admonition-title,.rst-content .code-block-caption .headerlink,.rst-content .eqno .headerlink,.rst-content code.download span:first-child,.rst-content dl dt .headerlink,.rst-content h1 .headerlink,.rst-content h2 .headerlink,.rst-content h3 .headerlink,.rst-content h4 .headerlink,.rst-content h5 .headerlink,.rst-content h6 .headerlink,.rst-content p.caption .headerlink,.rst-content p .headerlink,.rst-content table>caption .headerlink,.rst-content tt.download span:first-child,.wy-dropdown .caret,.wy-inline-validate.wy-inline-validate-danger .wy-input-context,.wy-inline-validate.wy-inline-validate-info .wy-input-context,.wy-inline-validate.wy-inline-validate-success .wy-input-context,.wy-inline-validate.wy-inline-validate-warning .wy-input-context,.wy-menu-vertical li.current>a button.toctree-expand,.wy-menu-vertical li.on a button.toctree-expand,.wy-menu-vertical li button.toctree-expand{font-family:inherit}.fa:before,.icon:before,.rst-content .admonition-title:before,.rst-content .code-block-caption .headerlink:before,.rst-content .eqno .headerlink:before,.rst-content code.download span:first-child:before,.rst-content dl dt .headerlink:before,.rst-content h1 .headerlink:before,.rst-content h2 .headerlink:before,.rst-content h3 .headerlink:before,.rst-content h4 .headerlink:before,.rst-content h5 .headerlink:before,.rst-content h6 .headerlink:before,.rst-content p.caption .headerlink:before,.rst-content p .headerlink:before,.rst-content table>caption .headerlink:before,.rst-content tt.download span:first-child:before,.wy-dropdown .caret:before,.wy-inline-validate.wy-inline-validate-danger .wy-input-context:before,.wy-inline-validate.wy-inline-validate-info .wy-input-context:before,.wy-inline-validate.wy-inline-validate-success .wy-input-context:before,.wy-inline-validate.wy-inline-validate-warning .wy-input-context:before,.wy-menu-vertical li.current>a button.toctree-expand:before,.wy-menu-vertical li.on a button.toctree-expand:before,.wy-menu-vertical li button.toctree-expand:before{font-family:FontAwesome;display:inline-block;font-style:normal;font-weight:400;line-height:1;text-decoration:inherit}.rst-content .code-block-caption a .headerlink,.rst-content .eqno a .headerlink,.rst-content a .admonition-title,.rst-content code.download a span:first-child,.rst-content dl dt a .headerlink,.rst-content h1 a .headerlink,.rst-content h2 a .headerlink,.rst-content h3 a .headerlink,.rst-content h4 a .headerlink,.rst-content h5 a .headerlink,.rst-content h6 a .headerlink,.rst-content p.caption a .headerlink,.rst-content p a .headerlink,.rst-content table>caption a .headerlink,.rst-content tt.download a span:first-child,.wy-menu-vertical li.current>a button.toctree-expand,.wy-menu-vertical li.on a button.toctree-expand,.wy-menu-vertical li a button.toctree-expand,a .fa,a .icon,a .rst-content .admonition-title,a .rst-content .code-block-caption .headerlink,a .rst-content .eqno .headerlink,a .rst-content code.download span:first-child,a .rst-content dl dt .headerlink,a .rst-content h1 .headerlink,a .rst-content h2 .headerlink,a .rst-content h3 .headerlink,a .rst-content h4 .headerlink,a .rst-content h5 .headerlink,a .rst-content h6 .headerlink,a .rst-content p.caption .headerlink,a .rst-content p .headerlink,a .rst-content table>caption .headerlink,a .rst-content tt.download span:first-child,a .wy-menu-vertical li button.toctree-expand{display:inline-block;text-decoration:inherit}.btn .fa,.btn .icon,.btn .rst-content .admonition-title,.btn .rst-content .code-block-caption .headerlink,.btn .rst-content .eqno .headerlink,.btn .rst-content code.download span:first-child,.btn .rst-content dl dt .headerlink,.btn .rst-content h1 .headerlink,.btn .rst-content h2 .headerlink,.btn .rst-content h3 .headerlink,.btn .rst-content h4 .headerlink,.btn .rst-content h5 .headerlink,.btn .rst-content h6 .headerlink,.btn .rst-content p .headerlink,.btn .rst-content table>caption .headerlink,.btn .rst-content tt.download span:first-child,.btn .wy-menu-vertical li.current>a button.toctree-expand,.btn .wy-menu-vertical li.on a button.toctree-expand,.btn .wy-menu-vertical li button.toctree-expand,.nav .fa,.nav .icon,.nav .rst-content .admonition-title,.nav .rst-content .code-block-caption .headerlink,.nav .rst-content .eqno .headerlink,.nav .rst-content code.download span:first-child,.nav .rst-content dl dt .headerlink,.nav .rst-content h1 .headerlink,.nav .rst-content h2 .headerlink,.nav .rst-content h3 .headerlink,.nav .rst-content h4 .headerlink,.nav .rst-content h5 .headerlink,.nav .rst-content h6 .headerlink,.nav .rst-content p .headerlink,.nav .rst-content table>caption .headerlink,.nav .rst-content tt.download span:first-child,.nav .wy-menu-vertical li.current>a button.toctree-expand,.nav .wy-menu-vertical li.on a button.toctree-expand,.nav .wy-menu-vertical li button.toctree-expand,.rst-content .btn .admonition-title,.rst-content .code-block-caption .btn .headerlink,.rst-content .code-block-caption .nav .headerlink,.rst-content .eqno .btn .headerlink,.rst-content .eqno .nav .headerlink,.rst-content .nav .admonition-title,.rst-content code.download .btn span:first-child,.rst-content code.download .nav span:first-child,.rst-content dl dt .btn .headerlink,.rst-content dl dt .nav .headerlink,.rst-content h1 .btn .headerlink,.rst-content h1 .nav .headerlink,.rst-content h2 .btn .headerlink,.rst-content h2 .nav .headerlink,.rst-content h3 .btn .headerlink,.rst-content h3 .nav .headerlink,.rst-content h4 .btn .headerlink,.rst-content h4 .nav .headerlink,.rst-content h5 .btn .headerlink,.rst-content h5 .nav .headerlink,.rst-content h6 .btn .headerlink,.rst-content h6 .nav .headerlink,.rst-content p .btn .headerlink,.rst-content p .nav .headerlink,.rst-content table>caption .btn .headerlink,.rst-content table>caption .nav .headerlink,.rst-content tt.download .btn span:first-child,.rst-content tt.download .nav span:first-child,.wy-menu-vertical li .btn button.toctree-expand,.wy-menu-vertical li.current>a .btn button.toctree-expand,.wy-menu-vertical li.current>a .nav button.toctree-expand,.wy-menu-vertical li .nav button.toctree-expand,.wy-menu-vertical li.on a .btn button.toctree-expand,.wy-menu-vertical li.on a .nav button.toctree-expand{display:inline}.btn .fa-large.icon,.btn .fa.fa-large,.btn .rst-content .code-block-caption .fa-large.headerlink,.btn .rst-content .eqno .fa-large.headerlink,.btn .rst-content .fa-large.admonition-title,.btn .rst-content code.download span.fa-large:first-child,.btn .rst-content dl dt .fa-large.headerlink,.btn .rst-content h1 .fa-large.headerlink,.btn .rst-content h2 .fa-large.headerlink,.btn .rst-content h3 .fa-large.headerlink,.btn .rst-content h4 .fa-large.headerlink,.btn .rst-content h5 .fa-large.headerlink,.btn .rst-content h6 .fa-large.headerlink,.btn .rst-content p .fa-large.headerlink,.btn .rst-content table>caption .fa-large.headerlink,.btn .rst-content tt.download span.fa-large:first-child,.btn .wy-menu-vertical li button.fa-large.toctree-expand,.nav .fa-large.icon,.nav .fa.fa-large,.nav .rst-content .code-block-caption .fa-large.headerlink,.nav .rst-content .eqno .fa-large.headerlink,.nav .rst-content .fa-large.admonition-title,.nav .rst-content code.download span.fa-large:first-child,.nav .rst-content dl dt .fa-large.headerlink,.nav .rst-content h1 .fa-large.headerlink,.nav .rst-content h2 .fa-large.headerlink,.nav .rst-content h3 .fa-large.headerlink,.nav .rst-content h4 .fa-large.headerlink,.nav .rst-content h5 .fa-large.headerlink,.nav .rst-content h6 .fa-large.headerlink,.nav .rst-content p .fa-large.headerlink,.nav .rst-content table>caption .fa-large.headerlink,.nav .rst-content tt.download span.fa-large:first-child,.nav .wy-menu-vertical li button.fa-large.toctree-expand,.rst-content .btn .fa-large.admonition-title,.rst-content .code-block-caption .btn .fa-large.headerlink,.rst-content .code-block-caption .nav .fa-large.headerlink,.rst-content .eqno .btn .fa-large.headerlink,.rst-content .eqno .nav .fa-large.headerlink,.rst-content .nav .fa-large.admonition-title,.rst-content code.download .btn span.fa-large:first-child,.rst-content code.download .nav span.fa-large:first-child,.rst-content dl dt .btn .fa-large.headerlink,.rst-content dl dt .nav .fa-large.headerlink,.rst-content h1 .btn .fa-large.headerlink,.rst-content h1 .nav .fa-large.headerlink,.rst-content h2 .btn .fa-large.headerlink,.rst-content h2 .nav .fa-large.headerlink,.rst-content h3 .btn .fa-large.headerlink,.rst-content h3 .nav .fa-large.headerlink,.rst-content h4 .btn .fa-large.headerlink,.rst-content h4 .nav .fa-large.headerlink,.rst-content h5 .btn .fa-large.headerlink,.rst-content h5 .nav .fa-large.headerlink,.rst-content h6 .btn .fa-large.headerlink,.rst-content h6 .nav .fa-large.headerlink,.rst-content p .btn .fa-large.headerlink,.rst-content p .nav .fa-large.headerlink,.rst-content table>caption .btn .fa-large.headerlink,.rst-content table>caption .nav .fa-large.headerlink,.rst-content tt.download .btn span.fa-large:first-child,.rst-content tt.download .nav span.fa-large:first-child,.wy-menu-vertical li .btn button.fa-large.toctree-expand,.wy-menu-vertical li .nav button.fa-large.toctree-expand{line-height:.9em}.btn .fa-spin.icon,.btn .fa.fa-spin,.btn .rst-content .code-block-caption .fa-spin.headerlink,.btn .rst-content .eqno .fa-spin.headerlink,.btn .rst-content .fa-spin.admonition-title,.btn .rst-content code.download span.fa-spin:first-child,.btn .rst-content dl dt .fa-spin.headerlink,.btn .rst-content h1 .fa-spin.headerlink,.btn .rst-content h2 .fa-spin.headerlink,.btn .rst-content h3 .fa-spin.headerlink,.btn .rst-content h4 .fa-spin.headerlink,.btn .rst-content h5 .fa-spin.headerlink,.btn .rst-content h6 .fa-spin.headerlink,.btn .rst-content p .fa-spin.headerlink,.btn .rst-content table>caption .fa-spin.headerlink,.btn .rst-content tt.download span.fa-spin:first-child,.btn .wy-menu-vertical li button.fa-spin.toctree-expand,.nav .fa-spin.icon,.nav .fa.fa-spin,.nav .rst-content .code-block-caption .fa-spin.headerlink,.nav .rst-content .eqno .fa-spin.headerlink,.nav .rst-content .fa-spin.admonition-title,.nav .rst-content code.download span.fa-spin:first-child,.nav .rst-content dl dt .fa-spin.headerlink,.nav .rst-content h1 .fa-spin.headerlink,.nav .rst-content h2 .fa-spin.headerlink,.nav .rst-content h3 .fa-spin.headerlink,.nav .rst-content h4 .fa-spin.headerlink,.nav .rst-content h5 .fa-spin.headerlink,.nav .rst-content h6 .fa-spin.headerlink,.nav .rst-content p .fa-spin.headerlink,.nav .rst-content table>caption .fa-spin.headerlink,.nav .rst-content tt.download span.fa-spin:first-child,.nav .wy-menu-vertical li button.fa-spin.toctree-expand,.rst-content .btn .fa-spin.admonition-title,.rst-content .code-block-caption .btn .fa-spin.headerlink,.rst-content .code-block-caption .nav .fa-spin.headerlink,.rst-content .eqno .btn .fa-spin.headerlink,.rst-content .eqno .nav .fa-spin.headerlink,.rst-content .nav .fa-spin.admonition-title,.rst-content code.download .btn span.fa-spin:first-child,.rst-content code.download .nav span.fa-spin:first-child,.rst-content dl dt .btn .fa-spin.headerlink,.rst-content dl dt .nav .fa-spin.headerlink,.rst-content h1 .btn .fa-spin.headerlink,.rst-content h1 .nav .fa-spin.headerlink,.rst-content h2 .btn .fa-spin.headerlink,.rst-content h2 .nav .fa-spin.headerlink,.rst-content h3 .btn .fa-spin.headerlink,.rst-content h3 .nav .fa-spin.headerlink,.rst-content h4 .btn .fa-spin.headerlink,.rst-content h4 .nav .fa-spin.headerlink,.rst-content h5 .btn .fa-spin.headerlink,.rst-content h5 .nav .fa-spin.headerlink,.rst-content h6 .btn .fa-spin.headerlink,.rst-content h6 .nav .fa-spin.headerlink,.rst-content p .btn .fa-spin.headerlink,.rst-content p .nav .fa-spin.headerlink,.rst-content table>caption .btn .fa-spin.headerlink,.rst-content table>caption .nav .fa-spin.headerlink,.rst-content tt.download .btn span.fa-spin:first-child,.rst-content tt.download .nav span.fa-spin:first-child,.wy-menu-vertical li .btn button.fa-spin.toctree-expand,.wy-menu-vertical li .nav button.fa-spin.toctree-expand{display:inline-block}.btn.fa:before,.btn.icon:before,.rst-content .btn.admonition-title:before,.rst-content .code-block-caption .btn.headerlink:before,.rst-content .eqno .btn.headerlink:before,.rst-content code.download span.btn:first-child:before,.rst-content dl dt .btn.headerlink:before,.rst-content h1 .btn.headerlink:before,.rst-content h2 .btn.headerlink:before,.rst-content h3 .btn.headerlink:before,.rst-content h4 .btn.headerlink:before,.rst-content h5 .btn.headerlink:before,.rst-content h6 .btn.headerlink:before,.rst-content p .btn.headerlink:before,.rst-content table>caption .btn.headerlink:before,.rst-content tt.download span.btn:first-child:before,.wy-menu-vertical li button.btn.toctree-expand:before{opacity:.5;-webkit-transition:opacity .05s ease-in;-moz-transition:opacity .05s ease-in;transition:opacity .05s ease-in}.btn.fa:hover:before,.btn.icon:hover:before,.rst-content .btn.admonition-title:hover:before,.rst-content .code-block-caption .btn.headerlink:hover:before,.rst-content .eqno .btn.headerlink:hover:before,.rst-content code.download span.btn:first-child:hover:before,.rst-content dl dt .btn.headerlink:hover:before,.rst-content h1 .btn.headerlink:hover:before,.rst-content h2 .btn.headerlink:hover:before,.rst-content h3 .btn.headerlink:hover:before,.rst-content h4 .btn.headerlink:hover:before,.rst-content h5 .btn.headerlink:hover:before,.rst-content h6 .btn.headerlink:hover:before,.rst-content p .btn.headerlink:hover:before,.rst-content table>caption .btn.headerlink:hover:before,.rst-content tt.download span.btn:first-child:hover:before,.wy-menu-vertical li button.btn.toctree-expand:hover:before{opacity:1}.btn-mini .fa:before,.btn-mini .icon:before,.btn-mini .rst-content .admonition-title:before,.btn-mini .rst-content .code-block-caption .headerlink:before,.btn-mini .rst-content .eqno .headerlink:before,.btn-mini .rst-content code.download span:first-child:before,.btn-mini .rst-content dl dt .headerlink:before,.btn-mini .rst-content h1 .headerlink:before,.btn-mini .rst-content h2 .headerlink:before,.btn-mini .rst-content h3 .headerlink:before,.btn-mini .rst-content h4 .headerlink:before,.btn-mini .rst-content h5 .headerlink:before,.btn-mini .rst-content h6 .headerlink:before,.btn-mini .rst-content p .headerlink:before,.btn-mini .rst-content table>caption .headerlink:before,.btn-mini .rst-content tt.download span:first-child:before,.btn-mini .wy-menu-vertical li button.toctree-expand:before,.rst-content .btn-mini .admonition-title:before,.rst-content .code-block-caption .btn-mini .headerlink:before,.rst-content .eqno .btn-mini .headerlink:before,.rst-content code.download .btn-mini span:first-child:before,.rst-content dl dt .btn-mini .headerlink:before,.rst-content h1 .btn-mini .headerlink:before,.rst-content h2 .btn-mini .headerlink:before,.rst-content h3 .btn-mini .headerlink:before,.rst-content h4 .btn-mini .headerlink:before,.rst-content h5 .btn-mini .headerlink:before,.rst-content h6 .btn-mini .headerlink:before,.rst-content p .btn-mini .headerlink:before,.rst-content table>caption .btn-mini .headerlink:before,.rst-content tt.download .btn-mini span:first-child:before,.wy-menu-vertical li .btn-mini button.toctree-expand:before{font-size:14px;vertical-align:-15%}.rst-content .admonition,.rst-content .admonition-todo,.rst-content .attention,.rst-content .caution,.rst-content .danger,.rst-content .error,.rst-content .hint,.rst-content .important,.rst-content .note,.rst-content .seealso,.rst-content .tip,.rst-content .warning,.wy-alert{padding:12px;line-height:24px;margin-bottom:24px;background:#e7f2fa}.rst-content .admonition-title,.wy-alert-title{font-weight:700;display:block;color:#fff;background:#6ab0de;padding:6px 12px;margin:-12px -12px 12px}.rst-content .danger,.rst-content .error,.rst-content .wy-alert-danger.admonition,.rst-content .wy-alert-danger.admonition-todo,.rst-content .wy-alert-danger.attention,.rst-content .wy-alert-danger.caution,.rst-content .wy-alert-danger.hint,.rst-content .wy-alert-danger.important,.rst-content .wy-alert-danger.note,.rst-content .wy-alert-danger.seealso,.rst-content .wy-alert-danger.tip,.rst-content .wy-alert-danger.warning,.wy-alert.wy-alert-danger{background:#fdf3f2}.rst-content .danger .admonition-title,.rst-content .danger .wy-alert-title,.rst-content .error .admonition-title,.rst-content .error .wy-alert-title,.rst-content .wy-alert-danger.admonition-todo .admonition-title,.rst-content .wy-alert-danger.admonition-todo .wy-alert-title,.rst-content .wy-alert-danger.admonition .admonition-title,.rst-content .wy-alert-danger.admonition .wy-alert-title,.rst-content .wy-alert-danger.attention .admonition-title,.rst-content .wy-alert-danger.attention .wy-alert-title,.rst-content .wy-alert-danger.caution .admonition-title,.rst-content .wy-alert-danger.caution .wy-alert-title,.rst-content .wy-alert-danger.hint .admonition-title,.rst-content .wy-alert-danger.hint .wy-alert-title,.rst-content .wy-alert-danger.important .admonition-title,.rst-content .wy-alert-danger.important .wy-alert-title,.rst-content .wy-alert-danger.note .admonition-title,.rst-content .wy-alert-danger.note .wy-alert-title,.rst-content .wy-alert-danger.seealso .admonition-title,.rst-content .wy-alert-danger.seealso .wy-alert-title,.rst-content .wy-alert-danger.tip .admonition-title,.rst-content .wy-alert-danger.tip .wy-alert-title,.rst-content .wy-alert-danger.warning .admonition-title,.rst-content .wy-alert-danger.warning .wy-alert-title,.rst-content .wy-alert.wy-alert-danger .admonition-title,.wy-alert.wy-alert-danger .rst-content .admonition-title,.wy-alert.wy-alert-danger .wy-alert-title{background:#f29f97}.rst-content .admonition-todo,.rst-content .attention,.rst-content .caution,.rst-content .warning,.rst-content .wy-alert-warning.admonition,.rst-content .wy-alert-warning.danger,.rst-content .wy-alert-warning.error,.rst-content .wy-alert-warning.hint,.rst-content .wy-alert-warning.important,.rst-content .wy-alert-warning.note,.rst-content .wy-alert-warning.seealso,.rst-content .wy-alert-warning.tip,.wy-alert.wy-alert-warning{background:#ffedcc}.rst-content .admonition-todo .admonition-title,.rst-content .admonition-todo .wy-alert-title,.rst-content .attention .admonition-title,.rst-content .attention .wy-alert-title,.rst-content .caution .admonition-title,.rst-content .caution .wy-alert-title,.rst-content .warning .admonition-title,.rst-content .warning .wy-alert-title,.rst-content .wy-alert-warning.admonition .admonition-title,.rst-content .wy-alert-warning.admonition .wy-alert-title,.rst-content .wy-alert-warning.danger .admonition-title,.rst-content .wy-alert-warning.danger .wy-alert-title,.rst-content .wy-alert-warning.error .admonition-title,.rst-content .wy-alert-warning.error .wy-alert-title,.rst-content .wy-alert-warning.hint .admonition-title,.rst-content .wy-alert-warning.hint .wy-alert-title,.rst-content .wy-alert-warning.important .admonition-title,.rst-content .wy-alert-warning.important .wy-alert-title,.rst-content .wy-alert-warning.note .admonition-title,.rst-content .wy-alert-warning.note .wy-alert-title,.rst-content .wy-alert-warning.seealso .admonition-title,.rst-content .wy-alert-warning.seealso .wy-alert-title,.rst-content .wy-alert-warning.tip .admonition-title,.rst-content .wy-alert-warning.tip .wy-alert-title,.rst-content .wy-alert.wy-alert-warning .admonition-title,.wy-alert.wy-alert-warning .rst-content .admonition-title,.wy-alert.wy-alert-warning .wy-alert-title{background:#f0b37e}.rst-content .note,.rst-content .seealso,.rst-content .wy-alert-info.admonition,.rst-content .wy-alert-info.admonition-todo,.rst-content .wy-alert-info.attention,.rst-content .wy-alert-info.caution,.rst-content .wy-alert-info.danger,.rst-content .wy-alert-info.error,.rst-content .wy-alert-info.hint,.rst-content .wy-alert-info.important,.rst-content .wy-alert-info.tip,.rst-content .wy-alert-info.warning,.wy-alert.wy-alert-info{background:#e7f2fa}.rst-content .note .admonition-title,.rst-content .note .wy-alert-title,.rst-content .seealso .admonition-title,.rst-content .seealso .wy-alert-title,.rst-content .wy-alert-info.admonition-todo .admonition-title,.rst-content .wy-alert-info.admonition-todo .wy-alert-title,.rst-content .wy-alert-info.admonition .admonition-title,.rst-content .wy-alert-info.admonition .wy-alert-title,.rst-content .wy-alert-info.attention .admonition-title,.rst-content .wy-alert-info.attention .wy-alert-title,.rst-content .wy-alert-info.caution .admonition-title,.rst-content .wy-alert-info.caution .wy-alert-title,.rst-content .wy-alert-info.danger .admonition-title,.rst-content .wy-alert-info.danger .wy-alert-title,.rst-content .wy-alert-info.error .admonition-title,.rst-content .wy-alert-info.error .wy-alert-title,.rst-content .wy-alert-info.hint .admonition-title,.rst-content .wy-alert-info.hint .wy-alert-title,.rst-content .wy-alert-info.important .admonition-title,.rst-content .wy-alert-info.important .wy-alert-title,.rst-content .wy-alert-info.tip .admonition-title,.rst-content .wy-alert-info.tip .wy-alert-title,.rst-content .wy-alert-info.warning .admonition-title,.rst-content .wy-alert-info.warning .wy-alert-title,.rst-content .wy-alert.wy-alert-info .admonition-title,.wy-alert.wy-alert-info .rst-content .admonition-title,.wy-alert.wy-alert-info .wy-alert-title{background:#6ab0de}.rst-content .hint,.rst-content .important,.rst-content .tip,.rst-content .wy-alert-success.admonition,.rst-content .wy-alert-success.admonition-todo,.rst-content .wy-alert-success.attention,.rst-content .wy-alert-success.caution,.rst-content .wy-alert-success.danger,.rst-content .wy-alert-success.error,.rst-content .wy-alert-success.note,.rst-content .wy-alert-success.seealso,.rst-content .wy-alert-success.warning,.wy-alert.wy-alert-success{background:#dbfaf4}.rst-content .hint .admonition-title,.rst-content .hint .wy-alert-title,.rst-content .important .admonition-title,.rst-content .important .wy-alert-title,.rst-content .tip .admonition-title,.rst-content .tip .wy-alert-title,.rst-content .wy-alert-success.admonition-todo .admonition-title,.rst-content .wy-alert-success.admonition-todo .wy-alert-title,.rst-content .wy-alert-success.admonition .admonition-title,.rst-content .wy-alert-success.admonition .wy-alert-title,.rst-content .wy-alert-success.attention .admonition-title,.rst-content .wy-alert-success.attention .wy-alert-title,.rst-content .wy-alert-success.caution .admonition-title,.rst-content .wy-alert-success.caution .wy-alert-title,.rst-content .wy-alert-success.danger .admonition-title,.rst-content .wy-alert-success.danger .wy-alert-title,.rst-content .wy-alert-success.error .admonition-title,.rst-content .wy-alert-success.error .wy-alert-title,.rst-content .wy-alert-success.note .admonition-title,.rst-content .wy-alert-success.note .wy-alert-title,.rst-content .wy-alert-success.seealso .admonition-title,.rst-content .wy-alert-success.seealso .wy-alert-title,.rst-content .wy-alert-success.warning .admonition-title,.rst-content .wy-alert-success.warning .wy-alert-title,.rst-content .wy-alert.wy-alert-success .admonition-title,.wy-alert.wy-alert-success .rst-content .admonition-title,.wy-alert.wy-alert-success .wy-alert-title{background:#1abc9c}.rst-content .wy-alert-neutral.admonition,.rst-content .wy-alert-neutral.admonition-todo,.rst-content .wy-alert-neutral.attention,.rst-content .wy-alert-neutral.caution,.rst-content .wy-alert-neutral.danger,.rst-content .wy-alert-neutral.error,.rst-content .wy-alert-neutral.hint,.rst-content .wy-alert-neutral.important,.rst-content .wy-alert-neutral.note,.rst-content .wy-alert-neutral.seealso,.rst-content .wy-alert-neutral.tip,.rst-content .wy-alert-neutral.warning,.wy-alert.wy-alert-neutral{background:#f3f6f6}.rst-content .wy-alert-neutral.admonition-todo .admonition-title,.rst-content .wy-alert-neutral.admonition-todo .wy-alert-title,.rst-content .wy-alert-neutral.admonition .admonition-title,.rst-content .wy-alert-neutral.admonition .wy-alert-title,.rst-content .wy-alert-neutral.attention .admonition-title,.rst-content .wy-alert-neutral.attention .wy-alert-title,.rst-content .wy-alert-neutral.caution .admonition-title,.rst-content .wy-alert-neutral.caution .wy-alert-title,.rst-content .wy-alert-neutral.danger .admonition-title,.rst-content .wy-alert-neutral.danger .wy-alert-title,.rst-content .wy-alert-neutral.error .admonition-title,.rst-content .wy-alert-neutral.error .wy-alert-title,.rst-content .wy-alert-neutral.hint .admonition-title,.rst-content .wy-alert-neutral.hint .wy-alert-title,.rst-content .wy-alert-neutral.important .admonition-title,.rst-content .wy-alert-neutral.important .wy-alert-title,.rst-content .wy-alert-neutral.note .admonition-title,.rst-content .wy-alert-neutral.note .wy-alert-title,.rst-content .wy-alert-neutral.seealso .admonition-title,.rst-content .wy-alert-neutral.seealso .wy-alert-title,.rst-content .wy-alert-neutral.tip .admonition-title,.rst-content .wy-alert-neutral.tip .wy-alert-title,.rst-content .wy-alert-neutral.warning .admonition-title,.rst-content .wy-alert-neutral.warning .wy-alert-title,.rst-content .wy-alert.wy-alert-neutral .admonition-title,.wy-alert.wy-alert-neutral .rst-content .admonition-title,.wy-alert.wy-alert-neutral .wy-alert-title{color:#404040;background:#e1e4e5}.rst-content .wy-alert-neutral.admonition-todo a,.rst-content .wy-alert-neutral.admonition a,.rst-content .wy-alert-neutral.attention a,.rst-content .wy-alert-neutral.caution a,.rst-content .wy-alert-neutral.danger a,.rst-content .wy-alert-neutral.error a,.rst-content .wy-alert-neutral.hint a,.rst-content .wy-alert-neutral.important a,.rst-content .wy-alert-neutral.note a,.rst-content .wy-alert-neutral.seealso a,.rst-content .wy-alert-neutral.tip a,.rst-content .wy-alert-neutral.warning a,.wy-alert.wy-alert-neutral a{color:#2980b9}.rst-content .admonition-todo p:last-child,.rst-content .admonition p:last-child,.rst-content .attention p:last-child,.rst-content .caution p:last-child,.rst-content .danger p:last-child,.rst-content .error p:last-child,.rst-content .hint p:last-child,.rst-content .important p:last-child,.rst-content .note p:last-child,.rst-content .seealso p:last-child,.rst-content .tip p:last-child,.rst-content .warning p:last-child,.wy-alert p:last-child{margin-bottom:0}.wy-tray-container{position:fixed;bottom:0;left:0;z-index:600}.wy-tray-container li{display:block;width:300px;background:transparent;color:#fff;text-align:center;box-shadow:0 5px 5px 0 rgba(0,0,0,.1);padding:0 24px;min-width:20%;opacity:0;height:0;line-height:56px;overflow:hidden;-webkit-transition:all .3s ease-in;-moz-transition:all .3s ease-in;transition:all .3s ease-in}.wy-tray-container li.wy-tray-item-success{background:#27ae60}.wy-tray-container li.wy-tray-item-info{background:#2980b9}.wy-tray-container li.wy-tray-item-warning{background:#e67e22}.wy-tray-container li.wy-tray-item-danger{background:#e74c3c}.wy-tray-container li.on{opacity:1;height:56px}@media screen and (max-width:768px){.wy-tray-container{bottom:auto;top:0;width:100%}.wy-tray-container li{width:100%}}button{font-size:100%;margin:0;vertical-align:baseline;*vertical-align:middle;cursor:pointer;line-height:normal;-webkit-appearance:button;*overflow:visible}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}button[disabled]{cursor:default}.btn{display:inline-block;border-radius:2px;line-height:normal;white-space:nowrap;text-align:center;cursor:pointer;font-size:100%;padding:6px 12px 8px;color:#fff;border:1px solid rgba(0,0,0,.1);background-color:#27ae60;text-decoration:none;font-weight:400;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;box-shadow:inset 0 1px 2px -1px hsla(0,0%,100%,.5),inset 0 -2px 0 0 rgba(0,0,0,.1);outline-none:false;vertical-align:middle;*display:inline;zoom:1;-webkit-user-drag:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-transition:all .1s linear;-moz-transition:all .1s linear;transition:all .1s linear}.btn-hover{background:#2e8ece;color:#fff}.btn:hover{background:#2cc36b;color:#fff}.btn:focus{background:#2cc36b;outline:0}.btn:active{box-shadow:inset 0 -1px 0 0 rgba(0,0,0,.05),inset 0 2px 0 0 rgba(0,0,0,.1);padding:8px 12px 6px}.btn:visited{color:#fff}.btn-disabled,.btn-disabled:active,.btn-disabled:focus,.btn-disabled:hover,.btn:disabled{background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);filter:alpha(opacity=40);opacity:.4;cursor:not-allowed;box-shadow:none}.btn::-moz-focus-inner{padding:0;border:0}.btn-small{font-size:80%}.btn-info{background-color:#2980b9!important}.btn-info:hover{background-color:#2e8ece!important}.btn-neutral{background-color:#f3f6f6!important;color:#404040!important}.btn-neutral:hover{background-color:#e5ebeb!important;color:#404040}.btn-neutral:visited{color:#404040!important}.btn-success{background-color:#27ae60!important}.btn-success:hover{background-color:#295!important}.btn-danger{background-color:#e74c3c!important}.btn-danger:hover{background-color:#ea6153!important}.btn-warning{background-color:#e67e22!important}.btn-warning:hover{background-color:#e98b39!important}.btn-invert{background-color:#222}.btn-invert:hover{background-color:#2f2f2f!important}.btn-link{background-color:transparent!important;color:#2980b9;box-shadow:none;border-color:transparent!important}.btn-link:active,.btn-link:hover{background-color:transparent!important;color:#409ad5!important;box-shadow:none}.btn-link:visited{color:#9b59b6}.wy-btn-group .btn,.wy-control .btn{vertical-align:middle}.wy-btn-group{margin-bottom:24px;*zoom:1}.wy-btn-group:after,.wy-btn-group:before{display:table;content:""}.wy-btn-group:after{clear:both}.wy-dropdown{position:relative;display:inline-block}.wy-dropdown-active .wy-dropdown-menu{display:block}.wy-dropdown-menu{position:absolute;left:0;display:none;float:left;top:100%;min-width:100%;background:#fcfcfc;z-index:100;border:1px solid #cfd7dd;box-shadow:0 2px 2px 0 rgba(0,0,0,.1);padding:12px}.wy-dropdown-menu>dd>a{display:block;clear:both;color:#404040;white-space:nowrap;font-size:90%;padding:0 12px;cursor:pointer}.wy-dropdown-menu>dd>a:hover{background:#2980b9;color:#fff}.wy-dropdown-menu>dd.divider{border-top:1px solid #cfd7dd;margin:6px 0}.wy-dropdown-menu>dd.search{padding-bottom:12px}.wy-dropdown-menu>dd.search input[type=search]{width:100%}.wy-dropdown-menu>dd.call-to-action{background:#e3e3e3;text-transform:uppercase;font-weight:500;font-size:80%}.wy-dropdown-menu>dd.call-to-action:hover{background:#e3e3e3}.wy-dropdown-menu>dd.call-to-action .btn{color:#fff}.wy-dropdown.wy-dropdown-up .wy-dropdown-menu{bottom:100%;top:auto;left:auto;right:0}.wy-dropdown.wy-dropdown-bubble .wy-dropdown-menu{background:#fcfcfc;margin-top:2px}.wy-dropdown.wy-dropdown-bubble .wy-dropdown-menu a{padding:6px 12px}.wy-dropdown.wy-dropdown-bubble .wy-dropdown-menu a:hover{background:#2980b9;color:#fff}.wy-dropdown.wy-dropdown-left .wy-dropdown-menu{right:0;left:auto;text-align:right}.wy-dropdown-arrow:before{content:" ";border-bottom:5px solid #f5f5f5;border-left:5px solid transparent;border-right:5px solid transparent;position:absolute;display:block;top:-4px;left:50%;margin-left:-3px}.wy-dropdown-arrow.wy-dropdown-arrow-left:before{left:11px}.wy-form-stacked select{display:block}.wy-form-aligned .wy-help-inline,.wy-form-aligned input,.wy-form-aligned label,.wy-form-aligned select,.wy-form-aligned textarea{display:inline-block;*display:inline;*zoom:1;vertical-align:middle}.wy-form-aligned .wy-control-group>label{display:inline-block;vertical-align:middle;width:10em;margin:6px 12px 0 0;float:left}.wy-form-aligned .wy-control{float:left}.wy-form-aligned .wy-control label{display:block}.wy-form-aligned .wy-control select{margin-top:6px}fieldset{margin:0}fieldset,legend{border:0;padding:0}legend{width:100%;white-space:normal;margin-bottom:24px;font-size:150%;*margin-left:-7px}label,legend{display:block}label{margin:0 0 .3125em;color:#333;font-size:90%}input,select,textarea{font-size:100%;margin:0;vertical-align:baseline;*vertical-align:middle}.wy-control-group{margin-bottom:24px;max-width:1200px;margin-left:auto;margin-right:auto;*zoom:1}.wy-control-group:after,.wy-control-group:before{display:table;content:""}.wy-control-group:after{clear:both}.wy-control-group.wy-control-group-required>label:after{content:" *";color:#e74c3c}.wy-control-group .wy-form-full,.wy-control-group .wy-form-halves,.wy-control-group .wy-form-thirds{padding-bottom:12px}.wy-control-group .wy-form-full input[type=color],.wy-control-group .wy-form-full input[type=date],.wy-control-group .wy-form-full input[type=datetime-local],.wy-control-group .wy-form-full input[type=datetime],.wy-control-group .wy-form-full input[type=email],.wy-control-group .wy-form-full input[type=month],.wy-control-group .wy-form-full input[type=number],.wy-control-group .wy-form-full input[type=password],.wy-control-group .wy-form-full input[type=search],.wy-control-group .wy-form-full input[type=tel],.wy-control-group .wy-form-full input[type=text],.wy-control-group .wy-form-full input[type=time],.wy-control-group .wy-form-full input[type=url],.wy-control-group .wy-form-full input[type=week],.wy-control-group .wy-form-full select,.wy-control-group .wy-form-halves input[type=color],.wy-control-group .wy-form-halves input[type=date],.wy-control-group .wy-form-halves input[type=datetime-local],.wy-control-group .wy-form-halves input[type=datetime],.wy-control-group .wy-form-halves input[type=email],.wy-control-group .wy-form-halves input[type=month],.wy-control-group .wy-form-halves input[type=number],.wy-control-group .wy-form-halves input[type=password],.wy-control-group .wy-form-halves input[type=search],.wy-control-group .wy-form-halves input[type=tel],.wy-control-group .wy-form-halves input[type=text],.wy-control-group .wy-form-halves input[type=time],.wy-control-group .wy-form-halves input[type=url],.wy-control-group .wy-form-halves input[type=week],.wy-control-group .wy-form-halves select,.wy-control-group .wy-form-thirds input[type=color],.wy-control-group .wy-form-thirds input[type=date],.wy-control-group .wy-form-thirds input[type=datetime-local],.wy-control-group .wy-form-thirds input[type=datetime],.wy-control-group .wy-form-thirds input[type=email],.wy-control-group .wy-form-thirds input[type=month],.wy-control-group .wy-form-thirds input[type=number],.wy-control-group .wy-form-thirds input[type=password],.wy-control-group .wy-form-thirds input[type=search],.wy-control-group .wy-form-thirds input[type=tel],.wy-control-group .wy-form-thirds input[type=text],.wy-control-group .wy-form-thirds input[type=time],.wy-control-group .wy-form-thirds input[type=url],.wy-control-group .wy-form-thirds input[type=week],.wy-control-group .wy-form-thirds select{width:100%}.wy-control-group .wy-form-full{float:left;display:block;width:100%;margin-right:0}.wy-control-group .wy-form-full:last-child{margin-right:0}.wy-control-group .wy-form-halves{float:left;display:block;margin-right:2.35765%;width:48.82117%}.wy-control-group .wy-form-halves:last-child,.wy-control-group .wy-form-halves:nth-of-type(2n){margin-right:0}.wy-control-group .wy-form-halves:nth-of-type(odd){clear:left}.wy-control-group .wy-form-thirds{float:left;display:block;margin-right:2.35765%;width:31.76157%}.wy-control-group .wy-form-thirds:last-child,.wy-control-group .wy-form-thirds:nth-of-type(3n){margin-right:0}.wy-control-group .wy-form-thirds:nth-of-type(3n+1){clear:left}.wy-control-group.wy-control-group-no-input .wy-control,.wy-control-no-input{margin:6px 0 0;font-size:90%}.wy-control-no-input{display:inline-block}.wy-control-group.fluid-input input[type=color],.wy-control-group.fluid-input input[type=date],.wy-control-group.fluid-input input[type=datetime-local],.wy-control-group.fluid-input input[type=datetime],.wy-control-group.fluid-input input[type=email],.wy-control-group.fluid-input input[type=month],.wy-control-group.fluid-input input[type=number],.wy-control-group.fluid-input input[type=password],.wy-control-group.fluid-input input[type=search],.wy-control-group.fluid-input input[type=tel],.wy-control-group.fluid-input input[type=text],.wy-control-group.fluid-input input[type=time],.wy-control-group.fluid-input input[type=url],.wy-control-group.fluid-input input[type=week]{width:100%}.wy-form-message-inline{padding-left:.3em;color:#666;font-size:90%}.wy-form-message{display:block;color:#999;font-size:70%;margin-top:.3125em;font-style:italic}.wy-form-message p{font-size:inherit;font-style:italic;margin-bottom:6px}.wy-form-message p:last-child{margin-bottom:0}input{line-height:normal}input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;*overflow:visible}input[type=color],input[type=date],input[type=datetime-local],input[type=datetime],input[type=email],input[type=month],input[type=number],input[type=password],input[type=search],input[type=tel],input[type=text],input[type=time],input[type=url],input[type=week]{-webkit-appearance:none;padding:6px;display:inline-block;border:1px solid #ccc;font-size:80%;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;box-shadow:inset 0 1px 3px #ddd;border-radius:0;-webkit-transition:border .3s linear;-moz-transition:border .3s linear;transition:border .3s linear}input[type=datetime-local]{padding:.34375em .625em}input[disabled]{cursor:default}input[type=checkbox],input[type=radio]{padding:0;margin-right:.3125em;*height:13px;*width:13px}input[type=checkbox],input[type=radio],input[type=search]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}input[type=color]:focus,input[type=date]:focus,input[type=datetime-local]:focus,input[type=datetime]:focus,input[type=email]:focus,input[type=month]:focus,input[type=number]:focus,input[type=password]:focus,input[type=search]:focus,input[type=tel]:focus,input[type=text]:focus,input[type=time]:focus,input[type=url]:focus,input[type=week]:focus{outline:0;outline:thin dotted\9;border-color:#333}input.no-focus:focus{border-color:#ccc!important}input[type=checkbox]:focus,input[type=file]:focus,input[type=radio]:focus{outline:thin dotted #333;outline:1px auto #129fea}input[type=color][disabled],input[type=date][disabled],input[type=datetime-local][disabled],input[type=datetime][disabled],input[type=email][disabled],input[type=month][disabled],input[type=number][disabled],input[type=password][disabled],input[type=search][disabled],input[type=tel][disabled],input[type=text][disabled],input[type=time][disabled],input[type=url][disabled],input[type=week][disabled]{cursor:not-allowed;background-color:#fafafa}input:focus:invalid,select:focus:invalid,textarea:focus:invalid{color:#e74c3c;border:1px solid #e74c3c}input:focus:invalid:focus,select:focus:invalid:focus,textarea:focus:invalid:focus{border-color:#e74c3c}input[type=checkbox]:focus:invalid:focus,input[type=file]:focus:invalid:focus,input[type=radio]:focus:invalid:focus{outline-color:#e74c3c}input.wy-input-large{padding:12px;font-size:100%}textarea{overflow:auto;vertical-align:top;width:100%;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif}select,textarea{padding:.5em .625em;display:inline-block;border:1px solid #ccc;font-size:80%;box-shadow:inset 0 1px 3px #ddd;-webkit-transition:border .3s linear;-moz-transition:border .3s linear;transition:border .3s linear}select{border:1px solid #ccc;background-color:#fff}select[multiple]{height:auto}select:focus,textarea:focus{outline:0}input[readonly],select[disabled],select[readonly],textarea[disabled],textarea[readonly]{cursor:not-allowed;background-color:#fafafa}input[type=checkbox][disabled],input[type=radio][disabled]{cursor:not-allowed}.wy-checkbox,.wy-radio{margin:6px 0;color:#404040;display:block}.wy-checkbox input,.wy-radio input{vertical-align:baseline}.wy-form-message-inline{display:inline-block;*display:inline;*zoom:1;vertical-align:middle}.wy-input-prefix,.wy-input-suffix{white-space:nowrap;padding:6px}.wy-input-prefix .wy-input-context,.wy-input-suffix .wy-input-context{line-height:27px;padding:0 8px;display:inline-block;font-size:80%;background-color:#f3f6f6;border:1px solid #ccc;color:#999}.wy-input-suffix .wy-input-context{border-left:0}.wy-input-prefix .wy-input-context{border-right:0}.wy-switch{position:relative;display:block;height:24px;margin-top:12px;cursor:pointer}.wy-switch:before{left:0;top:0;width:36px;height:12px;background:#ccc}.wy-switch:after,.wy-switch:before{position:absolute;content:"";display:block;border-radius:4px;-webkit-transition:all .2s ease-in-out;-moz-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.wy-switch:after{width:18px;height:18px;background:#999;left:-3px;top:-3px}.wy-switch span{position:absolute;left:48px;display:block;font-size:12px;color:#ccc;line-height:1}.wy-switch.active:before{background:#1e8449}.wy-switch.active:after{left:24px;background:#27ae60}.wy-switch.disabled{cursor:not-allowed;opacity:.8}.wy-control-group.wy-control-group-error .wy-form-message,.wy-control-group.wy-control-group-error>label{color:#e74c3c}.wy-control-group.wy-control-group-error input[type=color],.wy-control-group.wy-control-group-error input[type=date],.wy-control-group.wy-control-group-error input[type=datetime-local],.wy-control-group.wy-control-group-error input[type=datetime],.wy-control-group.wy-control-group-error input[type=email],.wy-control-group.wy-control-group-error input[type=month],.wy-control-group.wy-control-group-error input[type=number],.wy-control-group.wy-control-group-error input[type=password],.wy-control-group.wy-control-group-error input[type=search],.wy-control-group.wy-control-group-error input[type=tel],.wy-control-group.wy-control-group-error input[type=text],.wy-control-group.wy-control-group-error input[type=time],.wy-control-group.wy-control-group-error input[type=url],.wy-control-group.wy-control-group-error input[type=week],.wy-control-group.wy-control-group-error textarea{border:1px solid #e74c3c}.wy-inline-validate{white-space:nowrap}.wy-inline-validate .wy-input-context{padding:.5em .625em;display:inline-block;font-size:80%}.wy-inline-validate.wy-inline-validate-success .wy-input-context{color:#27ae60}.wy-inline-validate.wy-inline-validate-danger .wy-input-context{color:#e74c3c}.wy-inline-validate.wy-inline-validate-warning .wy-input-context{color:#e67e22}.wy-inline-validate.wy-inline-validate-info .wy-input-context{color:#2980b9}.rotate-90{-webkit-transform:rotate(90deg);-moz-transform:rotate(90deg);-ms-transform:rotate(90deg);-o-transform:rotate(90deg);transform:rotate(90deg)}.rotate-180{-webkit-transform:rotate(180deg);-moz-transform:rotate(180deg);-ms-transform:rotate(180deg);-o-transform:rotate(180deg);transform:rotate(180deg)}.rotate-270{-webkit-transform:rotate(270deg);-moz-transform:rotate(270deg);-ms-transform:rotate(270deg);-o-transform:rotate(270deg);transform:rotate(270deg)}.mirror{-webkit-transform:scaleX(-1);-moz-transform:scaleX(-1);-ms-transform:scaleX(-1);-o-transform:scaleX(-1);transform:scaleX(-1)}.mirror.rotate-90{-webkit-transform:scaleX(-1) rotate(90deg);-moz-transform:scaleX(-1) rotate(90deg);-ms-transform:scaleX(-1) rotate(90deg);-o-transform:scaleX(-1) rotate(90deg);transform:scaleX(-1) rotate(90deg)}.mirror.rotate-180{-webkit-transform:scaleX(-1) rotate(180deg);-moz-transform:scaleX(-1) rotate(180deg);-ms-transform:scaleX(-1) rotate(180deg);-o-transform:scaleX(-1) rotate(180deg);transform:scaleX(-1) rotate(180deg)}.mirror.rotate-270{-webkit-transform:scaleX(-1) rotate(270deg);-moz-transform:scaleX(-1) rotate(270deg);-ms-transform:scaleX(-1) rotate(270deg);-o-transform:scaleX(-1) rotate(270deg);transform:scaleX(-1) rotate(270deg)}@media only screen and (max-width:480px){.wy-form button[type=submit]{margin:.7em 0 0}.wy-form input[type=color],.wy-form input[type=date],.wy-form input[type=datetime-local],.wy-form input[type=datetime],.wy-form input[type=email],.wy-form input[type=month],.wy-form input[type=number],.wy-form input[type=password],.wy-form input[type=search],.wy-form input[type=tel],.wy-form input[type=text],.wy-form input[type=time],.wy-form input[type=url],.wy-form input[type=week],.wy-form label{margin-bottom:.3em;display:block}.wy-form input[type=color],.wy-form input[type=date],.wy-form input[type=datetime-local],.wy-form input[type=datetime],.wy-form input[type=email],.wy-form input[type=month],.wy-form input[type=number],.wy-form input[type=password],.wy-form input[type=search],.wy-form input[type=tel],.wy-form input[type=time],.wy-form input[type=url],.wy-form input[type=week]{margin-bottom:0}.wy-form-aligned .wy-control-group label{margin-bottom:.3em;text-align:left;display:block;width:100%}.wy-form-aligned .wy-control{margin:1.5em 0 0}.wy-form-message,.wy-form-message-inline,.wy-form .wy-help-inline{display:block;font-size:80%;padding:6px 0}}@media screen and (max-width:768px){.tablet-hide{display:none}}@media screen and (max-width:480px){.mobile-hide{display:none}}.float-left{float:left}.float-right{float:right}.full-width{width:100%}.rst-content table.docutils,.rst-content table.field-list,.wy-table{border-collapse:collapse;border-spacing:0;empty-cells:show;margin-bottom:24px}.rst-content table.docutils caption,.rst-content table.field-list caption,.wy-table caption{color:#000;font:italic 85%/1 arial,sans-serif;padding:1em 0;text-align:center}.rst-content table.docutils td,.rst-content table.docutils th,.rst-content table.field-list td,.rst-content table.field-list th,.wy-table td,.wy-table th{font-size:90%;margin:0;overflow:visible;padding:8px 16px}.rst-content table.docutils td:first-child,.rst-content table.docutils th:first-child,.rst-content table.field-list td:first-child,.rst-content table.field-list th:first-child,.wy-table td:first-child,.wy-table th:first-child{border-left-width:0}.rst-content table.docutils thead,.rst-content table.field-list thead,.wy-table thead{color:#000;text-align:left;vertical-align:bottom;white-space:nowrap}.rst-content table.docutils thead th,.rst-content table.field-list thead th,.wy-table thead th{font-weight:700;border-bottom:2px solid #e1e4e5}.rst-content table.docutils td,.rst-content table.field-list td,.wy-table td{background-color:transparent;vertical-align:middle}.rst-content table.docutils td p,.rst-content table.field-list td p,.wy-table td p{line-height:18px}.rst-content table.docutils td p:last-child,.rst-content table.field-list td p:last-child,.wy-table td p:last-child{margin-bottom:0}.rst-content table.docutils .wy-table-cell-min,.rst-content table.field-list .wy-table-cell-min,.wy-table .wy-table-cell-min{width:1%;padding-right:0}.rst-content table.docutils .wy-table-cell-min input[type=checkbox],.rst-content table.field-list .wy-table-cell-min input[type=checkbox],.wy-table .wy-table-cell-min input[type=checkbox]{margin:0}.wy-table-secondary{color:grey;font-size:90%}.wy-table-tertiary{color:grey;font-size:80%}.rst-content table.docutils:not(.field-list) tr:nth-child(2n-1) td,.wy-table-backed,.wy-table-odd td,.wy-table-striped tr:nth-child(2n-1) td{background-color:#f3f6f6}.rst-content table.docutils,.wy-table-bordered-all{border:1px solid #e1e4e5}.rst-content table.docutils td,.wy-table-bordered-all td{border-bottom:1px solid #e1e4e5;border-left:1px solid #e1e4e5}.rst-content table.docutils tbody>tr:last-child td,.wy-table-bordered-all tbody>tr:last-child td{border-bottom-width:0}.wy-table-bordered{border:1px solid #e1e4e5}.wy-table-bordered-rows td{border-bottom:1px solid #e1e4e5}.wy-table-bordered-rows tbody>tr:last-child td{border-bottom-width:0}.wy-table-horizontal td,.wy-table-horizontal th{border-width:0 0 1px;border-bottom:1px solid #e1e4e5}.wy-table-horizontal tbody>tr:last-child td{border-bottom-width:0}.wy-table-responsive{margin-bottom:24px;max-width:100%;overflow:auto}.wy-table-responsive table{margin-bottom:0!important}.wy-table-responsive table td,.wy-table-responsive table th{white-space:nowrap}a{color:#2980b9;text-decoration:none;cursor:pointer}a:hover{color:#3091d1}a:visited{color:#9b59b6}html{height:100%}body,html{overflow-x:hidden}body{font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;font-weight:400;color:#404040;min-height:100%;background:#edf0f2}.wy-text-left{text-align:left}.wy-text-center{text-align:center}.wy-text-right{text-align:right}.wy-text-large{font-size:120%}.wy-text-normal{font-size:100%}.wy-text-small,small{font-size:80%}.wy-text-strike{text-decoration:line-through}.wy-text-warning{color:#e67e22!important}a.wy-text-warning:hover{color:#eb9950!important}.wy-text-info{color:#2980b9!important}a.wy-text-info:hover{color:#409ad5!important}.wy-text-success{color:#27ae60!important}a.wy-text-success:hover{color:#36d278!important}.wy-text-danger{color:#e74c3c!important}a.wy-text-danger:hover{color:#ed7669!important}.wy-text-neutral{color:#404040!important}a.wy-text-neutral:hover{color:#595959!important}.rst-content .toctree-wrapper>p.caption,h1,h2,h3,h4,h5,h6,legend{margin-top:0;font-weight:700;font-family:Roboto Slab,ff-tisa-web-pro,Georgia,Arial,sans-serif}p{line-height:24px;font-size:16px;margin:0 0 24px}h1{font-size:175%}.rst-content .toctree-wrapper>p.caption,h2{font-size:150%}h3{font-size:125%}h4{font-size:115%}h5{font-size:110%}h6{font-size:100%}hr{display:block;height:1px;border:0;border-top:1px solid #e1e4e5;margin:24px 0;padding:0}.rst-content code,.rst-content tt,code{white-space:nowrap;max-width:100%;background:#fff;border:1px solid #e1e4e5;font-size:75%;padding:0 5px;font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;color:#e74c3c;overflow-x:auto}.rst-content tt.code-large,code.code-large{font-size:90%}.rst-content .section ul,.rst-content .toctree-wrapper ul,.rst-content section ul,.wy-plain-list-disc,article ul{list-style:disc;line-height:24px;margin-bottom:24px}.rst-content .section ul li,.rst-content .toctree-wrapper ul li,.rst-content section ul li,.wy-plain-list-disc li,article ul li{list-style:disc;margin-left:24px}.rst-content .section ul li p:last-child,.rst-content .section ul li ul,.rst-content .toctree-wrapper ul li p:last-child,.rst-content .toctree-wrapper ul li ul,.rst-content section ul li p:last-child,.rst-content section ul li ul,.wy-plain-list-disc li p:last-child,.wy-plain-list-disc li ul,article ul li p:last-child,article ul li ul{margin-bottom:0}.rst-content .section ul li li,.rst-content .toctree-wrapper ul li li,.rst-content section ul li li,.wy-plain-list-disc li li,article ul li li{list-style:circle}.rst-content .section ul li li li,.rst-content .toctree-wrapper ul li li li,.rst-content section ul li li li,.wy-plain-list-disc li li li,article ul li li li{list-style:square}.rst-content .section ul li ol li,.rst-content .toctree-wrapper ul li ol li,.rst-content section ul li ol li,.wy-plain-list-disc li ol li,article ul li ol li{list-style:decimal}.rst-content .section ol,.rst-content .section ol.arabic,.rst-content .toctree-wrapper ol,.rst-content .toctree-wrapper ol.arabic,.rst-content section ol,.rst-content section ol.arabic,.wy-plain-list-decimal,article ol{list-style:decimal;line-height:24px;margin-bottom:24px}.rst-content .section ol.arabic li,.rst-content .section ol li,.rst-content .toctree-wrapper ol.arabic li,.rst-content .toctree-wrapper ol li,.rst-content section ol.arabic li,.rst-content section ol li,.wy-plain-list-decimal li,article ol li{list-style:decimal;margin-left:24px}.rst-content .section ol.arabic li ul,.rst-content .section ol li p:last-child,.rst-content .section ol li ul,.rst-content .toctree-wrapper ol.arabic li ul,.rst-content .toctree-wrapper ol li p:last-child,.rst-content .toctree-wrapper ol li ul,.rst-content section ol.arabic li ul,.rst-content section ol li p:last-child,.rst-content section ol li ul,.wy-plain-list-decimal li p:last-child,.wy-plain-list-decimal li ul,article ol li p:last-child,article ol li ul{margin-bottom:0}.rst-content .section ol.arabic li ul li,.rst-content .section ol li ul li,.rst-content .toctree-wrapper ol.arabic li ul li,.rst-content .toctree-wrapper ol li ul li,.rst-content section ol.arabic li ul li,.rst-content section ol li ul li,.wy-plain-list-decimal li ul li,article ol li ul li{list-style:disc}.wy-breadcrumbs{*zoom:1}.wy-breadcrumbs:after,.wy-breadcrumbs:before{display:table;content:""}.wy-breadcrumbs:after{clear:both}.wy-breadcrumbs>li{display:inline-block;padding-top:5px}.wy-breadcrumbs>li.wy-breadcrumbs-aside{float:right}.rst-content .wy-breadcrumbs>li code,.rst-content .wy-breadcrumbs>li tt,.wy-breadcrumbs>li .rst-content tt,.wy-breadcrumbs>li code{all:inherit;color:inherit}.breadcrumb-item:before{content:"/";color:#bbb;font-size:13px;padding:0 6px 0 3px}.wy-breadcrumbs-extra{margin-bottom:0;color:#b3b3b3;font-size:80%;display:inline-block}@media screen and (max-width:480px){.wy-breadcrumbs-extra,.wy-breadcrumbs li.wy-breadcrumbs-aside{display:none}}@media print{.wy-breadcrumbs li.wy-breadcrumbs-aside{display:none}}html{font-size:16px}.wy-affix{position:fixed;top:1.618em}.wy-menu a:hover{text-decoration:none}.wy-menu-horiz{*zoom:1}.wy-menu-horiz:after,.wy-menu-horiz:before{display:table;content:""}.wy-menu-horiz:after{clear:both}.wy-menu-horiz li,.wy-menu-horiz ul{display:inline-block}.wy-menu-horiz li:hover{background:hsla(0,0%,100%,.1)}.wy-menu-horiz li.divide-left{border-left:1px solid #404040}.wy-menu-horiz li.divide-right{border-right:1px solid #404040}.wy-menu-horiz a{height:32px;display:inline-block;line-height:32px;padding:0 16px}.wy-menu-vertical{width:300px}.wy-menu-vertical header,.wy-menu-vertical p.caption{color:#55a5d9;height:32px;line-height:32px;padding:0 1.618em;margin:12px 0 0;display:block;font-weight:700;text-transform:uppercase;font-size:85%;white-space:nowrap}.wy-menu-vertical ul{margin-bottom:0}.wy-menu-vertical li.divide-top{border-top:1px solid #404040}.wy-menu-vertical li.divide-bottom{border-bottom:1px solid #404040}.wy-menu-vertical li.current{background:#e3e3e3}.wy-menu-vertical li.current a{color:grey;border-right:1px solid #c9c9c9;padding:.4045em 2.427em}.wy-menu-vertical li.current a:hover{background:#d6d6d6}.rst-content .wy-menu-vertical li tt,.wy-menu-vertical li .rst-content tt,.wy-menu-vertical li code{border:none;background:inherit;color:inherit;padding-left:0;padding-right:0}.wy-menu-vertical li button.toctree-expand{display:block;float:left;margin-left:-1.2em;line-height:18px;color:#4d4d4d;border:none;background:none;padding:0}.wy-menu-vertical li.current>a,.wy-menu-vertical li.on a{color:#404040;font-weight:700;position:relative;background:#fcfcfc;border:none;padding:.4045em 1.618em}.wy-menu-vertical li.current>a:hover,.wy-menu-vertical li.on a:hover{background:#fcfcfc}.wy-menu-vertical li.current>a:hover button.toctree-expand,.wy-menu-vertical li.on a:hover button.toctree-expand{color:grey}.wy-menu-vertical li.current>a button.toctree-expand,.wy-menu-vertical li.on a button.toctree-expand{display:block;line-height:18px;color:#333}.wy-menu-vertical li.toctree-l1.current>a{border-bottom:1px solid #c9c9c9;border-top:1px solid #c9c9c9}.wy-menu-vertical .toctree-l1.current .toctree-l2>ul,.wy-menu-vertical .toctree-l2.current .toctree-l3>ul,.wy-menu-vertical .toctree-l3.current .toctree-l4>ul,.wy-menu-vertical .toctree-l4.current .toctree-l5>ul,.wy-menu-vertical .toctree-l5.current .toctree-l6>ul,.wy-menu-vertical .toctree-l6.current .toctree-l7>ul,.wy-menu-vertical .toctree-l7.current .toctree-l8>ul,.wy-menu-vertical .toctree-l8.current .toctree-l9>ul,.wy-menu-vertical .toctree-l9.current .toctree-l10>ul,.wy-menu-vertical .toctree-l10.current .toctree-l11>ul{display:none}.wy-menu-vertical .toctree-l1.current .current.toctree-l2>ul,.wy-menu-vertical .toctree-l2.current .current.toctree-l3>ul,.wy-menu-vertical .toctree-l3.current .current.toctree-l4>ul,.wy-menu-vertical .toctree-l4.current .current.toctree-l5>ul,.wy-menu-vertical .toctree-l5.current .current.toctree-l6>ul,.wy-menu-vertical .toctree-l6.current .current.toctree-l7>ul,.wy-menu-vertical .toctree-l7.current .current.toctree-l8>ul,.wy-menu-vertical .toctree-l8.current .current.toctree-l9>ul,.wy-menu-vertical .toctree-l9.current .current.toctree-l10>ul,.wy-menu-vertical .toctree-l10.current .current.toctree-l11>ul{display:block}.wy-menu-vertical li.toctree-l3,.wy-menu-vertical li.toctree-l4{font-size:.9em}.wy-menu-vertical li.toctree-l2 a,.wy-menu-vertical li.toctree-l3 a,.wy-menu-vertical li.toctree-l4 a,.wy-menu-vertical li.toctree-l5 a,.wy-menu-vertical li.toctree-l6 a,.wy-menu-vertical li.toctree-l7 a,.wy-menu-vertical li.toctree-l8 a,.wy-menu-vertical li.toctree-l9 a,.wy-menu-vertical li.toctree-l10 a{color:#404040}.wy-menu-vertical li.toctree-l2 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l3 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l4 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l5 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l6 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l7 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l8 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l9 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l10 a:hover button.toctree-expand{color:grey}.wy-menu-vertical li.toctree-l2.current li.toctree-l3>a,.wy-menu-vertical li.toctree-l3.current li.toctree-l4>a,.wy-menu-vertical li.toctree-l4.current li.toctree-l5>a,.wy-menu-vertical li.toctree-l5.current li.toctree-l6>a,.wy-menu-vertical li.toctree-l6.current li.toctree-l7>a,.wy-menu-vertical li.toctree-l7.current li.toctree-l8>a,.wy-menu-vertical li.toctree-l8.current li.toctree-l9>a,.wy-menu-vertical li.toctree-l9.current li.toctree-l10>a,.wy-menu-vertical li.toctree-l10.current li.toctree-l11>a{display:block}.wy-menu-vertical li.toctree-l2.current>a{padding:.4045em 2.427em}.wy-menu-vertical li.toctree-l2.current li.toctree-l3>a{padding:.4045em 1.618em .4045em 4.045em}.wy-menu-vertical li.toctree-l3.current>a{padding:.4045em 4.045em}.wy-menu-vertical li.toctree-l3.current li.toctree-l4>a{padding:.4045em 1.618em .4045em 5.663em}.wy-menu-vertical li.toctree-l4.current>a{padding:.4045em 5.663em}.wy-menu-vertical li.toctree-l4.current li.toctree-l5>a{padding:.4045em 1.618em .4045em 7.281em}.wy-menu-vertical li.toctree-l5.current>a{padding:.4045em 7.281em}.wy-menu-vertical li.toctree-l5.current li.toctree-l6>a{padding:.4045em 1.618em .4045em 8.899em}.wy-menu-vertical li.toctree-l6.current>a{padding:.4045em 8.899em}.wy-menu-vertical li.toctree-l6.current li.toctree-l7>a{padding:.4045em 1.618em .4045em 10.517em}.wy-menu-vertical li.toctree-l7.current>a{padding:.4045em 10.517em}.wy-menu-vertical li.toctree-l7.current li.toctree-l8>a{padding:.4045em 1.618em .4045em 12.135em}.wy-menu-vertical li.toctree-l8.current>a{padding:.4045em 12.135em}.wy-menu-vertical li.toctree-l8.current li.toctree-l9>a{padding:.4045em 1.618em .4045em 13.753em}.wy-menu-vertical li.toctree-l9.current>a{padding:.4045em 13.753em}.wy-menu-vertical li.toctree-l9.current li.toctree-l10>a{padding:.4045em 1.618em .4045em 15.371em}.wy-menu-vertical li.toctree-l10.current>a{padding:.4045em 15.371em}.wy-menu-vertical li.toctree-l10.current li.toctree-l11>a{padding:.4045em 1.618em .4045em 16.989em}.wy-menu-vertical li.toctree-l2.current>a,.wy-menu-vertical li.toctree-l2.current li.toctree-l3>a{background:#c9c9c9}.wy-menu-vertical li.toctree-l2 button.toctree-expand{color:#a3a3a3}.wy-menu-vertical li.toctree-l3.current>a,.wy-menu-vertical li.toctree-l3.current li.toctree-l4>a{background:#bdbdbd}.wy-menu-vertical li.toctree-l3 button.toctree-expand{color:#969696}.wy-menu-vertical li.current ul{display:block}.wy-menu-vertical li ul{margin-bottom:0;display:none}.wy-menu-vertical li ul li a{margin-bottom:0;color:#d9d9d9;font-weight:400}.wy-menu-vertical a{line-height:18px;padding:.4045em 1.618em;display:block;position:relative;font-size:90%;color:#d9d9d9}.wy-menu-vertical a:hover{background-color:#4e4a4a;cursor:pointer}.wy-menu-vertical a:hover button.toctree-expand{color:#d9d9d9}.wy-menu-vertical a:active{background-color:#2980b9;cursor:pointer;color:#fff}.wy-menu-vertical a:active button.toctree-expand{color:#fff}.wy-side-nav-search{display:block;width:300px;padding:.809em;margin-bottom:.809em;z-index:200;background-color:#2980b9;text-align:center;color:#fcfcfc}.wy-side-nav-search input[type=text]{width:100%;border-radius:50px;padding:6px 12px;border-color:#2472a4}.wy-side-nav-search img{display:block;margin:auto auto .809em;height:45px;width:45px;background-color:#2980b9;padding:5px;border-radius:100%}.wy-side-nav-search .wy-dropdown>a,.wy-side-nav-search>a{color:#fcfcfc;font-size:100%;font-weight:700;display:inline-block;padding:4px 6px;margin-bottom:.809em;max-width:100%}.wy-side-nav-search .wy-dropdown>a:hover,.wy-side-nav-search .wy-dropdown>aactive,.wy-side-nav-search .wy-dropdown>afocus,.wy-side-nav-search>a:hover,.wy-side-nav-search>aactive,.wy-side-nav-search>afocus{background:hsla(0,0%,100%,.1)}.wy-side-nav-search .wy-dropdown>a img.logo,.wy-side-nav-search>a img.logo{display:block;margin:0 auto;height:auto;width:auto;border-radius:0;max-width:100%;background:transparent}.wy-side-nav-search .wy-dropdown>a.icon,.wy-side-nav-search>a.icon{display:block}.wy-side-nav-search .wy-dropdown>a.icon img.logo,.wy-side-nav-search>a.icon img.logo{margin-top:.85em}.wy-side-nav-search>div.switch-menus{position:relative;display:block;margin-top:-.4045em;margin-bottom:.809em;font-weight:400;color:hsla(0,0%,100%,.3)}.wy-side-nav-search>div.switch-menus>div.language-switch,.wy-side-nav-search>div.switch-menus>div.version-switch{display:inline-block;padding:.2em}.wy-side-nav-search>div.switch-menus>div.language-switch select,.wy-side-nav-search>div.switch-menus>div.version-switch select{display:inline-block;margin-right:-2rem;padding-right:2rem;max-width:240px;text-align-last:center;background:none;border:none;border-radius:0;box-shadow:none;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;font-size:1em;font-weight:400;color:hsla(0,0%,100%,.3);cursor:pointer;appearance:none;-webkit-appearance:none;-moz-appearance:none}.wy-side-nav-search>div.switch-menus>div.language-switch select:active,.wy-side-nav-search>div.switch-menus>div.language-switch select:focus,.wy-side-nav-search>div.switch-menus>div.language-switch select:hover,.wy-side-nav-search>div.switch-menus>div.version-switch select:active,.wy-side-nav-search>div.switch-menus>div.version-switch select:focus,.wy-side-nav-search>div.switch-menus>div.version-switch select:hover{background:hsla(0,0%,100%,.1);color:hsla(0,0%,100%,.5)}.wy-side-nav-search>div.switch-menus>div.language-switch select option,.wy-side-nav-search>div.switch-menus>div.version-switch select option{color:#000}.wy-side-nav-search>div.switch-menus>div.language-switch:has(>select):after,.wy-side-nav-search>div.switch-menus>div.version-switch:has(>select):after{display:inline-block;width:1.5em;height:100%;padding:.1em;content:"\f0d7";font-size:1em;line-height:1.2em;font-family:FontAwesome;text-align:center;pointer-events:none;box-sizing:border-box}.wy-nav .wy-menu-vertical header{color:#2980b9}.wy-nav .wy-menu-vertical a{color:#b3b3b3}.wy-nav .wy-menu-vertical a:hover{background-color:#2980b9;color:#fff}[data-menu-wrap]{-webkit-transition:all .2s ease-in;-moz-transition:all .2s ease-in;transition:all .2s ease-in;position:absolute;opacity:1;width:100%;opacity:0}[data-menu-wrap].move-center{left:0;right:auto;opacity:1}[data-menu-wrap].move-left{right:auto;left:-100%;opacity:0}[data-menu-wrap].move-right{right:-100%;left:auto;opacity:0}.wy-body-for-nav{background:#fcfcfc}.wy-grid-for-nav{position:absolute;width:100%;height:100%}.wy-nav-side{position:fixed;top:0;bottom:0;left:0;padding-bottom:2em;width:300px;overflow-x:hidden;overflow-y:hidden;min-height:100%;color:#9b9b9b;background:#343131;z-index:200}.wy-side-scroll{width:320px;position:relative;overflow-x:hidden;overflow-y:scroll;height:100%}.wy-nav-top{display:none;background:#2980b9;color:#fff;padding:.4045em .809em;position:relative;line-height:50px;text-align:center;font-size:100%;*zoom:1}.wy-nav-top:after,.wy-nav-top:before{display:table;content:""}.wy-nav-top:after{clear:both}.wy-nav-top a{color:#fff;font-weight:700}.wy-nav-top img{margin-right:12px;height:45px;width:45px;background-color:#2980b9;padding:5px;border-radius:100%}.wy-nav-top i{font-size:30px;float:left;cursor:pointer;padding-top:inherit}.wy-nav-content-wrap{margin-left:300px;background:#fcfcfc;min-height:100%}.wy-nav-content{padding:1.618em 3.236em;height:100%;max-width:800px;margin:auto}.wy-body-mask{position:fixed;width:100%;height:100%;background:rgba(0,0,0,.2);display:none;z-index:499}.wy-body-mask.on{display:block}footer{color:grey}footer p{margin-bottom:12px}.rst-content footer span.commit tt,footer span.commit .rst-content tt,footer span.commit code{padding:0;font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;font-size:1em;background:none;border:none;color:grey}.rst-footer-buttons{*zoom:1}.rst-footer-buttons:after,.rst-footer-buttons:before{width:100%;display:table;content:""}.rst-footer-buttons:after{clear:both}.rst-breadcrumbs-buttons{margin-top:12px;*zoom:1}.rst-breadcrumbs-buttons:after,.rst-breadcrumbs-buttons:before{display:table;content:""}.rst-breadcrumbs-buttons:after{clear:both}#search-results .search li{margin-bottom:24px;border-bottom:1px solid #e1e4e5;padding-bottom:24px}#search-results .search li:first-child{border-top:1px solid #e1e4e5;padding-top:24px}#search-results .search li a{font-size:120%;margin-bottom:12px;display:inline-block}#search-results .context{color:grey;font-size:90%}.genindextable li>ul{margin-left:24px}@media screen and (max-width:768px){.wy-body-for-nav{background:#fcfcfc}.wy-nav-top{display:block}.wy-nav-side{left:-300px}.wy-nav-side.shift{width:85%;left:0}.wy-menu.wy-menu-vertical,.wy-side-nav-search,.wy-side-scroll{width:auto}.wy-nav-content-wrap{margin-left:0}.wy-nav-content-wrap .wy-nav-content{padding:1.618em}.wy-nav-content-wrap.shift{position:fixed;min-width:100%;left:85%;top:0;height:100%;overflow:hidden}}@media screen and (min-width:1100px){.wy-nav-content-wrap{background:rgba(0,0,0,.05)}.wy-nav-content{margin:0;background:#fcfcfc}}@media print{.rst-versions,.wy-nav-side,footer{display:none}.wy-nav-content-wrap{margin-left:0}}.rst-versions{position:fixed;bottom:0;left:0;width:300px;color:#fcfcfc;background:#1f1d1d;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;z-index:400}.rst-versions a{color:#2980b9;text-decoration:none}.rst-versions .rst-badge-small{display:none}.rst-versions .rst-current-version{padding:12px;background-color:#272525;display:block;text-align:right;font-size:90%;cursor:pointer;color:#27ae60;*zoom:1}.rst-versions .rst-current-version:after,.rst-versions .rst-current-version:before{display:table;content:""}.rst-versions .rst-current-version:after{clear:both}.rst-content .code-block-caption .rst-versions .rst-current-version .headerlink,.rst-content .eqno .rst-versions .rst-current-version .headerlink,.rst-content .rst-versions .rst-current-version .admonition-title,.rst-content code.download .rst-versions .rst-current-version span:first-child,.rst-content dl dt .rst-versions .rst-current-version .headerlink,.rst-content h1 .rst-versions .rst-current-version .headerlink,.rst-content h2 .rst-versions .rst-current-version .headerlink,.rst-content h3 .rst-versions .rst-current-version .headerlink,.rst-content h4 .rst-versions .rst-current-version .headerlink,.rst-content h5 .rst-versions .rst-current-version .headerlink,.rst-content h6 .rst-versions .rst-current-version .headerlink,.rst-content p .rst-versions .rst-current-version .headerlink,.rst-content table>caption .rst-versions .rst-current-version .headerlink,.rst-content tt.download .rst-versions .rst-current-version span:first-child,.rst-versions .rst-current-version .fa,.rst-versions .rst-current-version .icon,.rst-versions .rst-current-version .rst-content .admonition-title,.rst-versions .rst-current-version .rst-content .code-block-caption .headerlink,.rst-versions .rst-current-version .rst-content .eqno .headerlink,.rst-versions .rst-current-version .rst-content code.download span:first-child,.rst-versions .rst-current-version .rst-content dl dt .headerlink,.rst-versions .rst-current-version .rst-content h1 .headerlink,.rst-versions .rst-current-version .rst-content h2 .headerlink,.rst-versions .rst-current-version .rst-content h3 .headerlink,.rst-versions .rst-current-version .rst-content h4 .headerlink,.rst-versions .rst-current-version .rst-content h5 .headerlink,.rst-versions .rst-current-version .rst-content h6 .headerlink,.rst-versions .rst-current-version .rst-content p .headerlink,.rst-versions .rst-current-version .rst-content table>caption .headerlink,.rst-versions .rst-current-version .rst-content tt.download span:first-child,.rst-versions .rst-current-version .wy-menu-vertical li button.toctree-expand,.wy-menu-vertical li .rst-versions .rst-current-version button.toctree-expand{color:#fcfcfc}.rst-versions .rst-current-version .fa-book,.rst-versions .rst-current-version .icon-book{float:left}.rst-versions .rst-current-version.rst-out-of-date{background-color:#e74c3c;color:#fff}.rst-versions .rst-current-version.rst-active-old-version{background-color:#f1c40f;color:#000}.rst-versions.shift-up{height:auto;max-height:100%;overflow-y:scroll}.rst-versions.shift-up .rst-other-versions{display:block}.rst-versions .rst-other-versions{font-size:90%;padding:12px;color:grey;display:none}.rst-versions .rst-other-versions hr{display:block;height:1px;border:0;margin:20px 0;padding:0;border-top:1px solid #413d3d}.rst-versions .rst-other-versions dd{display:inline-block;margin:0}.rst-versions .rst-other-versions dd a{display:inline-block;padding:6px;color:#fcfcfc}.rst-versions .rst-other-versions .rtd-current-item{font-weight:700}.rst-versions.rst-badge{width:auto;bottom:20px;right:20px;left:auto;border:none;max-width:300px;max-height:90%}.rst-versions.rst-badge .fa-book,.rst-versions.rst-badge .icon-book{float:none;line-height:30px}.rst-versions.rst-badge.shift-up .rst-current-version{text-align:right}.rst-versions.rst-badge.shift-up .rst-current-version .fa-book,.rst-versions.rst-badge.shift-up .rst-current-version .icon-book{float:left}.rst-versions.rst-badge>.rst-current-version{width:auto;height:30px;line-height:30px;padding:0 6px;display:block;text-align:center}@media screen and (max-width:768px){.rst-versions{width:85%;display:none}.rst-versions.shift{display:block}}#flyout-search-form{padding:6px}.rst-content .toctree-wrapper>p.caption,.rst-content h1,.rst-content h2,.rst-content h3,.rst-content h4,.rst-content h5,.rst-content h6{margin-bottom:24px}.rst-content img{max-width:100%;height:auto}.rst-content div.figure,.rst-content figure{margin-bottom:24px}.rst-content div.figure .caption-text,.rst-content figure .caption-text{font-style:italic}.rst-content div.figure p:last-child.caption,.rst-content figure p:last-child.caption{margin-bottom:0}.rst-content div.figure.align-center,.rst-content figure.align-center{text-align:center}.rst-content .section>a>img,.rst-content .section>img,.rst-content section>a>img,.rst-content section>img{margin-bottom:24px}.rst-content abbr[title]{text-decoration:none}.rst-content.style-external-links a.reference.external:after{font-family:FontAwesome;content:"\f08e";color:#b3b3b3;vertical-align:super;font-size:60%;margin:0 .2em}.rst-content blockquote{margin-left:24px;line-height:24px;margin-bottom:24px}.rst-content pre.literal-block{white-space:pre;margin:0;padding:12px;font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;display:block;overflow:auto}.rst-content div[class^=highlight],.rst-content pre.literal-block{border:1px solid #e1e4e5;overflow-x:auto;margin:1px 0 24px}.rst-content div[class^=highlight] div[class^=highlight],.rst-content pre.literal-block div[class^=highlight]{padding:0;border:none;margin:0}.rst-content div[class^=highlight] td.code{width:100%}.rst-content .linenodiv pre{border-right:1px solid #e6e9ea;margin:0;padding:12px;font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;user-select:none;pointer-events:none}.rst-content div[class^=highlight] pre{white-space:pre;margin:0;padding:12px;display:block;overflow:auto}.rst-content div[class^=highlight] pre .hll{display:block;margin:0 -12px;padding:0 12px}.rst-content .linenodiv pre,.rst-content div[class^=highlight] pre,.rst-content pre.literal-block{font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;font-size:12px;line-height:1.4}.rst-content div.highlight .gp,.rst-content div.highlight span.linenos{user-select:none;pointer-events:none}.rst-content div.highlight span.linenos{display:inline-block;padding-left:0;padding-right:12px;margin-right:12px;border-right:1px solid #e6e9ea}.rst-content .code-block-caption{font-style:italic;font-size:85%;line-height:1;padding:1em 0;text-align:center}@media print{.rst-content .codeblock,.rst-content div[class^=highlight],.rst-content div[class^=highlight] pre{white-space:pre-wrap}}.rst-content .admonition,.rst-content .admonition-todo,.rst-content .attention,.rst-content .caution,.rst-content .danger,.rst-content .error,.rst-content .hint,.rst-content .important,.rst-content .note,.rst-content .seealso,.rst-content .tip,.rst-content .warning{clear:both}.rst-content .admonition-todo .last,.rst-content .admonition-todo>:last-child,.rst-content .admonition .last,.rst-content .admonition>:last-child,.rst-content .attention .last,.rst-content .attention>:last-child,.rst-content .caution .last,.rst-content .caution>:last-child,.rst-content .danger .last,.rst-content .danger>:last-child,.rst-content .error .last,.rst-content .error>:last-child,.rst-content .hint .last,.rst-content .hint>:last-child,.rst-content .important .last,.rst-content .important>:last-child,.rst-content .note .last,.rst-content .note>:last-child,.rst-content .seealso .last,.rst-content .seealso>:last-child,.rst-content .tip .last,.rst-content .tip>:last-child,.rst-content .warning .last,.rst-content .warning>:last-child{margin-bottom:0}.rst-content .admonition-title:before{margin-right:4px}.rst-content .admonition table{border-color:rgba(0,0,0,.1)}.rst-content .admonition table td,.rst-content .admonition table th{background:transparent!important;border-color:rgba(0,0,0,.1)!important}.rst-content .section ol.loweralpha,.rst-content .section ol.loweralpha>li,.rst-content .toctree-wrapper ol.loweralpha,.rst-content .toctree-wrapper ol.loweralpha>li,.rst-content section ol.loweralpha,.rst-content section ol.loweralpha>li{list-style:lower-alpha}.rst-content .section ol.upperalpha,.rst-content .section ol.upperalpha>li,.rst-content .toctree-wrapper ol.upperalpha,.rst-content .toctree-wrapper ol.upperalpha>li,.rst-content section ol.upperalpha,.rst-content section ol.upperalpha>li{list-style:upper-alpha}.rst-content .section ol li>*,.rst-content .section ul li>*,.rst-content .toctree-wrapper ol li>*,.rst-content .toctree-wrapper ul li>*,.rst-content section ol li>*,.rst-content section ul li>*{margin-top:12px;margin-bottom:12px}.rst-content .section ol li>:first-child,.rst-content .section ul li>:first-child,.rst-content .toctree-wrapper ol li>:first-child,.rst-content .toctree-wrapper ul li>:first-child,.rst-content section ol li>:first-child,.rst-content section ul li>:first-child{margin-top:0}.rst-content .section ol li>p,.rst-content .section ol li>p:last-child,.rst-content .section ul li>p,.rst-content .section ul li>p:last-child,.rst-content .toctree-wrapper ol li>p,.rst-content .toctree-wrapper ol li>p:last-child,.rst-content .toctree-wrapper ul li>p,.rst-content .toctree-wrapper ul li>p:last-child,.rst-content section ol li>p,.rst-content section ol li>p:last-child,.rst-content section ul li>p,.rst-content section ul li>p:last-child{margin-bottom:12px}.rst-content .section ol li>p:only-child,.rst-content .section ol li>p:only-child:last-child,.rst-content .section ul li>p:only-child,.rst-content .section ul li>p:only-child:last-child,.rst-content .toctree-wrapper ol li>p:only-child,.rst-content .toctree-wrapper ol li>p:only-child:last-child,.rst-content .toctree-wrapper ul li>p:only-child,.rst-content .toctree-wrapper ul li>p:only-child:last-child,.rst-content section ol li>p:only-child,.rst-content section ol li>p:only-child:last-child,.rst-content section ul li>p:only-child,.rst-content section ul li>p:only-child:last-child{margin-bottom:0}.rst-content .section ol li>ol,.rst-content .section ol li>ul,.rst-content .section ul li>ol,.rst-content .section ul li>ul,.rst-content .toctree-wrapper ol li>ol,.rst-content .toctree-wrapper ol li>ul,.rst-content .toctree-wrapper ul li>ol,.rst-content .toctree-wrapper ul li>ul,.rst-content section ol li>ol,.rst-content section ol li>ul,.rst-content section ul li>ol,.rst-content section ul li>ul{margin-bottom:12px}.rst-content .section ol.simple li>*,.rst-content .section ol.simple li ol,.rst-content .section ol.simple li ul,.rst-content .section ul.simple li>*,.rst-content .section ul.simple li ol,.rst-content .section ul.simple li ul,.rst-content .toctree-wrapper ol.simple li>*,.rst-content .toctree-wrapper ol.simple li ol,.rst-content .toctree-wrapper ol.simple li ul,.rst-content .toctree-wrapper ul.simple li>*,.rst-content .toctree-wrapper ul.simple li ol,.rst-content .toctree-wrapper ul.simple li ul,.rst-content section ol.simple li>*,.rst-content section ol.simple li ol,.rst-content section ol.simple li ul,.rst-content section ul.simple li>*,.rst-content section ul.simple li ol,.rst-content section ul.simple li ul{margin-top:0;margin-bottom:0}.rst-content .line-block{margin-left:0;margin-bottom:24px;line-height:24px}.rst-content .line-block .line-block{margin-left:24px;margin-bottom:0}.rst-content .topic-title{font-weight:700;margin-bottom:12px}.rst-content .toc-backref{color:#404040}.rst-content .align-right{float:right;margin:0 0 24px 24px}.rst-content .align-left{float:left;margin:0 24px 24px 0}.rst-content .align-center{margin:auto}.rst-content .align-center:not(table){display:block}.rst-content .code-block-caption .headerlink,.rst-content .eqno .headerlink,.rst-content .toctree-wrapper>p.caption .headerlink,.rst-content dl dt .headerlink,.rst-content h1 .headerlink,.rst-content h2 .headerlink,.rst-content h3 .headerlink,.rst-content h4 .headerlink,.rst-content h5 .headerlink,.rst-content h6 .headerlink,.rst-content p.caption .headerlink,.rst-content p .headerlink,.rst-content table>caption .headerlink{opacity:0;font-size:14px;font-family:FontAwesome;margin-left:.5em}.rst-content .code-block-caption .headerlink:focus,.rst-content .code-block-caption:hover .headerlink,.rst-content .eqno .headerlink:focus,.rst-content .eqno:hover .headerlink,.rst-content .toctree-wrapper>p.caption .headerlink:focus,.rst-content .toctree-wrapper>p.caption:hover .headerlink,.rst-content dl dt .headerlink:focus,.rst-content dl dt:hover .headerlink,.rst-content h1 .headerlink:focus,.rst-content h1:hover .headerlink,.rst-content h2 .headerlink:focus,.rst-content h2:hover .headerlink,.rst-content h3 .headerlink:focus,.rst-content h3:hover .headerlink,.rst-content h4 .headerlink:focus,.rst-content h4:hover .headerlink,.rst-content h5 .headerlink:focus,.rst-content h5:hover .headerlink,.rst-content h6 .headerlink:focus,.rst-content h6:hover .headerlink,.rst-content p.caption .headerlink:focus,.rst-content p.caption:hover .headerlink,.rst-content p .headerlink:focus,.rst-content p:hover .headerlink,.rst-content table>caption .headerlink:focus,.rst-content table>caption:hover .headerlink{opacity:1}.rst-content p a{overflow-wrap:anywhere}.rst-content .wy-table td p,.rst-content .wy-table td ul,.rst-content .wy-table th p,.rst-content .wy-table th ul,.rst-content table.docutils td p,.rst-content table.docutils td ul,.rst-content table.docutils th p,.rst-content table.docutils th ul,.rst-content table.field-list td p,.rst-content table.field-list td ul,.rst-content table.field-list th p,.rst-content table.field-list th ul{font-size:inherit}.rst-content .btn:focus{outline:2px solid}.rst-content table>caption .headerlink:after{font-size:12px}.rst-content .centered{text-align:center}.rst-content .sidebar{float:right;width:40%;display:block;margin:0 0 24px 24px;padding:24px;background:#f3f6f6;border:1px solid #e1e4e5}.rst-content .sidebar dl,.rst-content .sidebar p,.rst-content .sidebar ul{font-size:90%}.rst-content .sidebar .last,.rst-content .sidebar>:last-child{margin-bottom:0}.rst-content .sidebar .sidebar-title{display:block;font-family:Roboto Slab,ff-tisa-web-pro,Georgia,Arial,sans-serif;font-weight:700;background:#e1e4e5;padding:6px 12px;margin:-24px -24px 24px;font-size:100%}.rst-content .highlighted{background:#f1c40f;box-shadow:0 0 0 2px #f1c40f;display:inline;font-weight:700}.rst-content .citation-reference,.rst-content .footnote-reference{vertical-align:baseline;position:relative;top:-.4em;line-height:0;font-size:90%}.rst-content .citation-reference>span.fn-bracket,.rst-content .footnote-reference>span.fn-bracket{display:none}.rst-content .hlist{width:100%}.rst-content dl dt span.classifier:before{content:" : "}.rst-content dl dt span.classifier-delimiter{display:none!important}html.writer-html4 .rst-content table.docutils.citation,html.writer-html4 .rst-content table.docutils.footnote{background:none;border:none}html.writer-html4 .rst-content table.docutils.citation td,html.writer-html4 .rst-content table.docutils.citation tr,html.writer-html4 .rst-content table.docutils.footnote td,html.writer-html4 .rst-content table.docutils.footnote tr{border:none;background-color:transparent!important;white-space:normal}html.writer-html4 .rst-content table.docutils.citation td.label,html.writer-html4 .rst-content table.docutils.footnote td.label{padding-left:0;padding-right:0;vertical-align:top}html.writer-html5 .rst-content dl.citation,html.writer-html5 .rst-content dl.field-list,html.writer-html5 .rst-content dl.footnote{display:grid;grid-template-columns:auto minmax(80%,95%)}html.writer-html5 .rst-content dl.citation>dt,html.writer-html5 .rst-content dl.field-list>dt,html.writer-html5 .rst-content dl.footnote>dt{display:inline-grid;grid-template-columns:max-content auto}html.writer-html5 .rst-content aside.citation,html.writer-html5 .rst-content aside.footnote,html.writer-html5 .rst-content div.citation{display:grid;grid-template-columns:auto auto minmax(.65rem,auto) minmax(40%,95%)}html.writer-html5 .rst-content aside.citation>span.label,html.writer-html5 .rst-content aside.footnote>span.label,html.writer-html5 .rst-content div.citation>span.label{grid-column-start:1;grid-column-end:2}html.writer-html5 .rst-content aside.citation>span.backrefs,html.writer-html5 .rst-content aside.footnote>span.backrefs,html.writer-html5 .rst-content div.citation>span.backrefs{grid-column-start:2;grid-column-end:3;grid-row-start:1;grid-row-end:3}html.writer-html5 .rst-content aside.citation>p,html.writer-html5 .rst-content aside.footnote>p,html.writer-html5 .rst-content div.citation>p{grid-column-start:4;grid-column-end:5}html.writer-html5 .rst-content dl.citation,html.writer-html5 .rst-content dl.field-list,html.writer-html5 .rst-content dl.footnote{margin-bottom:24px}html.writer-html5 .rst-content dl.citation>dt,html.writer-html5 .rst-content dl.field-list>dt,html.writer-html5 .rst-content dl.footnote>dt{padding-left:1rem}html.writer-html5 .rst-content dl.citation>dd,html.writer-html5 .rst-content dl.citation>dt,html.writer-html5 .rst-content dl.field-list>dd,html.writer-html5 .rst-content dl.field-list>dt,html.writer-html5 .rst-content dl.footnote>dd,html.writer-html5 .rst-content dl.footnote>dt{margin-bottom:0}html.writer-html5 .rst-content dl.citation,html.writer-html5 .rst-content dl.footnote{font-size:.9rem}html.writer-html5 .rst-content dl.citation>dt,html.writer-html5 .rst-content dl.footnote>dt{margin:0 .5rem .5rem 0;line-height:1.2rem;word-break:break-all;font-weight:400}html.writer-html5 .rst-content dl.citation>dt>span.brackets:before,html.writer-html5 .rst-content dl.footnote>dt>span.brackets:before{content:"["}html.writer-html5 .rst-content dl.citation>dt>span.brackets:after,html.writer-html5 .rst-content dl.footnote>dt>span.brackets:after{content:"]"}html.writer-html5 .rst-content dl.citation>dt>span.fn-backref,html.writer-html5 .rst-content dl.footnote>dt>span.fn-backref{text-align:left;font-style:italic;margin-left:.65rem;word-break:break-word;word-spacing:-.1rem;max-width:5rem}html.writer-html5 .rst-content dl.citation>dt>span.fn-backref>a,html.writer-html5 .rst-content dl.footnote>dt>span.fn-backref>a{word-break:keep-all}html.writer-html5 .rst-content dl.citation>dt>span.fn-backref>a:not(:first-child):before,html.writer-html5 .rst-content dl.footnote>dt>span.fn-backref>a:not(:first-child):before{content:" "}html.writer-html5 .rst-content dl.citation>dd,html.writer-html5 .rst-content dl.footnote>dd{margin:0 0 .5rem;line-height:1.2rem}html.writer-html5 .rst-content dl.citation>dd p,html.writer-html5 .rst-content dl.footnote>dd p{font-size:.9rem}html.writer-html5 .rst-content aside.citation,html.writer-html5 .rst-content aside.footnote,html.writer-html5 .rst-content div.citation{padding-left:1rem;padding-right:1rem;font-size:.9rem;line-height:1.2rem}html.writer-html5 .rst-content aside.citation p,html.writer-html5 .rst-content aside.footnote p,html.writer-html5 .rst-content div.citation p{font-size:.9rem;line-height:1.2rem;margin-bottom:12px}html.writer-html5 .rst-content aside.citation span.backrefs,html.writer-html5 .rst-content aside.footnote span.backrefs,html.writer-html5 .rst-content div.citation span.backrefs{text-align:left;font-style:italic;margin-left:.65rem;word-break:break-word;word-spacing:-.1rem;max-width:5rem}html.writer-html5 .rst-content aside.citation span.backrefs>a,html.writer-html5 .rst-content aside.footnote span.backrefs>a,html.writer-html5 .rst-content div.citation span.backrefs>a{word-break:keep-all}html.writer-html5 .rst-content aside.citation span.backrefs>a:not(:first-child):before,html.writer-html5 .rst-content aside.footnote span.backrefs>a:not(:first-child):before,html.writer-html5 .rst-content div.citation span.backrefs>a:not(:first-child):before{content:" "}html.writer-html5 .rst-content aside.citation span.label,html.writer-html5 .rst-content aside.footnote span.label,html.writer-html5 .rst-content div.citation span.label{line-height:1.2rem}html.writer-html5 .rst-content aside.citation-list,html.writer-html5 .rst-content aside.footnote-list,html.writer-html5 .rst-content div.citation-list{margin-bottom:24px}html.writer-html5 .rst-content dl.option-list kbd{font-size:.9rem}.rst-content table.docutils.footnote,html.writer-html4 .rst-content table.docutils.citation,html.writer-html5 .rst-content aside.footnote,html.writer-html5 .rst-content aside.footnote-list aside.footnote,html.writer-html5 .rst-content div.citation-list>div.citation,html.writer-html5 .rst-content dl.citation,html.writer-html5 .rst-content dl.footnote{color:grey}.rst-content table.docutils.footnote code,.rst-content table.docutils.footnote tt,html.writer-html4 .rst-content table.docutils.citation code,html.writer-html4 .rst-content table.docutils.citation tt,html.writer-html5 .rst-content aside.footnote-list aside.footnote code,html.writer-html5 .rst-content aside.footnote-list aside.footnote tt,html.writer-html5 .rst-content aside.footnote code,html.writer-html5 .rst-content aside.footnote tt,html.writer-html5 .rst-content div.citation-list>div.citation code,html.writer-html5 .rst-content div.citation-list>div.citation tt,html.writer-html5 .rst-content dl.citation code,html.writer-html5 .rst-content dl.citation tt,html.writer-html5 .rst-content dl.footnote code,html.writer-html5 .rst-content dl.footnote tt{color:#555}.rst-content .wy-table-responsive.citation,.rst-content .wy-table-responsive.footnote{margin-bottom:0}.rst-content .wy-table-responsive.citation+:not(.citation),.rst-content .wy-table-responsive.footnote+:not(.footnote){margin-top:24px}.rst-content .wy-table-responsive.citation:last-child,.rst-content .wy-table-responsive.footnote:last-child{margin-bottom:24px}.rst-content table.docutils th{border-color:#e1e4e5}html.writer-html5 .rst-content table.docutils th{border:1px solid #e1e4e5}html.writer-html5 .rst-content table.docutils td>p,html.writer-html5 .rst-content table.docutils th>p{line-height:1rem;margin-bottom:0;font-size:.9rem}.rst-content table.docutils td .last,.rst-content table.docutils td .last>:last-child{margin-bottom:0}.rst-content table.field-list,.rst-content table.field-list td{border:none}.rst-content table.field-list td p{line-height:inherit}.rst-content table.field-list td>strong{display:inline-block}.rst-content table.field-list .field-name{padding-right:10px;text-align:left;white-space:nowrap}.rst-content table.field-list .field-body{text-align:left}.rst-content code,.rst-content tt{color:#000;font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;padding:2px 5px}.rst-content code big,.rst-content code em,.rst-content tt big,.rst-content tt em{font-size:100%!important;line-height:normal}.rst-content code.literal,.rst-content tt.literal{color:#e74c3c;white-space:normal}.rst-content code.xref,.rst-content tt.xref,a .rst-content code,a .rst-content tt{font-weight:700;color:#404040;overflow-wrap:normal}.rst-content kbd,.rst-content pre,.rst-content samp{font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace}.rst-content a code,.rst-content a tt{color:#2980b9}.rst-content dl{margin-bottom:24px}.rst-content dl dt{font-weight:700;margin-bottom:12px}.rst-content dl ol,.rst-content dl p,.rst-content dl table,.rst-content dl ul{margin-bottom:12px}.rst-content dl dd{margin:0 0 12px 24px;line-height:24px}.rst-content dl dd>ol:last-child,.rst-content dl dd>p:last-child,.rst-content dl dd>table:last-child,.rst-content dl dd>ul:last-child{margin-bottom:0}html.writer-html4 .rst-content dl:not(.docutils),html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple){margin-bottom:24px}html.writer-html4 .rst-content dl:not(.docutils)>dt,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple)>dt{display:table;margin:6px 0;font-size:90%;line-height:normal;background:#e7f2fa;color:#2980b9;border-top:3px solid #6ab0de;padding:6px;position:relative}html.writer-html4 .rst-content dl:not(.docutils)>dt:before,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple)>dt:before{color:#6ab0de}html.writer-html4 .rst-content dl:not(.docutils)>dt .headerlink,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple)>dt .headerlink{color:#404040;font-size:100%!important}html.writer-html4 .rst-content dl:not(.docutils) dl:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple)>dt,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) dl:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple)>dt{margin-bottom:6px;border:none;border-left:3px solid #ccc;background:#f0f0f0;color:#555}html.writer-html4 .rst-content dl:not(.docutils) dl:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple)>dt .headerlink,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) dl:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple)>dt .headerlink{color:#404040;font-size:100%!important}html.writer-html4 .rst-content dl:not(.docutils)>dt:first-child,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple)>dt:first-child{margin-top:0}html.writer-html4 .rst-content dl:not(.docutils) code.descclassname,html.writer-html4 .rst-content dl:not(.docutils) code.descname,html.writer-html4 .rst-content dl:not(.docutils) tt.descclassname,html.writer-html4 .rst-content dl:not(.docutils) tt.descname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) code.descclassname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) code.descname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) tt.descclassname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) tt.descname{background-color:transparent;border:none;padding:0;font-size:100%!important}html.writer-html4 .rst-content dl:not(.docutils) code.descname,html.writer-html4 .rst-content dl:not(.docutils) tt.descname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) code.descname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) tt.descname{font-weight:700}html.writer-html4 .rst-content dl:not(.docutils) .optional,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) .optional{display:inline-block;padding:0 4px;color:#000;font-weight:700}html.writer-html4 .rst-content dl:not(.docutils) .property,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) .property{display:inline-block;padding-right:8px;max-width:100%}html.writer-html4 .rst-content dl:not(.docutils) .k,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) .k{font-style:italic}html.writer-html4 .rst-content dl:not(.docutils) .descclassname,html.writer-html4 .rst-content dl:not(.docutils) .descname,html.writer-html4 .rst-content dl:not(.docutils) .sig-name,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) .descclassname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) .descname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) .sig-name{font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;color:#000}.rst-content .viewcode-back,.rst-content .viewcode-link{display:inline-block;color:#27ae60;font-size:80%;padding-left:24px}.rst-content .viewcode-back{display:block;float:right}.rst-content p.rubric{margin-bottom:12px;font-weight:700}.rst-content code.download,.rst-content tt.download{background:inherit;padding:inherit;font-weight:400;font-family:inherit;font-size:inherit;color:inherit;border:inherit;white-space:inherit}.rst-content code.download span:first-child,.rst-content tt.download span:first-child{-webkit-font-smoothing:subpixel-antialiased}.rst-content code.download span:first-child:before,.rst-content tt.download span:first-child:before{margin-right:4px}.rst-content .guilabel,.rst-content .menuselection{font-size:80%;font-weight:700;border-radius:4px;padding:2.4px 6px;margin:auto 2px}.rst-content .guilabel,.rst-content .menuselection{border:1px solid #7fbbe3;background:#e7f2fa}.rst-content :not(dl.option-list)>:not(dt):not(kbd):not(.kbd)>.kbd,.rst-content :not(dl.option-list)>:not(dt):not(kbd):not(.kbd)>kbd{color:inherit;font-size:80%;background-color:#fff;border:1px solid #a6a6a6;border-radius:4px;box-shadow:0 2px grey;padding:2.4px 6px;margin:auto 0}.rst-content .versionmodified{font-style:italic}@media screen and (max-width:480px){.rst-content .sidebar{width:100%}}span[id*=MathJax-Span]{color:#404040}.math{text-align:center}@font-face{font-family:Lato;src:url(fonts/lato-normal.woff2?bd03a2cc277bbbc338d464e679fe9942) format("woff2"),url(fonts/lato-normal.woff?27bd77b9162d388cb8d4c4217c7c5e2a) format("woff");font-weight:400;font-style:normal;font-display:block}@font-face{font-family:Lato;src:url(fonts/lato-bold.woff2?cccb897485813c7c256901dbca54ecf2) format("woff2"),url(fonts/lato-bold.woff?d878b6c29b10beca227e9eef4246111b) format("woff");font-weight:700;font-style:normal;font-display:block}@font-face{font-family:Lato;src:url(fonts/lato-bold-italic.woff2?0b6bb6725576b072c5d0b02ecdd1900d) format("woff2"),url(fonts/lato-bold-italic.woff?9c7e4e9eb485b4a121c760e61bc3707c) format("woff");font-weight:700;font-style:italic;font-display:block}@font-face{font-family:Lato;src:url(fonts/lato-normal-italic.woff2?4eb103b4d12be57cb1d040ed5e162e9d) format("woff2"),url(fonts/lato-normal-italic.woff?f28f2d6482446544ef1ea1ccc6dd5892) format("woff");font-weight:400;font-style:italic;font-display:block}@font-face{font-family:Roboto Slab;font-style:normal;font-weight:400;src:url(fonts/Roboto-Slab-Regular.woff2?7abf5b8d04d26a2cafea937019bca958) format("woff2"),url(fonts/Roboto-Slab-Regular.woff?c1be9284088d487c5e3ff0a10a92e58c) format("woff");font-display:block}@font-face{font-family:Roboto Slab;font-style:normal;font-weight:700;src:url(fonts/Roboto-Slab-Bold.woff2?9984f4a9bda09be08e83f2506954adbe) format("woff2"),url(fonts/Roboto-Slab-Bold.woff?bed5564a116b05148e3b3bea6fb1162a) format("woff");font-display:block} \ No newline at end of file diff --git a/docs/build/html/_static/custom.css b/docs/build/html/_static/custom.css deleted file mode 100644 index b5198bd..0000000 --- a/docs/build/html/_static/custom.css +++ /dev/null @@ -1 +0,0 @@ -/* 기본 상태로 복원 - 커스텀 스타일 제거 */ \ No newline at end of file diff --git a/docs/build/html/_static/doctools.js b/docs/build/html/_static/doctools.js deleted file mode 100644 index 0398ebb..0000000 --- a/docs/build/html/_static/doctools.js +++ /dev/null @@ -1,149 +0,0 @@ -/* - * Base JavaScript utilities for all Sphinx HTML documentation. - */ -"use strict"; - -const BLACKLISTED_KEY_CONTROL_ELEMENTS = new Set([ - "TEXTAREA", - "INPUT", - "SELECT", - "BUTTON", -]); - -const _ready = (callback) => { - if (document.readyState !== "loading") { - callback(); - } else { - document.addEventListener("DOMContentLoaded", callback); - } -}; - -/** - * Small JavaScript module for the documentation. - */ -const Documentation = { - init: () => { - Documentation.initDomainIndexTable(); - Documentation.initOnKeyListeners(); - }, - - /** - * i18n support - */ - TRANSLATIONS: {}, - PLURAL_EXPR: (n) => (n === 1 ? 0 : 1), - LOCALE: "unknown", - - // gettext and ngettext don't access this so that the functions - // can safely bound to a different name (_ = Documentation.gettext) - gettext: (string) => { - const translated = Documentation.TRANSLATIONS[string]; - switch (typeof translated) { - case "undefined": - return string; // no translation - case "string": - return translated; // translation exists - default: - return translated[0]; // (singular, plural) translation tuple exists - } - }, - - ngettext: (singular, plural, n) => { - const translated = Documentation.TRANSLATIONS[singular]; - if (typeof translated !== "undefined") - return translated[Documentation.PLURAL_EXPR(n)]; - return n === 1 ? singular : plural; - }, - - addTranslations: (catalog) => { - Object.assign(Documentation.TRANSLATIONS, catalog.messages); - Documentation.PLURAL_EXPR = new Function( - "n", - `return (${catalog.plural_expr})` - ); - Documentation.LOCALE = catalog.locale; - }, - - /** - * helper function to focus on search bar - */ - focusSearchBar: () => { - document.querySelectorAll("input[name=q]")[0]?.focus(); - }, - - /** - * Initialise the domain index toggle buttons - */ - initDomainIndexTable: () => { - const toggler = (el) => { - const idNumber = el.id.substr(7); - const toggledRows = document.querySelectorAll(`tr.cg-${idNumber}`); - if (el.src.substr(-9) === "minus.png") { - el.src = `${el.src.substr(0, el.src.length - 9)}plus.png`; - toggledRows.forEach((el) => (el.style.display = "none")); - } else { - el.src = `${el.src.substr(0, el.src.length - 8)}minus.png`; - toggledRows.forEach((el) => (el.style.display = "")); - } - }; - - const togglerElements = document.querySelectorAll("img.toggler"); - togglerElements.forEach((el) => - el.addEventListener("click", (event) => toggler(event.currentTarget)) - ); - togglerElements.forEach((el) => (el.style.display = "")); - if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) togglerElements.forEach(toggler); - }, - - initOnKeyListeners: () => { - // only install a listener if it is really needed - if ( - !DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS && - !DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS - ) - return; - - document.addEventListener("keydown", (event) => { - // bail for input elements - if (BLACKLISTED_KEY_CONTROL_ELEMENTS.has(document.activeElement.tagName)) return; - // bail with special keys - if (event.altKey || event.ctrlKey || event.metaKey) return; - - if (!event.shiftKey) { - switch (event.key) { - case "ArrowLeft": - if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) break; - - const prevLink = document.querySelector('link[rel="prev"]'); - if (prevLink && prevLink.href) { - window.location.href = prevLink.href; - event.preventDefault(); - } - break; - case "ArrowRight": - if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) break; - - const nextLink = document.querySelector('link[rel="next"]'); - if (nextLink && nextLink.href) { - window.location.href = nextLink.href; - event.preventDefault(); - } - break; - } - } - - // some keyboard layouts may need Shift to get / - switch (event.key) { - case "/": - if (!DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS) break; - Documentation.focusSearchBar(); - event.preventDefault(); - } - }); - }, -}; - -// quick alias for translations -const _ = Documentation.gettext; - -_ready(Documentation.init); diff --git a/docs/build/html/_static/documentation_options.js b/docs/build/html/_static/documentation_options.js deleted file mode 100644 index 03dec6c..0000000 --- a/docs/build/html/_static/documentation_options.js +++ /dev/null @@ -1,13 +0,0 @@ -const DOCUMENTATION_OPTIONS = { - VERSION: '2.0.0', - LANGUAGE: 'ko', - COLLAPSE_INDEX: false, - BUILDER: 'html', - FILE_SUFFIX: '.html', - LINK_SUFFIX: '.html', - HAS_SOURCE: true, - SOURCELINK_SUFFIX: '.txt', - NAVIGATION_WITH_KEYS: false, - SHOW_SEARCH_SUMMARY: true, - ENABLE_SEARCH_SHORTCUTS: true, -}; \ No newline at end of file diff --git a/docs/build/html/_static/file.png b/docs/build/html/_static/file.png deleted file mode 100644 index a858a41..0000000 Binary files a/docs/build/html/_static/file.png and /dev/null differ diff --git a/docs/build/html/_static/fonts/Lato/lato-bold.eot b/docs/build/html/_static/fonts/Lato/lato-bold.eot deleted file mode 100644 index 3361183..0000000 Binary files a/docs/build/html/_static/fonts/Lato/lato-bold.eot and /dev/null differ diff --git a/docs/build/html/_static/fonts/Lato/lato-bold.ttf b/docs/build/html/_static/fonts/Lato/lato-bold.ttf deleted file mode 100644 index 29f691d..0000000 Binary files a/docs/build/html/_static/fonts/Lato/lato-bold.ttf and /dev/null differ diff --git a/docs/build/html/_static/fonts/Lato/lato-bold.woff b/docs/build/html/_static/fonts/Lato/lato-bold.woff deleted file mode 100644 index c6dff51..0000000 Binary files a/docs/build/html/_static/fonts/Lato/lato-bold.woff and /dev/null differ diff --git a/docs/build/html/_static/fonts/Lato/lato-bold.woff2 b/docs/build/html/_static/fonts/Lato/lato-bold.woff2 deleted file mode 100644 index bb19504..0000000 Binary files a/docs/build/html/_static/fonts/Lato/lato-bold.woff2 and /dev/null differ diff --git a/docs/build/html/_static/fonts/Lato/lato-bolditalic.eot b/docs/build/html/_static/fonts/Lato/lato-bolditalic.eot deleted file mode 100644 index 3d41549..0000000 Binary files a/docs/build/html/_static/fonts/Lato/lato-bolditalic.eot and /dev/null differ diff --git a/docs/build/html/_static/fonts/Lato/lato-bolditalic.ttf b/docs/build/html/_static/fonts/Lato/lato-bolditalic.ttf deleted file mode 100644 index f402040..0000000 Binary files a/docs/build/html/_static/fonts/Lato/lato-bolditalic.ttf and /dev/null differ diff --git a/docs/build/html/_static/fonts/Lato/lato-bolditalic.woff b/docs/build/html/_static/fonts/Lato/lato-bolditalic.woff deleted file mode 100644 index 88ad05b..0000000 Binary files a/docs/build/html/_static/fonts/Lato/lato-bolditalic.woff and /dev/null differ diff --git a/docs/build/html/_static/fonts/Lato/lato-bolditalic.woff2 b/docs/build/html/_static/fonts/Lato/lato-bolditalic.woff2 deleted file mode 100644 index c4e3d80..0000000 Binary files a/docs/build/html/_static/fonts/Lato/lato-bolditalic.woff2 and /dev/null differ diff --git a/docs/build/html/_static/fonts/Lato/lato-italic.eot b/docs/build/html/_static/fonts/Lato/lato-italic.eot deleted file mode 100644 index 3f82642..0000000 Binary files a/docs/build/html/_static/fonts/Lato/lato-italic.eot and /dev/null differ diff --git a/docs/build/html/_static/fonts/Lato/lato-italic.ttf b/docs/build/html/_static/fonts/Lato/lato-italic.ttf deleted file mode 100644 index b4bfc9b..0000000 Binary files a/docs/build/html/_static/fonts/Lato/lato-italic.ttf and /dev/null differ diff --git a/docs/build/html/_static/fonts/Lato/lato-italic.woff b/docs/build/html/_static/fonts/Lato/lato-italic.woff deleted file mode 100644 index 76114bc..0000000 Binary files a/docs/build/html/_static/fonts/Lato/lato-italic.woff and /dev/null differ diff --git a/docs/build/html/_static/fonts/Lato/lato-italic.woff2 b/docs/build/html/_static/fonts/Lato/lato-italic.woff2 deleted file mode 100644 index 3404f37..0000000 Binary files a/docs/build/html/_static/fonts/Lato/lato-italic.woff2 and /dev/null differ diff --git a/docs/build/html/_static/fonts/Lato/lato-regular.eot b/docs/build/html/_static/fonts/Lato/lato-regular.eot deleted file mode 100644 index 11e3f2a..0000000 Binary files a/docs/build/html/_static/fonts/Lato/lato-regular.eot and /dev/null differ diff --git a/docs/build/html/_static/fonts/Lato/lato-regular.ttf b/docs/build/html/_static/fonts/Lato/lato-regular.ttf deleted file mode 100644 index 74decd9..0000000 Binary files a/docs/build/html/_static/fonts/Lato/lato-regular.ttf and /dev/null differ diff --git a/docs/build/html/_static/fonts/Lato/lato-regular.woff b/docs/build/html/_static/fonts/Lato/lato-regular.woff deleted file mode 100644 index ae1307f..0000000 Binary files a/docs/build/html/_static/fonts/Lato/lato-regular.woff and /dev/null differ diff --git a/docs/build/html/_static/fonts/Lato/lato-regular.woff2 b/docs/build/html/_static/fonts/Lato/lato-regular.woff2 deleted file mode 100644 index 3bf9843..0000000 Binary files a/docs/build/html/_static/fonts/Lato/lato-regular.woff2 and /dev/null differ diff --git a/docs/build/html/_static/fonts/RobotoSlab/roboto-slab-v7-bold.eot b/docs/build/html/_static/fonts/RobotoSlab/roboto-slab-v7-bold.eot deleted file mode 100644 index 79dc8ef..0000000 Binary files a/docs/build/html/_static/fonts/RobotoSlab/roboto-slab-v7-bold.eot and /dev/null differ diff --git a/docs/build/html/_static/fonts/RobotoSlab/roboto-slab-v7-bold.ttf b/docs/build/html/_static/fonts/RobotoSlab/roboto-slab-v7-bold.ttf deleted file mode 100644 index df5d1df..0000000 Binary files a/docs/build/html/_static/fonts/RobotoSlab/roboto-slab-v7-bold.ttf and /dev/null differ diff --git a/docs/build/html/_static/fonts/RobotoSlab/roboto-slab-v7-bold.woff b/docs/build/html/_static/fonts/RobotoSlab/roboto-slab-v7-bold.woff deleted file mode 100644 index 6cb6000..0000000 Binary files a/docs/build/html/_static/fonts/RobotoSlab/roboto-slab-v7-bold.woff and /dev/null differ diff --git a/docs/build/html/_static/fonts/RobotoSlab/roboto-slab-v7-bold.woff2 b/docs/build/html/_static/fonts/RobotoSlab/roboto-slab-v7-bold.woff2 deleted file mode 100644 index 7059e23..0000000 Binary files a/docs/build/html/_static/fonts/RobotoSlab/roboto-slab-v7-bold.woff2 and /dev/null differ diff --git a/docs/build/html/_static/fonts/RobotoSlab/roboto-slab-v7-regular.eot b/docs/build/html/_static/fonts/RobotoSlab/roboto-slab-v7-regular.eot deleted file mode 100644 index 2f7ca78..0000000 Binary files a/docs/build/html/_static/fonts/RobotoSlab/roboto-slab-v7-regular.eot and /dev/null differ diff --git a/docs/build/html/_static/fonts/RobotoSlab/roboto-slab-v7-regular.ttf b/docs/build/html/_static/fonts/RobotoSlab/roboto-slab-v7-regular.ttf deleted file mode 100644 index eb52a79..0000000 Binary files a/docs/build/html/_static/fonts/RobotoSlab/roboto-slab-v7-regular.ttf and /dev/null differ diff --git a/docs/build/html/_static/fonts/RobotoSlab/roboto-slab-v7-regular.woff b/docs/build/html/_static/fonts/RobotoSlab/roboto-slab-v7-regular.woff deleted file mode 100644 index f815f63..0000000 Binary files a/docs/build/html/_static/fonts/RobotoSlab/roboto-slab-v7-regular.woff and /dev/null differ diff --git a/docs/build/html/_static/fonts/RobotoSlab/roboto-slab-v7-regular.woff2 b/docs/build/html/_static/fonts/RobotoSlab/roboto-slab-v7-regular.woff2 deleted file mode 100644 index f2c76e5..0000000 Binary files a/docs/build/html/_static/fonts/RobotoSlab/roboto-slab-v7-regular.woff2 and /dev/null differ diff --git a/docs/build/html/_static/jquery.js b/docs/build/html/_static/jquery.js deleted file mode 100644 index c4c6022..0000000 --- a/docs/build/html/_static/jquery.js +++ /dev/null @@ -1,2 +0,0 @@ -/*! jQuery v3.6.0 | (c) OpenJS Foundation and other contributors | jquery.org/license */ -!function(e,t){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(C,e){"use strict";var t=[],r=Object.getPrototypeOf,s=t.slice,g=t.flat?function(e){return t.flat.call(e)}:function(e){return t.concat.apply([],e)},u=t.push,i=t.indexOf,n={},o=n.toString,v=n.hasOwnProperty,a=v.toString,l=a.call(Object),y={},m=function(e){return"function"==typeof e&&"number"!=typeof e.nodeType&&"function"!=typeof e.item},x=function(e){return null!=e&&e===e.window},E=C.document,c={type:!0,src:!0,nonce:!0,noModule:!0};function b(e,t,n){var r,i,o=(n=n||E).createElement("script");if(o.text=e,t)for(r in c)(i=t[r]||t.getAttribute&&t.getAttribute(r))&&o.setAttribute(r,i);n.head.appendChild(o).parentNode.removeChild(o)}function w(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?n[o.call(e)]||"object":typeof e}var f="3.6.0",S=function(e,t){return new S.fn.init(e,t)};function p(e){var t=!!e&&"length"in e&&e.length,n=w(e);return!m(e)&&!x(e)&&("array"===n||0===t||"number"==typeof t&&0+~]|"+M+")"+M+"*"),U=new RegExp(M+"|>"),X=new RegExp(F),V=new RegExp("^"+I+"$"),G={ID:new RegExp("^#("+I+")"),CLASS:new RegExp("^\\.("+I+")"),TAG:new RegExp("^("+I+"|[*])"),ATTR:new RegExp("^"+W),PSEUDO:new RegExp("^"+F),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:new RegExp("^(?:"+R+")$","i"),needsContext:new RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},Y=/HTML$/i,Q=/^(?:input|select|textarea|button)$/i,J=/^h\d$/i,K=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ee=/[+~]/,te=new RegExp("\\\\[\\da-fA-F]{1,6}"+M+"?|\\\\([^\\r\\n\\f])","g"),ne=function(e,t){var n="0x"+e.slice(1)-65536;return t||(n<0?String.fromCharCode(n+65536):String.fromCharCode(n>>10|55296,1023&n|56320))},re=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,ie=function(e,t){return t?"\0"===e?"\ufffd":e.slice(0,-1)+"\\"+e.charCodeAt(e.length-1).toString(16)+" ":"\\"+e},oe=function(){T()},ae=be(function(e){return!0===e.disabled&&"fieldset"===e.nodeName.toLowerCase()},{dir:"parentNode",next:"legend"});try{H.apply(t=O.call(p.childNodes),p.childNodes),t[p.childNodes.length].nodeType}catch(e){H={apply:t.length?function(e,t){L.apply(e,O.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function se(t,e,n,r){var i,o,a,s,u,l,c,f=e&&e.ownerDocument,p=e?e.nodeType:9;if(n=n||[],"string"!=typeof t||!t||1!==p&&9!==p&&11!==p)return n;if(!r&&(T(e),e=e||C,E)){if(11!==p&&(u=Z.exec(t)))if(i=u[1]){if(9===p){if(!(a=e.getElementById(i)))return n;if(a.id===i)return n.push(a),n}else if(f&&(a=f.getElementById(i))&&y(e,a)&&a.id===i)return n.push(a),n}else{if(u[2])return H.apply(n,e.getElementsByTagName(t)),n;if((i=u[3])&&d.getElementsByClassName&&e.getElementsByClassName)return H.apply(n,e.getElementsByClassName(i)),n}if(d.qsa&&!N[t+" "]&&(!v||!v.test(t))&&(1!==p||"object"!==e.nodeName.toLowerCase())){if(c=t,f=e,1===p&&(U.test(t)||z.test(t))){(f=ee.test(t)&&ye(e.parentNode)||e)===e&&d.scope||((s=e.getAttribute("id"))?s=s.replace(re,ie):e.setAttribute("id",s=S)),o=(l=h(t)).length;while(o--)l[o]=(s?"#"+s:":scope")+" "+xe(l[o]);c=l.join(",")}try{return H.apply(n,f.querySelectorAll(c)),n}catch(e){N(t,!0)}finally{s===S&&e.removeAttribute("id")}}}return g(t.replace($,"$1"),e,n,r)}function ue(){var r=[];return function e(t,n){return r.push(t+" ")>b.cacheLength&&delete e[r.shift()],e[t+" "]=n}}function le(e){return e[S]=!0,e}function ce(e){var t=C.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function fe(e,t){var n=e.split("|"),r=n.length;while(r--)b.attrHandle[n[r]]=t}function pe(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&e.sourceIndex-t.sourceIndex;if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function de(t){return function(e){return"input"===e.nodeName.toLowerCase()&&e.type===t}}function he(n){return function(e){var t=e.nodeName.toLowerCase();return("input"===t||"button"===t)&&e.type===n}}function ge(t){return function(e){return"form"in e?e.parentNode&&!1===e.disabled?"label"in e?"label"in e.parentNode?e.parentNode.disabled===t:e.disabled===t:e.isDisabled===t||e.isDisabled!==!t&&ae(e)===t:e.disabled===t:"label"in e&&e.disabled===t}}function ve(a){return le(function(o){return o=+o,le(function(e,t){var n,r=a([],e.length,o),i=r.length;while(i--)e[n=r[i]]&&(e[n]=!(t[n]=e[n]))})})}function ye(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}for(e in d=se.support={},i=se.isXML=function(e){var t=e&&e.namespaceURI,n=e&&(e.ownerDocument||e).documentElement;return!Y.test(t||n&&n.nodeName||"HTML")},T=se.setDocument=function(e){var t,n,r=e?e.ownerDocument||e:p;return r!=C&&9===r.nodeType&&r.documentElement&&(a=(C=r).documentElement,E=!i(C),p!=C&&(n=C.defaultView)&&n.top!==n&&(n.addEventListener?n.addEventListener("unload",oe,!1):n.attachEvent&&n.attachEvent("onunload",oe)),d.scope=ce(function(e){return a.appendChild(e).appendChild(C.createElement("div")),"undefined"!=typeof e.querySelectorAll&&!e.querySelectorAll(":scope fieldset div").length}),d.attributes=ce(function(e){return e.className="i",!e.getAttribute("className")}),d.getElementsByTagName=ce(function(e){return e.appendChild(C.createComment("")),!e.getElementsByTagName("*").length}),d.getElementsByClassName=K.test(C.getElementsByClassName),d.getById=ce(function(e){return a.appendChild(e).id=S,!C.getElementsByName||!C.getElementsByName(S).length}),d.getById?(b.filter.ID=function(e){var t=e.replace(te,ne);return function(e){return e.getAttribute("id")===t}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n=t.getElementById(e);return n?[n]:[]}}):(b.filter.ID=function(e){var n=e.replace(te,ne);return function(e){var t="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return t&&t.value===n}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n,r,i,o=t.getElementById(e);if(o){if((n=o.getAttributeNode("id"))&&n.value===e)return[o];i=t.getElementsByName(e),r=0;while(o=i[r++])if((n=o.getAttributeNode("id"))&&n.value===e)return[o]}return[]}}),b.find.TAG=d.getElementsByTagName?function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):d.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},b.find.CLASS=d.getElementsByClassName&&function(e,t){if("undefined"!=typeof t.getElementsByClassName&&E)return t.getElementsByClassName(e)},s=[],v=[],(d.qsa=K.test(C.querySelectorAll))&&(ce(function(e){var t;a.appendChild(e).innerHTML="",e.querySelectorAll("[msallowcapture^='']").length&&v.push("[*^$]="+M+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||v.push("\\["+M+"*(?:value|"+R+")"),e.querySelectorAll("[id~="+S+"-]").length||v.push("~="),(t=C.createElement("input")).setAttribute("name",""),e.appendChild(t),e.querySelectorAll("[name='']").length||v.push("\\["+M+"*name"+M+"*="+M+"*(?:''|\"\")"),e.querySelectorAll(":checked").length||v.push(":checked"),e.querySelectorAll("a#"+S+"+*").length||v.push(".#.+[+~]"),e.querySelectorAll("\\\f"),v.push("[\\r\\n\\f]")}),ce(function(e){e.innerHTML="";var t=C.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&v.push("name"+M+"*[*^$|!~]?="),2!==e.querySelectorAll(":enabled").length&&v.push(":enabled",":disabled"),a.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&v.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),v.push(",.*:")})),(d.matchesSelector=K.test(c=a.matches||a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.msMatchesSelector))&&ce(function(e){d.disconnectedMatch=c.call(e,"*"),c.call(e,"[s!='']:x"),s.push("!=",F)}),v=v.length&&new RegExp(v.join("|")),s=s.length&&new RegExp(s.join("|")),t=K.test(a.compareDocumentPosition),y=t||K.test(a.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},j=t?function(e,t){if(e===t)return l=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n||(1&(n=(e.ownerDocument||e)==(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!d.sortDetached&&t.compareDocumentPosition(e)===n?e==C||e.ownerDocument==p&&y(p,e)?-1:t==C||t.ownerDocument==p&&y(p,t)?1:u?P(u,e)-P(u,t):0:4&n?-1:1)}:function(e,t){if(e===t)return l=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,a=[e],s=[t];if(!i||!o)return e==C?-1:t==C?1:i?-1:o?1:u?P(u,e)-P(u,t):0;if(i===o)return pe(e,t);n=e;while(n=n.parentNode)a.unshift(n);n=t;while(n=n.parentNode)s.unshift(n);while(a[r]===s[r])r++;return r?pe(a[r],s[r]):a[r]==p?-1:s[r]==p?1:0}),C},se.matches=function(e,t){return se(e,null,null,t)},se.matchesSelector=function(e,t){if(T(e),d.matchesSelector&&E&&!N[t+" "]&&(!s||!s.test(t))&&(!v||!v.test(t)))try{var n=c.call(e,t);if(n||d.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(e){N(t,!0)}return 0":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(te,ne),e[3]=(e[3]||e[4]||e[5]||"").replace(te,ne),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||se.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&se.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return G.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&X.test(n)&&(t=h(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(te,ne).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=m[e+" "];return t||(t=new RegExp("(^|"+M+")"+e+"("+M+"|$)"))&&m(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(n,r,i){return function(e){var t=se.attr(e,n);return null==t?"!="===r:!r||(t+="","="===r?t===i:"!="===r?t!==i:"^="===r?i&&0===t.indexOf(i):"*="===r?i&&-1:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function j(e,n,r){return m(n)?S.grep(e,function(e,t){return!!n.call(e,t,e)!==r}):n.nodeType?S.grep(e,function(e){return e===n!==r}):"string"!=typeof n?S.grep(e,function(e){return-1)[^>]*|#([\w-]+))$/;(S.fn.init=function(e,t,n){var r,i;if(!e)return this;if(n=n||D,"string"==typeof e){if(!(r="<"===e[0]&&">"===e[e.length-1]&&3<=e.length?[null,e,null]:q.exec(e))||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof S?t[0]:t,S.merge(this,S.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:E,!0)),N.test(r[1])&&S.isPlainObject(t))for(r in t)m(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return(i=E.getElementById(r[2]))&&(this[0]=i,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):m(e)?void 0!==n.ready?n.ready(e):e(S):S.makeArray(e,this)}).prototype=S.fn,D=S(E);var L=/^(?:parents|prev(?:Until|All))/,H={children:!0,contents:!0,next:!0,prev:!0};function O(e,t){while((e=e[t])&&1!==e.nodeType);return e}S.fn.extend({has:function(e){var t=S(e,this),n=t.length;return this.filter(function(){for(var e=0;e\x20\t\r\n\f]*)/i,he=/^$|^module$|\/(?:java|ecma)script/i;ce=E.createDocumentFragment().appendChild(E.createElement("div")),(fe=E.createElement("input")).setAttribute("type","radio"),fe.setAttribute("checked","checked"),fe.setAttribute("name","t"),ce.appendChild(fe),y.checkClone=ce.cloneNode(!0).cloneNode(!0).lastChild.checked,ce.innerHTML="",y.noCloneChecked=!!ce.cloneNode(!0).lastChild.defaultValue,ce.innerHTML="",y.option=!!ce.lastChild;var ge={thead:[1,"","
"],col:[2,"","
"],tr:[2,"","
"],td:[3,"","
"],_default:[0,"",""]};function ve(e,t){var n;return n="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&A(e,t)?S.merge([e],n):n}function ye(e,t){for(var n=0,r=e.length;n",""]);var me=/<|&#?\w+;/;function xe(e,t,n,r,i){for(var o,a,s,u,l,c,f=t.createDocumentFragment(),p=[],d=0,h=e.length;d\s*$/g;function je(e,t){return A(e,"table")&&A(11!==t.nodeType?t:t.firstChild,"tr")&&S(e).children("tbody")[0]||e}function De(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function qe(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute("type"),e}function Le(e,t){var n,r,i,o,a,s;if(1===t.nodeType){if(Y.hasData(e)&&(s=Y.get(e).events))for(i in Y.remove(t,"handle events"),s)for(n=0,r=s[i].length;n").attr(n.scriptAttrs||{}).prop({charset:n.scriptCharset,src:n.url}).on("load error",i=function(e){r.remove(),i=null,e&&t("error"===e.type?404:200,e.type)}),E.head.appendChild(r[0])},abort:function(){i&&i()}}});var _t,zt=[],Ut=/(=)\?(?=&|$)|\?\?/;S.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=zt.pop()||S.expando+"_"+wt.guid++;return this[e]=!0,e}}),S.ajaxPrefilter("json jsonp",function(e,t,n){var r,i,o,a=!1!==e.jsonp&&(Ut.test(e.url)?"url":"string"==typeof e.data&&0===(e.contentType||"").indexOf("application/x-www-form-urlencoded")&&Ut.test(e.data)&&"data");if(a||"jsonp"===e.dataTypes[0])return r=e.jsonpCallback=m(e.jsonpCallback)?e.jsonpCallback():e.jsonpCallback,a?e[a]=e[a].replace(Ut,"$1"+r):!1!==e.jsonp&&(e.url+=(Tt.test(e.url)?"&":"?")+e.jsonp+"="+r),e.converters["script json"]=function(){return o||S.error(r+" was not called"),o[0]},e.dataTypes[0]="json",i=C[r],C[r]=function(){o=arguments},n.always(function(){void 0===i?S(C).removeProp(r):C[r]=i,e[r]&&(e.jsonpCallback=t.jsonpCallback,zt.push(r)),o&&m(i)&&i(o[0]),o=i=void 0}),"script"}),y.createHTMLDocument=((_t=E.implementation.createHTMLDocument("").body).innerHTML="
",2===_t.childNodes.length),S.parseHTML=function(e,t,n){return"string"!=typeof e?[]:("boolean"==typeof t&&(n=t,t=!1),t||(y.createHTMLDocument?((r=(t=E.implementation.createHTMLDocument("")).createElement("base")).href=E.location.href,t.head.appendChild(r)):t=E),o=!n&&[],(i=N.exec(e))?[t.createElement(i[1])]:(i=xe([e],t,o),o&&o.length&&S(o).remove(),S.merge([],i.childNodes)));var r,i,o},S.fn.load=function(e,t,n){var r,i,o,a=this,s=e.indexOf(" ");return-1").append(S.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this},S.expr.pseudos.animated=function(t){return S.grep(S.timers,function(e){return t===e.elem}).length},S.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l=S.css(e,"position"),c=S(e),f={};"static"===l&&(e.style.position="relative"),s=c.offset(),o=S.css(e,"top"),u=S.css(e,"left"),("absolute"===l||"fixed"===l)&&-1<(o+u).indexOf("auto")?(a=(r=c.position()).top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(u)||0),m(t)&&(t=t.call(e,n,S.extend({},s))),null!=t.top&&(f.top=t.top-s.top+a),null!=t.left&&(f.left=t.left-s.left+i),"using"in t?t.using.call(e,f):c.css(f)}},S.fn.extend({offset:function(t){if(arguments.length)return void 0===t?this:this.each(function(e){S.offset.setOffset(this,t,e)});var e,n,r=this[0];return r?r.getClientRects().length?(e=r.getBoundingClientRect(),n=r.ownerDocument.defaultView,{top:e.top+n.pageYOffset,left:e.left+n.pageXOffset}):{top:0,left:0}:void 0},position:function(){if(this[0]){var e,t,n,r=this[0],i={top:0,left:0};if("fixed"===S.css(r,"position"))t=r.getBoundingClientRect();else{t=this.offset(),n=r.ownerDocument,e=r.offsetParent||n.documentElement;while(e&&(e===n.body||e===n.documentElement)&&"static"===S.css(e,"position"))e=e.parentNode;e&&e!==r&&1===e.nodeType&&((i=S(e).offset()).top+=S.css(e,"borderTopWidth",!0),i.left+=S.css(e,"borderLeftWidth",!0))}return{top:t.top-i.top-S.css(r,"marginTop",!0),left:t.left-i.left-S.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent;while(e&&"static"===S.css(e,"position"))e=e.offsetParent;return e||re})}}),S.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(t,i){var o="pageYOffset"===i;S.fn[t]=function(e){return $(this,function(e,t,n){var r;if(x(e)?r=e:9===e.nodeType&&(r=e.defaultView),void 0===n)return r?r[i]:e[t];r?r.scrollTo(o?r.pageXOffset:n,o?n:r.pageYOffset):e[t]=n},t,e,arguments.length)}}),S.each(["top","left"],function(e,n){S.cssHooks[n]=Fe(y.pixelPosition,function(e,t){if(t)return t=We(e,n),Pe.test(t)?S(e).position()[n]+"px":t})}),S.each({Height:"height",Width:"width"},function(a,s){S.each({padding:"inner"+a,content:s,"":"outer"+a},function(r,o){S.fn[o]=function(e,t){var n=arguments.length&&(r||"boolean"!=typeof e),i=r||(!0===e||!0===t?"margin":"border");return $(this,function(e,t,n){var r;return x(e)?0===o.indexOf("outer")?e["inner"+a]:e.document.documentElement["client"+a]:9===e.nodeType?(r=e.documentElement,Math.max(e.body["scroll"+a],r["scroll"+a],e.body["offset"+a],r["offset"+a],r["client"+a])):void 0===n?S.css(e,t,i):S.style(e,t,n,i)},s,n?e:void 0,n)}})}),S.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){S.fn[t]=function(e){return this.on(t,e)}}),S.fn.extend({bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)},hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)}}),S.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(e,n){S.fn[n]=function(e,t){return 0"),n("table.docutils.footnote").wrap("
"),n("table.docutils.citation").wrap("
"),n(".wy-menu-vertical ul").not(".simple").siblings("a").each((function(){var t=n(this);expand=n(''),expand.on("click",(function(n){return e.toggleCurrent(t),n.stopPropagation(),!1})),t.prepend(expand)}))},reset:function(){var n=encodeURI(window.location.hash)||"#";try{var e=$(".wy-menu-vertical"),t=e.find('[href="'+n+'"]');if(0===t.length){var i=$('.document [id="'+n.substring(1)+'"]').closest("div.section");0===(t=e.find('[href="#'+i.attr("id")+'"]')).length&&(t=e.find('[href="#"]'))}if(t.length>0){$(".wy-menu-vertical .current").removeClass("current").attr("aria-expanded","false"),t.addClass("current").attr("aria-expanded","true"),t.closest("li.toctree-l1").parent().addClass("current").attr("aria-expanded","true");for(let n=1;n<=10;n++)t.closest("li.toctree-l"+n).addClass("current").attr("aria-expanded","true");t[0].scrollIntoView()}}catch(n){console.log("Error expanding nav for anchor",n)}},onScroll:function(){this.winScroll=!1;var n=this.win.scrollTop(),e=n+this.winHeight,t=this.navBar.scrollTop()+(n-this.winPosition);n<0||e>this.docHeight||(this.navBar.scrollTop(t),this.winPosition=n)},onResize:function(){this.winResize=!1,this.winHeight=this.win.height(),this.docHeight=$(document).height()},hashChange:function(){this.linkScroll=!0,this.win.one("hashchange",(function(){this.linkScroll=!1}))},toggleCurrent:function(n){var e=n.closest("li");e.siblings("li.current").removeClass("current").attr("aria-expanded","false"),e.siblings().find("li.current").removeClass("current").attr("aria-expanded","false");var t=e.find("> ul li");t.length&&(t.removeClass("current").attr("aria-expanded","false"),e.toggleClass("current").attr("aria-expanded",(function(n,e){return"true"==e?"false":"true"})))}},"undefined"!=typeof window&&(window.SphinxRtdTheme={Navigation:n.exports.ThemeNav,StickyNav:n.exports.ThemeNav}),function(){for(var n=0,e=["ms","moz","webkit","o"],t=0;t a.language.name.localeCompare(b.language.name)); - - const languagesHTML = ` -
-
Languages
- ${languages - .map( - (translation) => ` -
- ${translation.language.code} -
- `, - ) - .join("\n")} -
- `; - return languagesHTML; - } - - function renderVersions(config) { - if (!config.versions.active.length) { - return ""; - } - const versionsHTML = ` -
-
Versions
- ${config.versions.active - .map( - (version) => ` -
- ${version.slug} -
- `, - ) - .join("\n")} -
- `; - return versionsHTML; - } - - function renderDownloads(config) { - if (!Object.keys(config.versions.current.downloads).length) { - return ""; - } - const downloadsNameDisplay = { - pdf: "PDF", - epub: "Epub", - htmlzip: "HTML", - }; - - const downloadsHTML = ` -
-
Downloads
- ${Object.entries(config.versions.current.downloads) - .map( - ([name, url]) => ` -
- ${downloadsNameDisplay[name]} -
- `, - ) - .join("\n")} -
- `; - return downloadsHTML; - } - - document.addEventListener("readthedocs-addons-data-ready", function (event) { - const config = event.detail.data(); - - const flyout = ` -
- - Read the Docs - v: ${config.versions.current.slug} - - -
-
- ${renderLanguages(config)} - ${renderVersions(config)} - ${renderDownloads(config)} -
-
On Read the Docs
-
- Project Home -
-
- Builds -
-
- Downloads -
-
-
-
검색
-
-
- -
-
-
-
- - Hosted by Read the Docs - -
-
- `; - - // Inject the generated flyout into the body HTML element. - document.body.insertAdjacentHTML("beforeend", flyout); - - // Trigger the Read the Docs Addons Search modal when clicking on the "Search docs" input from inside the flyout. - document - .querySelector("#flyout-search-form") - .addEventListener("focusin", () => { - const event = new CustomEvent("readthedocs-search-show"); - document.dispatchEvent(event); - }); - }) -} - -if (themeLanguageSelector || themeVersionSelector) { - function onSelectorSwitch(event) { - const option = event.target.selectedIndex; - const item = event.target.options[option]; - window.location.href = item.dataset.url; - } - - document.addEventListener("readthedocs-addons-data-ready", function (event) { - const config = event.detail.data(); - - const versionSwitch = document.querySelector( - "div.switch-menus > div.version-switch", - ); - if (themeVersionSelector) { - let versions = config.versions.active; - if (config.versions.current.hidden || config.versions.current.type === "external") { - versions.unshift(config.versions.current); - } - const versionSelect = ` - - `; - - versionSwitch.innerHTML = versionSelect; - versionSwitch.firstElementChild.addEventListener("change", onSelectorSwitch); - } - - const languageSwitch = document.querySelector( - "div.switch-menus > div.language-switch", - ); - - if (themeLanguageSelector) { - if (config.projects.translations.length) { - // Add the current language to the options on the selector - let languages = config.projects.translations.concat( - config.projects.current, - ); - languages = languages.sort((a, b) => - a.language.name.localeCompare(b.language.name), - ); - - const languageSelect = ` - - `; - - languageSwitch.innerHTML = languageSelect; - languageSwitch.firstElementChild.addEventListener("change", onSelectorSwitch); - } - else { - languageSwitch.remove(); - } - } - }); -} - -document.addEventListener("readthedocs-addons-data-ready", function (event) { - // Trigger the Read the Docs Addons Search modal when clicking on "Search docs" input from the topnav. - document - .querySelector("[role='search'] input") - .addEventListener("focusin", () => { - const event = new CustomEvent("readthedocs-search-show"); - document.dispatchEvent(event); - }); -}); \ No newline at end of file diff --git a/docs/build/html/_static/language_data.js b/docs/build/html/_static/language_data.js deleted file mode 100644 index c7fe6c6..0000000 --- a/docs/build/html/_static/language_data.js +++ /dev/null @@ -1,192 +0,0 @@ -/* - * This script contains the language-specific data used by searchtools.js, - * namely the list of stopwords, stemmer, scorer and splitter. - */ - -var stopwords = ["a", "and", "are", "as", "at", "be", "but", "by", "for", "if", "in", "into", "is", "it", "near", "no", "not", "of", "on", "or", "such", "that", "the", "their", "then", "there", "these", "they", "this", "to", "was", "will", "with"]; - - -/* Non-minified version is copied as a separate JS file, if available */ - -/** - * Porter Stemmer - */ -var Stemmer = function() { - - var step2list = { - ational: 'ate', - tional: 'tion', - enci: 'ence', - anci: 'ance', - izer: 'ize', - bli: 'ble', - alli: 'al', - entli: 'ent', - eli: 'e', - ousli: 'ous', - ization: 'ize', - ation: 'ate', - ator: 'ate', - alism: 'al', - iveness: 'ive', - fulness: 'ful', - ousness: 'ous', - aliti: 'al', - iviti: 'ive', - biliti: 'ble', - logi: 'log' - }; - - var step3list = { - icate: 'ic', - ative: '', - alize: 'al', - iciti: 'ic', - ical: 'ic', - ful: '', - ness: '' - }; - - var c = "[^aeiou]"; // consonant - var v = "[aeiouy]"; // vowel - var C = c + "[^aeiouy]*"; // consonant sequence - var V = v + "[aeiou]*"; // vowel sequence - - var mgr0 = "^(" + C + ")?" + V + C; // [C]VC... is m>0 - var meq1 = "^(" + C + ")?" + V + C + "(" + V + ")?$"; // [C]VC[V] is m=1 - var mgr1 = "^(" + C + ")?" + V + C + V + C; // [C]VCVC... is m>1 - var s_v = "^(" + C + ")?" + v; // vowel in stem - - this.stemWord = function (w) { - var stem; - var suffix; - var firstch; - var origword = w; - - if (w.length < 3) - return w; - - var re; - var re2; - var re3; - var re4; - - firstch = w.substr(0,1); - if (firstch == "y") - w = firstch.toUpperCase() + w.substr(1); - - // Step 1a - re = /^(.+?)(ss|i)es$/; - re2 = /^(.+?)([^s])s$/; - - if (re.test(w)) - w = w.replace(re,"$1$2"); - else if (re2.test(w)) - w = w.replace(re2,"$1$2"); - - // Step 1b - re = /^(.+?)eed$/; - re2 = /^(.+?)(ed|ing)$/; - if (re.test(w)) { - var fp = re.exec(w); - re = new RegExp(mgr0); - if (re.test(fp[1])) { - re = /.$/; - w = w.replace(re,""); - } - } - else if (re2.test(w)) { - var fp = re2.exec(w); - stem = fp[1]; - re2 = new RegExp(s_v); - if (re2.test(stem)) { - w = stem; - re2 = /(at|bl|iz)$/; - re3 = new RegExp("([^aeiouylsz])\\1$"); - re4 = new RegExp("^" + C + v + "[^aeiouwxy]$"); - if (re2.test(w)) - w = w + "e"; - else if (re3.test(w)) { - re = /.$/; - w = w.replace(re,""); - } - else if (re4.test(w)) - w = w + "e"; - } - } - - // Step 1c - re = /^(.+?)y$/; - if (re.test(w)) { - var fp = re.exec(w); - stem = fp[1]; - re = new RegExp(s_v); - if (re.test(stem)) - w = stem + "i"; - } - - // Step 2 - re = /^(.+?)(ational|tional|enci|anci|izer|bli|alli|entli|eli|ousli|ization|ation|ator|alism|iveness|fulness|ousness|aliti|iviti|biliti|logi)$/; - if (re.test(w)) { - var fp = re.exec(w); - stem = fp[1]; - suffix = fp[2]; - re = new RegExp(mgr0); - if (re.test(stem)) - w = stem + step2list[suffix]; - } - - // Step 3 - re = /^(.+?)(icate|ative|alize|iciti|ical|ful|ness)$/; - if (re.test(w)) { - var fp = re.exec(w); - stem = fp[1]; - suffix = fp[2]; - re = new RegExp(mgr0); - if (re.test(stem)) - w = stem + step3list[suffix]; - } - - // Step 4 - re = /^(.+?)(al|ance|ence|er|ic|able|ible|ant|ement|ment|ent|ou|ism|ate|iti|ous|ive|ize)$/; - re2 = /^(.+?)(s|t)(ion)$/; - if (re.test(w)) { - var fp = re.exec(w); - stem = fp[1]; - re = new RegExp(mgr1); - if (re.test(stem)) - w = stem; - } - else if (re2.test(w)) { - var fp = re2.exec(w); - stem = fp[1] + fp[2]; - re2 = new RegExp(mgr1); - if (re2.test(stem)) - w = stem; - } - - // Step 5 - re = /^(.+?)e$/; - if (re.test(w)) { - var fp = re.exec(w); - stem = fp[1]; - re = new RegExp(mgr1); - re2 = new RegExp(meq1); - re3 = new RegExp("^" + C + v + "[^aeiouwxy]$"); - if (re.test(stem) || (re2.test(stem) && !(re3.test(stem)))) - w = stem; - } - re = /ll$/; - re2 = new RegExp(mgr1); - if (re.test(w) && re2.test(w)) { - re = /.$/; - w = w.replace(re,""); - } - - // and turn initial Y back to y - if (firstch == "y") - w = firstch.toLowerCase() + w.substr(1); - return w; - } -} - diff --git a/docs/build/html/_static/minus.png b/docs/build/html/_static/minus.png deleted file mode 100644 index d96755f..0000000 Binary files a/docs/build/html/_static/minus.png and /dev/null differ diff --git a/docs/build/html/_static/plus.png b/docs/build/html/_static/plus.png deleted file mode 100644 index 7107cec..0000000 Binary files a/docs/build/html/_static/plus.png and /dev/null differ diff --git a/docs/build/html/_static/pygments.css b/docs/build/html/_static/pygments.css deleted file mode 100644 index 6f8b210..0000000 --- a/docs/build/html/_static/pygments.css +++ /dev/null @@ -1,75 +0,0 @@ -pre { line-height: 125%; } -td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; } -span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; } -td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } -span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } -.highlight .hll { background-color: #ffffcc } -.highlight { background: #f8f8f8; } -.highlight .c { color: #3D7B7B; font-style: italic } /* Comment */ -.highlight .err { border: 1px solid #F00 } /* Error */ -.highlight .k { color: #008000; font-weight: bold } /* Keyword */ -.highlight .o { color: #666 } /* Operator */ -.highlight .ch { color: #3D7B7B; font-style: italic } /* Comment.Hashbang */ -.highlight .cm { color: #3D7B7B; font-style: italic } /* Comment.Multiline */ -.highlight .cp { color: #9C6500 } /* Comment.Preproc */ -.highlight .cpf { color: #3D7B7B; font-style: italic } /* Comment.PreprocFile */ -.highlight .c1 { color: #3D7B7B; font-style: italic } /* Comment.Single */ -.highlight .cs { color: #3D7B7B; font-style: italic } /* Comment.Special */ -.highlight .gd { color: #A00000 } /* Generic.Deleted */ -.highlight .ge { font-style: italic } /* Generic.Emph */ -.highlight .ges { font-weight: bold; font-style: italic } /* Generic.EmphStrong */ -.highlight .gr { color: #E40000 } /* Generic.Error */ -.highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */ -.highlight .gi { color: #008400 } /* Generic.Inserted */ -.highlight .go { color: #717171 } /* Generic.Output */ -.highlight .gp { color: #000080; font-weight: bold } /* Generic.Prompt */ -.highlight .gs { font-weight: bold } /* Generic.Strong */ -.highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */ -.highlight .gt { color: #04D } /* Generic.Traceback */ -.highlight .kc { color: #008000; font-weight: bold } /* Keyword.Constant */ -.highlight .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */ -.highlight .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */ -.highlight .kp { color: #008000 } /* Keyword.Pseudo */ -.highlight .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */ -.highlight .kt { color: #B00040 } /* Keyword.Type */ -.highlight .m { color: #666 } /* Literal.Number */ -.highlight .s { color: #BA2121 } /* Literal.String */ -.highlight .na { color: #687822 } /* Name.Attribute */ -.highlight .nb { color: #008000 } /* Name.Builtin */ -.highlight .nc { color: #00F; font-weight: bold } /* Name.Class */ -.highlight .no { color: #800 } /* Name.Constant */ -.highlight .nd { color: #A2F } /* Name.Decorator */ -.highlight .ni { color: #717171; font-weight: bold } /* Name.Entity */ -.highlight .ne { color: #CB3F38; font-weight: bold } /* Name.Exception */ -.highlight .nf { color: #00F } /* Name.Function */ -.highlight .nl { color: #767600 } /* Name.Label */ -.highlight .nn { color: #00F; font-weight: bold } /* Name.Namespace */ -.highlight .nt { color: #008000; font-weight: bold } /* Name.Tag */ -.highlight .nv { color: #19177C } /* Name.Variable */ -.highlight .ow { color: #A2F; font-weight: bold } /* Operator.Word */ -.highlight .w { color: #BBB } /* Text.Whitespace */ -.highlight .mb { color: #666 } /* Literal.Number.Bin */ -.highlight .mf { color: #666 } /* Literal.Number.Float */ -.highlight .mh { color: #666 } /* Literal.Number.Hex */ -.highlight .mi { color: #666 } /* Literal.Number.Integer */ -.highlight .mo { color: #666 } /* Literal.Number.Oct */ -.highlight .sa { color: #BA2121 } /* Literal.String.Affix */ -.highlight .sb { color: #BA2121 } /* Literal.String.Backtick */ -.highlight .sc { color: #BA2121 } /* Literal.String.Char */ -.highlight .dl { color: #BA2121 } /* Literal.String.Delimiter */ -.highlight .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */ -.highlight .s2 { color: #BA2121 } /* Literal.String.Double */ -.highlight .se { color: #AA5D1F; font-weight: bold } /* Literal.String.Escape */ -.highlight .sh { color: #BA2121 } /* Literal.String.Heredoc */ -.highlight .si { color: #A45A77; font-weight: bold } /* Literal.String.Interpol */ -.highlight .sx { color: #008000 } /* Literal.String.Other */ -.highlight .sr { color: #A45A77 } /* Literal.String.Regex */ -.highlight .s1 { color: #BA2121 } /* Literal.String.Single */ -.highlight .ss { color: #19177C } /* Literal.String.Symbol */ -.highlight .bp { color: #008000 } /* Name.Builtin.Pseudo */ -.highlight .fm { color: #00F } /* Name.Function.Magic */ -.highlight .vc { color: #19177C } /* Name.Variable.Class */ -.highlight .vg { color: #19177C } /* Name.Variable.Global */ -.highlight .vi { color: #19177C } /* Name.Variable.Instance */ -.highlight .vm { color: #19177C } /* Name.Variable.Magic */ -.highlight .il { color: #666 } /* Literal.Number.Integer.Long */ \ No newline at end of file diff --git a/docs/build/html/_static/searchtools.js b/docs/build/html/_static/searchtools.js deleted file mode 100644 index 91f4be5..0000000 --- a/docs/build/html/_static/searchtools.js +++ /dev/null @@ -1,635 +0,0 @@ -/* - * Sphinx JavaScript utilities for the full-text search. - */ -"use strict"; - -/** - * Simple result scoring code. - */ -if (typeof Scorer === "undefined") { - var Scorer = { - // Implement the following function to further tweak the score for each result - // The function takes a result array [docname, title, anchor, descr, score, filename] - // and returns the new score. - /* - score: result => { - const [docname, title, anchor, descr, score, filename, kind] = result - return score - }, - */ - - // query matches the full name of an object - objNameMatch: 11, - // or matches in the last dotted part of the object name - objPartialMatch: 6, - // Additive scores depending on the priority of the object - objPrio: { - 0: 15, // used to be importantResults - 1: 5, // used to be objectResults - 2: -5, // used to be unimportantResults - }, - // Used when the priority is not in the mapping. - objPrioDefault: 0, - - // query found in title - title: 15, - partialTitle: 7, - // query found in terms - term: 5, - partialTerm: 2, - }; -} - -// Global search result kind enum, used by themes to style search results. -class SearchResultKind { - static get index() { return "index"; } - static get object() { return "object"; } - static get text() { return "text"; } - static get title() { return "title"; } -} - -const _removeChildren = (element) => { - while (element && element.lastChild) element.removeChild(element.lastChild); -}; - -/** - * See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions#escaping - */ -const _escapeRegExp = (string) => - string.replace(/[.*+\-?^${}()|[\]\\]/g, "\\$&"); // $& means the whole matched string - -const _displayItem = (item, searchTerms, highlightTerms) => { - const docBuilder = DOCUMENTATION_OPTIONS.BUILDER; - const docFileSuffix = DOCUMENTATION_OPTIONS.FILE_SUFFIX; - const docLinkSuffix = DOCUMENTATION_OPTIONS.LINK_SUFFIX; - const showSearchSummary = DOCUMENTATION_OPTIONS.SHOW_SEARCH_SUMMARY; - const contentRoot = document.documentElement.dataset.content_root; - - const [docName, title, anchor, descr, score, _filename, kind] = item; - - let listItem = document.createElement("li"); - // Add a class representing the item's type: - // can be used by a theme's CSS selector for styling - // See SearchResultKind for the class names. - listItem.classList.add(`kind-${kind}`); - let requestUrl; - let linkUrl; - if (docBuilder === "dirhtml") { - // dirhtml builder - let dirname = docName + "/"; - if (dirname.match(/\/index\/$/)) - dirname = dirname.substring(0, dirname.length - 6); - else if (dirname === "index/") dirname = ""; - requestUrl = contentRoot + dirname; - linkUrl = requestUrl; - } else { - // normal html builders - requestUrl = contentRoot + docName + docFileSuffix; - linkUrl = docName + docLinkSuffix; - } - let linkEl = listItem.appendChild(document.createElement("a")); - linkEl.href = linkUrl + anchor; - linkEl.dataset.score = score; - linkEl.innerHTML = title; - if (descr) { - listItem.appendChild(document.createElement("span")).innerHTML = - " (" + descr + ")"; - // highlight search terms in the description - if (SPHINX_HIGHLIGHT_ENABLED) // set in sphinx_highlight.js - highlightTerms.forEach((term) => _highlightText(listItem, term, "highlighted")); - } - else if (showSearchSummary) - fetch(requestUrl) - .then((responseData) => responseData.text()) - .then((data) => { - if (data) - listItem.appendChild( - Search.makeSearchSummary(data, searchTerms, anchor) - ); - // highlight search terms in the summary - if (SPHINX_HIGHLIGHT_ENABLED) // set in sphinx_highlight.js - highlightTerms.forEach((term) => _highlightText(listItem, term, "highlighted")); - }); - Search.output.appendChild(listItem); -}; -const _finishSearch = (resultCount) => { - Search.stopPulse(); - Search.title.innerText = _("Search Results"); - if (!resultCount) - Search.status.innerText = Documentation.gettext( - "Your search did not match any documents. Please make sure that all words are spelled correctly and that you've selected enough categories." - ); - else - Search.status.innerText = Documentation.ngettext( - "Search finished, found one page matching the search query.", - "Search finished, found ${resultCount} pages matching the search query.", - resultCount, - ).replace('${resultCount}', resultCount); -}; -const _displayNextItem = ( - results, - resultCount, - searchTerms, - highlightTerms, -) => { - // results left, load the summary and display it - // this is intended to be dynamic (don't sub resultsCount) - if (results.length) { - _displayItem(results.pop(), searchTerms, highlightTerms); - setTimeout( - () => _displayNextItem(results, resultCount, searchTerms, highlightTerms), - 5 - ); - } - // search finished, update title and status message - else _finishSearch(resultCount); -}; -// Helper function used by query() to order search results. -// Each input is an array of [docname, title, anchor, descr, score, filename, kind]. -// Order the results by score (in opposite order of appearance, since the -// `_displayNextItem` function uses pop() to retrieve items) and then alphabetically. -const _orderResultsByScoreThenName = (a, b) => { - const leftScore = a[4]; - const rightScore = b[4]; - if (leftScore === rightScore) { - // same score: sort alphabetically - const leftTitle = a[1].toLowerCase(); - const rightTitle = b[1].toLowerCase(); - if (leftTitle === rightTitle) return 0; - return leftTitle > rightTitle ? -1 : 1; // inverted is intentional - } - return leftScore > rightScore ? 1 : -1; -}; - -/** - * Default splitQuery function. Can be overridden in ``sphinx.search`` with a - * custom function per language. - * - * The regular expression works by splitting the string on consecutive characters - * that are not Unicode letters, numbers, underscores, or emoji characters. - * This is the same as ``\W+`` in Python, preserving the surrogate pair area. - */ -if (typeof splitQuery === "undefined") { - var splitQuery = (query) => query - .split(/[^\p{Letter}\p{Number}_\p{Emoji_Presentation}]+/gu) - .filter(term => term) // remove remaining empty strings -} - -/** - * Search Module - */ -const Search = { - _index: null, - _queued_query: null, - _pulse_status: -1, - - htmlToText: (htmlString, anchor) => { - const htmlElement = new DOMParser().parseFromString(htmlString, 'text/html'); - for (const removalQuery of [".headerlink", "script", "style"]) { - htmlElement.querySelectorAll(removalQuery).forEach((el) => { el.remove() }); - } - if (anchor) { - const anchorContent = htmlElement.querySelector(`[role="main"] ${anchor}`); - if (anchorContent) return anchorContent.textContent; - - console.warn( - `Anchored content block not found. Sphinx search tries to obtain it via DOM query '[role=main] ${anchor}'. Check your theme or template.` - ); - } - - // if anchor not specified or not found, fall back to main content - const docContent = htmlElement.querySelector('[role="main"]'); - if (docContent) return docContent.textContent; - - console.warn( - "Content block not found. Sphinx search tries to obtain it via DOM query '[role=main]'. Check your theme or template." - ); - return ""; - }, - - init: () => { - const query = new URLSearchParams(window.location.search).get("q"); - document - .querySelectorAll('input[name="q"]') - .forEach((el) => (el.value = query)); - if (query) Search.performSearch(query); - }, - - loadIndex: (url) => - (document.body.appendChild(document.createElement("script")).src = url), - - setIndex: (index) => { - Search._index = index; - if (Search._queued_query !== null) { - const query = Search._queued_query; - Search._queued_query = null; - Search.query(query); - } - }, - - hasIndex: () => Search._index !== null, - - deferQuery: (query) => (Search._queued_query = query), - - stopPulse: () => (Search._pulse_status = -1), - - startPulse: () => { - if (Search._pulse_status >= 0) return; - - const pulse = () => { - Search._pulse_status = (Search._pulse_status + 1) % 4; - Search.dots.innerText = ".".repeat(Search._pulse_status); - if (Search._pulse_status >= 0) window.setTimeout(pulse, 500); - }; - pulse(); - }, - - /** - * perform a search for something (or wait until index is loaded) - */ - performSearch: (query) => { - // create the required interface elements - const searchText = document.createElement("h2"); - searchText.textContent = _("Searching"); - const searchSummary = document.createElement("p"); - searchSummary.classList.add("search-summary"); - searchSummary.innerText = ""; - const searchList = document.createElement("ul"); - searchList.setAttribute("role", "list"); - searchList.classList.add("search"); - - const out = document.getElementById("search-results"); - Search.title = out.appendChild(searchText); - Search.dots = Search.title.appendChild(document.createElement("span")); - Search.status = out.appendChild(searchSummary); - Search.output = out.appendChild(searchList); - - const searchProgress = document.getElementById("search-progress"); - // Some themes don't use the search progress node - if (searchProgress) { - searchProgress.innerText = _("Preparing search..."); - } - Search.startPulse(); - - // index already loaded, the browser was quick! - if (Search.hasIndex()) Search.query(query); - else Search.deferQuery(query); - }, - - _parseQuery: (query) => { - // stem the search terms and add them to the correct list - const stemmer = new Stemmer(); - const searchTerms = new Set(); - const excludedTerms = new Set(); - const highlightTerms = new Set(); - const objectTerms = new Set(splitQuery(query.toLowerCase().trim())); - splitQuery(query.trim()).forEach((queryTerm) => { - const queryTermLower = queryTerm.toLowerCase(); - - // maybe skip this "word" - // stopwords array is from language_data.js - if ( - stopwords.indexOf(queryTermLower) !== -1 || - queryTerm.match(/^\d+$/) - ) - return; - - // stem the word - let word = stemmer.stemWord(queryTermLower); - // select the correct list - if (word[0] === "-") excludedTerms.add(word.substr(1)); - else { - searchTerms.add(word); - highlightTerms.add(queryTermLower); - } - }); - - if (SPHINX_HIGHLIGHT_ENABLED) { // set in sphinx_highlight.js - localStorage.setItem("sphinx_highlight_terms", [...highlightTerms].join(" ")) - } - - // console.debug("SEARCH: searching for:"); - // console.info("required: ", [...searchTerms]); - // console.info("excluded: ", [...excludedTerms]); - - return [query, searchTerms, excludedTerms, highlightTerms, objectTerms]; - }, - - /** - * execute search (requires search index to be loaded) - */ - _performSearch: (query, searchTerms, excludedTerms, highlightTerms, objectTerms) => { - const filenames = Search._index.filenames; - const docNames = Search._index.docnames; - const titles = Search._index.titles; - const allTitles = Search._index.alltitles; - const indexEntries = Search._index.indexentries; - - // Collect multiple result groups to be sorted separately and then ordered. - // Each is an array of [docname, title, anchor, descr, score, filename, kind]. - const normalResults = []; - const nonMainIndexResults = []; - - _removeChildren(document.getElementById("search-progress")); - - const queryLower = query.toLowerCase().trim(); - for (const [title, foundTitles] of Object.entries(allTitles)) { - if (title.toLowerCase().trim().includes(queryLower) && (queryLower.length >= title.length/2)) { - for (const [file, id] of foundTitles) { - const score = Math.round(Scorer.title * queryLower.length / title.length); - const boost = titles[file] === title ? 1 : 0; // add a boost for document titles - normalResults.push([ - docNames[file], - titles[file] !== title ? `${titles[file]} > ${title}` : title, - id !== null ? "#" + id : "", - null, - score + boost, - filenames[file], - SearchResultKind.title, - ]); - } - } - } - - // search for explicit entries in index directives - for (const [entry, foundEntries] of Object.entries(indexEntries)) { - if (entry.includes(queryLower) && (queryLower.length >= entry.length/2)) { - for (const [file, id, isMain] of foundEntries) { - const score = Math.round(100 * queryLower.length / entry.length); - const result = [ - docNames[file], - titles[file], - id ? "#" + id : "", - null, - score, - filenames[file], - SearchResultKind.index, - ]; - if (isMain) { - normalResults.push(result); - } else { - nonMainIndexResults.push(result); - } - } - } - } - - // lookup as object - objectTerms.forEach((term) => - normalResults.push(...Search.performObjectSearch(term, objectTerms)) - ); - - // lookup as search terms in fulltext - normalResults.push(...Search.performTermsSearch(searchTerms, excludedTerms)); - - // let the scorer override scores with a custom scoring function - if (Scorer.score) { - normalResults.forEach((item) => (item[4] = Scorer.score(item))); - nonMainIndexResults.forEach((item) => (item[4] = Scorer.score(item))); - } - - // Sort each group of results by score and then alphabetically by name. - normalResults.sort(_orderResultsByScoreThenName); - nonMainIndexResults.sort(_orderResultsByScoreThenName); - - // Combine the result groups in (reverse) order. - // Non-main index entries are typically arbitrary cross-references, - // so display them after other results. - let results = [...nonMainIndexResults, ...normalResults]; - - // remove duplicate search results - // note the reversing of results, so that in the case of duplicates, the highest-scoring entry is kept - let seen = new Set(); - results = results.reverse().reduce((acc, result) => { - let resultStr = result.slice(0, 4).concat([result[5]]).map(v => String(v)).join(','); - if (!seen.has(resultStr)) { - acc.push(result); - seen.add(resultStr); - } - return acc; - }, []); - - return results.reverse(); - }, - - query: (query) => { - const [searchQuery, searchTerms, excludedTerms, highlightTerms, objectTerms] = Search._parseQuery(query); - const results = Search._performSearch(searchQuery, searchTerms, excludedTerms, highlightTerms, objectTerms); - - // for debugging - //Search.lastresults = results.slice(); // a copy - // console.info("search results:", Search.lastresults); - - // print the results - _displayNextItem(results, results.length, searchTerms, highlightTerms); - }, - - /** - * search for object names - */ - performObjectSearch: (object, objectTerms) => { - const filenames = Search._index.filenames; - const docNames = Search._index.docnames; - const objects = Search._index.objects; - const objNames = Search._index.objnames; - const titles = Search._index.titles; - - const results = []; - - const objectSearchCallback = (prefix, match) => { - const name = match[4] - const fullname = (prefix ? prefix + "." : "") + name; - const fullnameLower = fullname.toLowerCase(); - if (fullnameLower.indexOf(object) < 0) return; - - let score = 0; - const parts = fullnameLower.split("."); - - // check for different match types: exact matches of full name or - // "last name" (i.e. last dotted part) - if (fullnameLower === object || parts.slice(-1)[0] === object) - score += Scorer.objNameMatch; - else if (parts.slice(-1)[0].indexOf(object) > -1) - score += Scorer.objPartialMatch; // matches in last name - - const objName = objNames[match[1]][2]; - const title = titles[match[0]]; - - // If more than one term searched for, we require other words to be - // found in the name/title/description - const otherTerms = new Set(objectTerms); - otherTerms.delete(object); - if (otherTerms.size > 0) { - const haystack = `${prefix} ${name} ${objName} ${title}`.toLowerCase(); - if ( - [...otherTerms].some((otherTerm) => haystack.indexOf(otherTerm) < 0) - ) - return; - } - - let anchor = match[3]; - if (anchor === "") anchor = fullname; - else if (anchor === "-") anchor = objNames[match[1]][1] + "-" + fullname; - - const descr = objName + _(", in ") + title; - - // add custom score for some objects according to scorer - if (Scorer.objPrio.hasOwnProperty(match[2])) - score += Scorer.objPrio[match[2]]; - else score += Scorer.objPrioDefault; - - results.push([ - docNames[match[0]], - fullname, - "#" + anchor, - descr, - score, - filenames[match[0]], - SearchResultKind.object, - ]); - }; - Object.keys(objects).forEach((prefix) => - objects[prefix].forEach((array) => - objectSearchCallback(prefix, array) - ) - ); - return results; - }, - - /** - * search for full-text terms in the index - */ - performTermsSearch: (searchTerms, excludedTerms) => { - // prepare search - const terms = Search._index.terms; - const titleTerms = Search._index.titleterms; - const filenames = Search._index.filenames; - const docNames = Search._index.docnames; - const titles = Search._index.titles; - - const scoreMap = new Map(); - const fileMap = new Map(); - - // perform the search on the required terms - searchTerms.forEach((word) => { - const files = []; - // find documents, if any, containing the query word in their text/title term indices - // use Object.hasOwnProperty to avoid mismatching against prototype properties - const arr = [ - { files: terms.hasOwnProperty(word) ? terms[word] : undefined, score: Scorer.term }, - { files: titleTerms.hasOwnProperty(word) ? titleTerms[word] : undefined, score: Scorer.title }, - ]; - // add support for partial matches - if (word.length > 2) { - const escapedWord = _escapeRegExp(word); - if (!terms.hasOwnProperty(word)) { - Object.keys(terms).forEach((term) => { - if (term.match(escapedWord)) - arr.push({ files: terms[term], score: Scorer.partialTerm }); - }); - } - if (!titleTerms.hasOwnProperty(word)) { - Object.keys(titleTerms).forEach((term) => { - if (term.match(escapedWord)) - arr.push({ files: titleTerms[term], score: Scorer.partialTitle }); - }); - } - } - - // no match but word was a required one - if (arr.every((record) => record.files === undefined)) return; - - // found search word in contents - arr.forEach((record) => { - if (record.files === undefined) return; - - let recordFiles = record.files; - if (recordFiles.length === undefined) recordFiles = [recordFiles]; - files.push(...recordFiles); - - // set score for the word in each file - recordFiles.forEach((file) => { - if (!scoreMap.has(file)) scoreMap.set(file, new Map()); - const fileScores = scoreMap.get(file); - fileScores.set(word, record.score); - }); - }); - - // create the mapping - files.forEach((file) => { - if (!fileMap.has(file)) fileMap.set(file, [word]); - else if (fileMap.get(file).indexOf(word) === -1) fileMap.get(file).push(word); - }); - }); - - // now check if the files don't contain excluded terms - const results = []; - for (const [file, wordList] of fileMap) { - // check if all requirements are matched - - // as search terms with length < 3 are discarded - const filteredTermCount = [...searchTerms].filter( - (term) => term.length > 2 - ).length; - if ( - wordList.length !== searchTerms.size && - wordList.length !== filteredTermCount - ) - continue; - - // ensure that none of the excluded terms is in the search result - if ( - [...excludedTerms].some( - (term) => - terms[term] === file || - titleTerms[term] === file || - (terms[term] || []).includes(file) || - (titleTerms[term] || []).includes(file) - ) - ) - break; - - // select one (max) score for the file. - const score = Math.max(...wordList.map((w) => scoreMap.get(file).get(w))); - // add result to the result list - results.push([ - docNames[file], - titles[file], - "", - null, - score, - filenames[file], - SearchResultKind.text, - ]); - } - return results; - }, - - /** - * helper function to return a node containing the - * search summary for a given text. keywords is a list - * of stemmed words. - */ - makeSearchSummary: (htmlText, keywords, anchor) => { - const text = Search.htmlToText(htmlText, anchor); - if (text === "") return null; - - const textLower = text.toLowerCase(); - const actualStartPosition = [...keywords] - .map((k) => textLower.indexOf(k.toLowerCase())) - .filter((i) => i > -1) - .slice(-1)[0]; - const startWithContext = Math.max(actualStartPosition - 120, 0); - - const top = startWithContext === 0 ? "" : "..."; - const tail = startWithContext + 240 < text.length ? "..." : ""; - - let summary = document.createElement("p"); - summary.classList.add("context"); - summary.textContent = top + text.substr(startWithContext, 240).trim() + tail; - - return summary; - }, -}; - -_ready(Search.init); diff --git a/docs/build/html/_static/sphinx_highlight.js b/docs/build/html/_static/sphinx_highlight.js deleted file mode 100644 index 8a96c69..0000000 --- a/docs/build/html/_static/sphinx_highlight.js +++ /dev/null @@ -1,154 +0,0 @@ -/* Highlighting utilities for Sphinx HTML documentation. */ -"use strict"; - -const SPHINX_HIGHLIGHT_ENABLED = true - -/** - * highlight a given string on a node by wrapping it in - * span elements with the given class name. - */ -const _highlight = (node, addItems, text, className) => { - if (node.nodeType === Node.TEXT_NODE) { - const val = node.nodeValue; - const parent = node.parentNode; - const pos = val.toLowerCase().indexOf(text); - if ( - pos >= 0 && - !parent.classList.contains(className) && - !parent.classList.contains("nohighlight") - ) { - let span; - - const closestNode = parent.closest("body, svg, foreignObject"); - const isInSVG = closestNode && closestNode.matches("svg"); - if (isInSVG) { - span = document.createElementNS("http://www.w3.org/2000/svg", "tspan"); - } else { - span = document.createElement("span"); - span.classList.add(className); - } - - span.appendChild(document.createTextNode(val.substr(pos, text.length))); - const rest = document.createTextNode(val.substr(pos + text.length)); - parent.insertBefore( - span, - parent.insertBefore( - rest, - node.nextSibling - ) - ); - node.nodeValue = val.substr(0, pos); - /* There may be more occurrences of search term in this node. So call this - * function recursively on the remaining fragment. - */ - _highlight(rest, addItems, text, className); - - if (isInSVG) { - const rect = document.createElementNS( - "http://www.w3.org/2000/svg", - "rect" - ); - const bbox = parent.getBBox(); - rect.x.baseVal.value = bbox.x; - rect.y.baseVal.value = bbox.y; - rect.width.baseVal.value = bbox.width; - rect.height.baseVal.value = bbox.height; - rect.setAttribute("class", className); - addItems.push({ parent: parent, target: rect }); - } - } - } else if (node.matches && !node.matches("button, select, textarea")) { - node.childNodes.forEach((el) => _highlight(el, addItems, text, className)); - } -}; -const _highlightText = (thisNode, text, className) => { - let addItems = []; - _highlight(thisNode, addItems, text, className); - addItems.forEach((obj) => - obj.parent.insertAdjacentElement("beforebegin", obj.target) - ); -}; - -/** - * Small JavaScript module for the documentation. - */ -const SphinxHighlight = { - - /** - * highlight the search words provided in localstorage in the text - */ - highlightSearchWords: () => { - if (!SPHINX_HIGHLIGHT_ENABLED) return; // bail if no highlight - - // get and clear terms from localstorage - const url = new URL(window.location); - const highlight = - localStorage.getItem("sphinx_highlight_terms") - || url.searchParams.get("highlight") - || ""; - localStorage.removeItem("sphinx_highlight_terms") - url.searchParams.delete("highlight"); - window.history.replaceState({}, "", url); - - // get individual terms from highlight string - const terms = highlight.toLowerCase().split(/\s+/).filter(x => x); - if (terms.length === 0) return; // nothing to do - - // There should never be more than one element matching "div.body" - const divBody = document.querySelectorAll("div.body"); - const body = divBody.length ? divBody[0] : document.querySelector("body"); - window.setTimeout(() => { - terms.forEach((term) => _highlightText(body, term, "highlighted")); - }, 10); - - const searchBox = document.getElementById("searchbox"); - if (searchBox === null) return; - searchBox.appendChild( - document - .createRange() - .createContextualFragment( - '" - ) - ); - }, - - /** - * helper function to hide the search marks again - */ - hideSearchWords: () => { - document - .querySelectorAll("#searchbox .highlight-link") - .forEach((el) => el.remove()); - document - .querySelectorAll("span.highlighted") - .forEach((el) => el.classList.remove("highlighted")); - localStorage.removeItem("sphinx_highlight_terms") - }, - - initEscapeListener: () => { - // only install a listener if it is really needed - if (!DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS) return; - - document.addEventListener("keydown", (event) => { - // bail for input elements - if (BLACKLISTED_KEY_CONTROL_ELEMENTS.has(document.activeElement.tagName)) return; - // bail with special keys - if (event.shiftKey || event.altKey || event.ctrlKey || event.metaKey) return; - if (DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS && (event.key === "Escape")) { - SphinxHighlight.hideSearchWords(); - event.preventDefault(); - } - }); - }, -}; - -_ready(() => { - /* Do not call highlightSearchWords() when we are on the search page. - * It will highlight words from the *previous* search query. - */ - if (typeof Search === "undefined") SphinxHighlight.highlightSearchWords(); - SphinxHighlight.initEscapeListener(); -}); diff --git a/docs/build/html/_static/translations.js b/docs/build/html/_static/translations.js deleted file mode 100644 index 58fdf54..0000000 --- a/docs/build/html/_static/translations.js +++ /dev/null @@ -1,62 +0,0 @@ -Documentation.addTranslations({ - "locale": "ko", - "messages": { - "%(filename)s — %(docstitle)s": "%(filename)s — %(docstitle)s", - "© %(copyright_prefix)s %(copyright)s.": "", - ", in ": ", \ubb38\uc11c - ", - "About these documents": "\uc774 \ubb38\uc11c \uc815\ubcf4", - "Automatically generated list of changes in version %(version)s": "\ubc84\uc804 %(version)s\uc758 \ubcc0\uacbd \uc0ac\ud56d (\uc790\ub3d9\uc73c\ub85c \uc0dd\uc131\ub41c \ubaa9\ub85d)", - "C API changes": "C API \ubcc0\uacbd \uc0ac\ud56d", - "Changes in Version %(version)s — %(docstitle)s": "\ubc84\uc804 %(version)s\uc758 \ubcc0\uacbd \uc0ac\ud56d — %(docstitle)s", - "Collapse sidebar": "\uc0ac\uc774\ub4dc\ubc14 \ub2eb\uae30", - "Complete Table of Contents": "\uc885\ud569 \ubaa9\ucc28", - "Contents": "\ub0b4\uc6a9", - "Copyright": "\uc800\uc791\uad8c", - "Created using Sphinx %(sphinx_version)s.": "Sphinx %(sphinx_version)s \ubc84\uc804\uc73c\ub85c \uc0dd\uc131\ub418\uc5c8\uc2b5\ub2c8\ub2e4.", - "Expand sidebar": "\uc0ac\uc774\ub4dc\ubc14 \uc5f4\uae30", - "Full index on one page": "\ud55c \ud398\uc774\uc9c0\uc5d0 \uc804\uccb4 \uc0c9\uc778 \ubcf4\uae30", - "General Index": "\uc804\uccb4 \uc0c9\uc778", - "Global Module Index": "\ubaa8\ub4c8 \ucd1d \uc0c9\uc778", - "Go": "\uc774\ub3d9", - "Hide Search Matches": "\uac80\uc0c9 \uc77c\uce58 \uc228\uae30\uae30", - "Index": "\uc0c9\uc778", - "Index – %(key)s": "", - "Index pages by letter": "\uc54c\ud30c\ubcb3\ubcc4 \uc0c9\uc778", - "Indices and tables:": "\uc0c9\uc778 \ubc0f \ud45c \ubaa9\ub85d:", - "Last updated on %(last_updated)s.": "\ucd5c\uc885 \uc5c5\ub370\uc774\ud2b8: %(last_updated)s", - "Library changes": "\ub77c\uc774\ube0c\ub7ec\ub9ac \ubcc0\uacbd \uc0ac\ud56d", - "Navigation": "\ud0d0\uc0c9", - "Next topic": "\ub2e4\uc74c \ud56d\ubaa9", - "Other changes": "\ub2e4\ub978 \ubcc0\uacbd \uc0ac\ud56d", - "Overview": "\uac1c\uc694", - "Please activate JavaScript to enable the search\n functionality.": "\uac80\uc0c9 \uae30\ub2a5\uc744 \uc0ac\uc6a9\ud558\ub824\uba74 JavaScript\ub97c \ud65c\uc131\ud654\ud558\uc2ed\uc2dc\uc624.", - "Preparing search...": "\uac80\uc0c9 \uc900\ube44 \uc911\u2026", - "Previous topic": "\uc774\uc804 \ud56d\ubaa9", - "Quick search": "\ube60\ub978 \uac80\uc0c9", - "Search": "\uac80\uc0c9", - "Search Page": "\uac80\uc0c9 \ud398\uc774\uc9c0", - "Search Results": "\uac80\uc0c9 \uacb0\uacfc", - "Search finished, found one page matching the search query.": [ - "" - ], - "Search within %(docstitle)s": "%(docstitle)s\uc5d0\uc11c \ucc3e\uae30", - "Searching": "\uac80\uc0c9 \uc911", - "Searching for multiple words only shows matches that contain\n all words.": "\uc5ec\ub7ec \ub2e8\uc5b4\ub97c \uac80\uc0c9\ud558\uba74 \ubaa8\ub4e0 \ub2e8\uc5b4\uac00 \ud3ec\ud568\ub41c \uc77c\uce58 \ud56d\ubaa9\ub9cc \ud45c\uc2dc\ub429\ub2c8\ub2e4.", - "Show Source": "\uc18c\uc2a4 \ubcf4\uae30", - "Table of Contents": "\ubaa9\ucc28", - "This Page": "\ud604\uc7ac \ubb38\uc11c", - "Welcome! This is": "\ud658\uc601\ud569\ub2c8\ub2e4!", - "Your search did not match any documents. Please make sure that all words are spelled correctly and that you've selected enough categories.": "\uac80\uc0c9\uc5b4\uc640 \uc77c\uce58\ud558\ub294 \ubb38\uc11c\uac00 \uc5c6\uc2b5\ub2c8\ub2e4. \ubaa8\ub4e0 \ub2e8\uc5b4\uc758 \ucca0\uc790\uac00 \uc62c\ubc14\ub978\uc9c0, \ucda9\ubd84\ud55c \uce74\ud14c\uace0\ub9ac\ub97c \uc120\ud0dd\ud588\ub294\uc9c0 \ud655\uc778\ud558\uc2ed\uc2dc\uc624.", - "all functions, classes, terms": "\ud568\uc218, \ud074\ub798\uc2a4 \ubc0f \uc6a9\uc5b4 \uac1c\uad00", - "can be huge": "\ud070 \uacbd\uc6b0\uac00 \uc788\uc73c\ubbc0\ub85c \uc8fc\uc758", - "last updated": "\ucd5c\uc885 \uc5c5\ub370\uc774\ud2b8", - "lists all sections and subsections": "\ubaa8\ub4e0 \uad6c\uc5ed\uacfc \ud558\uc704 \uad6c\uc5ed \ubaa9\ub85d", - "next chapter": "\ub2e4\uc74c \uc7a5", - "previous chapter": "\uc774\uc804 \uc7a5", - "quick access to all modules": "\ubaa8\ub4e0 \ubaa8\ub4c8 \uc870\uacac\ud45c", - "search": "\uac80\uc0c9", - "search this documentation": "\ubb38\uc11c \uac80\uc0c9", - "the documentation for": "\ubb38\uc11c:" - }, - "plural_expr": "0" -}); \ No newline at end of file diff --git a/docs/build/html/advanced_usage.html b/docs/build/html/advanced_usage.html deleted file mode 100644 index ab40641..0000000 --- a/docs/build/html/advanced_usage.html +++ /dev/null @@ -1,454 +0,0 @@ - - - - - - - - - 고급 사용법 — Atio 2.0.0 문서 - - - - - - - - - - - - - - - - - - -
- - -
- -
-
-
- -
-
-
-
- -
-

고급 사용법

-

이 섹션에서는 Atio의 고급 기능들을 다룹니다.

-
-

스냅샷 기반 버전 관리

-

Atio는 데이터의 버전을 관리할 수 있는 스냅샷 시스템을 제공합니다.

-
-

기본 스냅샷 쓰기

-
import atio
-import pandas as pd
-
-# 데이터 생성
-df = pd.DataFrame({
-    "id": [1, 2, 3],
-    "name": ["Alice", "Bob", "Charlie"]
-})
-
-# 스냅샷으로 저장 (버전 관리)
-atio.write_snapshot(df, "users_table", format="parquet")
-
-# 새로운 데이터로 업데이트
-df_new = pd.DataFrame({
-    "id": [1, 2, 3, 4],
-    "name": ["Alice", "Bob", "Charlie", "David"]
-})
-
-# append 모드로 스냅샷 추가
-atio.write_snapshot(df_new, "users_table", mode="append", format="parquet")
-
-
-
-
-

스냅샷 읽기

-
# 최신 버전 읽기
-latest_data = atio.read_table("users_table")
-
-# 특정 버전 읽기
-version_1_data = atio.read_table("users_table", version=1)
-
-# Polars로 읽기
-polars_data = atio.read_table("users_table", output_as="polars")
-
-
-
-
-

스냅샷 정리

-
from datetime import timedelta
-
-# 7일 이상 된 스냅샷 삭제 (dry run)
-atio.expire_snapshots("users_table", keep_for=timedelta(days=7), dry_run=True)
-
-# 실제 삭제 실행
-atio.expire_snapshots("users_table", keep_for=timedelta(days=7), dry_run=False)
-
-
-
-
-
-

데이터베이스 연동

-

Pandas와 Polars를 사용하여 데이터베이스에 안전하게 데이터를 저장할 수 있습니다.

-
-

Pandas SQL 연동

-
import atio
-import pandas as pd
-from sqlalchemy import create_engine
-
-# 데이터베이스 연결
-engine = create_engine('postgresql://user:password@localhost/dbname')
-
-df = pd.DataFrame({
-    "id": [1, 2, 3],
-    "name": ["Alice", "Bob", "Charlie"]
-})
-
-# SQL 데이터베이스에 저장
-atio.write(df, format="sql", name="users", con=engine)
-
-
-
-
-

Polars 데이터베이스 연동

-
import atio
-import polars as pl
-
-df = pl.DataFrame({
-    "id": [1, 2, 3],
-    "name": ["Alice", "Bob", "Charlie"]
-})
-
-# 데이터베이스에 저장
-atio.write(df, format="database",
-           table_name="users",
-           connection_uri="postgresql://user:password@localhost/dbname")
-
-
-
-
-
-

성능 최적화

-
-

진행도 표시

-

대용량 파일 처리 시 진행 상황을 실시간으로 확인할 수 있습니다.

-
import atio
-import pandas as pd
-import numpy as np
-
-# 대용량 데이터 생성
-large_df = pd.DataFrame(np.random.randn(1000000, 10))
-
-# 진행도 표시와 함께 저장
-atio.write(large_df, "large_data.parquet",
-           format="parquet",
-           show_progress=True)
-
-
-
-
-

상세 로깅

-

성능 진단을 위한 상세한 로깅을 활성화할 수 있습니다.

-
# 상세한 성능 정보 출력
-atio.write(df, "data.parquet", format="parquet", verbose=True)
-
-
-

이를 통해 다음과 같은 정보를 확인할 수 있습니다:

-
    -
  • 각 단계별 소요 시간

  • -
  • 임시 파일 생성 및 교체 과정

  • -
  • 백업 및 롤백 과정

  • -
  • 성능 병목점 분석

  • -
-
-
-
-

에러 처리

-

Atio는 다양한 에러 상황에 대해 안전하게 처리합니다.

-
-

파일 시스템 에러

-
import atio
-import pandas as pd
-
-df = pd.DataFrame({"a": [1, 2, 3]})
-
-try:
-    # 권한이 없는 디렉토리에 저장 시도
-    atio.write(df, "/root/data.parquet", format="parquet")
-except PermissionError as e:
-    print(f"권한 에러: {e}")
-    # 원본 파일은 그대로 보존됨
-
-
-
-
-

포맷 에러

-
try:
-    # 지원하지 않는 포맷 사용
-    atio.write(df, "data.unknown", format="unknown")
-except ValueError as e:
-    print(f"지원하지 않는 포맷: {e}")
-
-
-
-
-

데이터베이스 에러

-
try:
-    # 잘못된 데이터베이스 연결 정보
-    atio.write(df, format="sql",
-               name="users",
-               con="invalid_connection")
-except Exception as e:
-    print(f"데이터베이스 에러: {e}")
-
-
-
-
-
-

플러그인 확장

-

Atio는 플러그인 아키텍처를 통해 새로운 형식을 쉽게 추가할 수 있습니다.

-
-

커스텀 형식 등록

-
from atio.plugins import register_writer
-import pandas as pd
-
-# 커스텀 형식 등록
-def custom_writer(df, path, **kwargs):
-    # 커스텀 저장 로직
-    with open(path, 'w') as f:
-        f.write("Custom format\n")
-        f.write(df.to_string())
-
-# Pandas DataFrame에 대한 커스텀 형식 등록
-register_writer(pd.DataFrame, "custom", custom_writer)
-
-# 사용
-df = pd.DataFrame({"a": [1, 2, 3]})
-atio.write(df, "data.custom", format="custom")
-
-
-
-
-
-

NumPy 배열 처리

-

NumPy 배열의 다양한 저장 방식을 지원합니다.

-
-

단일 배열 저장

-
import atio
-import numpy as np
-
-arr = np.array([[1, 2, 3], [4, 5, 6]])
-
-# .npy 파일로 저장
-atio.write(arr, "array.npy", format="npy")
-
-# .csv 파일로 저장
-atio.write(arr, "array.csv", format="csv")
-
-
-
-
-

여러 배열 저장

-
# 여러 배열을 딕셔너리로 저장
-arrays = {
-    "features": np.random.randn(1000, 10),
-    "labels": np.random.randint(0, 2, 1000),
-    "metadata": np.array([1, 2, 3, 4, 5])
-}
-
-# 압축된 .npz 파일로 저장
-atio.write(arrays, "data.npz", format="npz_compressed")
-
-
-
-
-
-

실제 사용 사례

-
-

머신러닝 파이프라인

-
import atio
-import pandas as pd
-from sklearn.model_selection import train_test_split
-from sklearn.ensemble import RandomForestClassifier
-
-# 데이터 로드 및 전처리
-df = pd.read_csv("raw_data.csv")
-
-# 전처리된 데이터를 안전하게 저장
-atio.write(df, "processed_data.parquet", format="parquet")
-
-# 학습/테스트 분할
-X_train, X_test, y_train, y_test = train_test_split(
-    df.drop('target', axis=1), df['target'], test_size=0.2
-)
-
-# 분할된 데이터를 스냅샷으로 저장
-atio.write_snapshot(X_train, "training_data", format="parquet")
-atio.write_snapshot(X_test, "test_data", format="parquet")
-
-# 모델 학습
-model = RandomForestClassifier()
-model.fit(X_train, y_train)
-
-# 예측 결과를 안전하게 저장
-predictions = model.predict(X_test)
-results_df = pd.DataFrame({
-    'actual': y_test,
-    'predicted': predictions
-})
-
-atio.write(results_df, "predictions.parquet", format="parquet")
-
-
-
-
-

ETL 파이프라인

-
import atio
-import pandas as pd
-from sqlalchemy import create_engine
-
-# 1. 원본 데이터 로드
-raw_data = pd.read_csv("source_data.csv")
-
-# 2. 데이터 정제
-cleaned_data = raw_data.dropna()
-cleaned_data = cleaned_data[cleaned_data['value'] > 0]
-
-# 3. 안전하게 정제된 데이터 저장
-atio.write(cleaned_data, "cleaned_data.parquet", format="parquet")
-
-# 4. 데이터베이스에 저장
-engine = create_engine('postgresql://user:password@localhost/warehouse')
-atio.write(cleaned_data, format="sql",
-           name="processed_table",
-           con=engine,
-           if_exists='replace')
-
-# 5. 스냅샷으로 버전 관리
-atio.write_snapshot(cleaned_data, "daily_processed", format="parquet")
-
-
-
-
-
- - -
-
- -
-
-
-
- - - - \ No newline at end of file diff --git a/docs/build/html/api.html b/docs/build/html/api.html deleted file mode 100644 index b4782d6..0000000 --- a/docs/build/html/api.html +++ /dev/null @@ -1,489 +0,0 @@ - - - - - - - - - API 참조 — Atio 2.0.0 문서 - - - - - - - - - - - - - - - - - - -
- - -
- -
-
-
- -
-
-
-
- -
-

API 참조

-

Atio의 모든 함수와 클래스에 대한 상세한 API 문서입니다.

-
-

주요 함수

-

Atio: 안전한 원자적 파일 쓰기 라이브러리

-
-
-

Core 모듈

-

progress 적용 후 write 함수

-
-
-atio.core.write(obj, target_path=None, format=None, show_progress=False, verbose=False, **kwargs)[소스]
-

데이터 객체(obj)를 안전하게 target_path 또는 데이터베이스에 저장합니다.

-
    -
  • 파일 기반 쓰기 (format: ‘csv’, ‘parquet’, ‘excel’ 등): -- target_path (str): 필수. 데이터가 저장될 파일 경로입니다. -- 롤백 기능이 있는 원자적 쓰기를 수행합니다.

  • -
  • 데이터베이스 기반 쓰기 (format: ‘sql’, ‘database’): -- target_path: 사용되지 않습니다. -- kwargs (dict): 데이터베이스 쓰기에 필요한 추가 인자들입니다.

    -
    -
      -
    • pandas.to_sql: ‘name’(테이블명), ‘con’(커넥션 객체)가 필수입니다.

    • -
    • polars.write_database: ‘table_name’, ‘connection_uri’가 필수입니다.

    • -
    -
    -
  • -
-
-
매개변수:
-
    -
  • obj – 저장할 데이터 객체 (e.g., pandas.DataFrame, polars.DataFrame, np.ndarray).

  • -
  • target_path (str, optional) – 파일 저장 경로. 파일 기반 쓰기 시 필수. Defaults to None.

  • -
  • format (str, optional) – 저장할 포맷. Defaults to None.

  • -
  • show_progress (bool) – 진행도 표시 여부. Defaults to False.

  • -
  • verbose (bool) – 상세한 성능 진단 정보 출력 여부. Defaults to False.

  • -
  • **kwargs – 각 쓰기 함수에 전달될 추가 키워드 인자.

  • -
-
-
-
- -
-
-atio.core.write_snapshot(obj, table_path, mode='overwrite', format='parquet', **kwargs)[소스]
-
- -
-
-atio.core.read_table(table_path, version=None, output_as='pandas')[소스]
-
- -
-
-atio.core.expire_snapshots(table_path, keep_for=datetime.timedelta(days=7), dry_run=True)[소스]
-

설정된 보관 기간(keep_for)보다 오래된 스냅샷과 -더 이상 참조되지 않는 데이터 파일을 삭제합니다.

-
- -
-
-

write()

-

안전한 원자적 파일 쓰기를 수행하는 메인 함수입니다.

-
-
-atio.write(obj, target_path=None, format='parquet', **kwargs)
-
-
매개변수:
-
    -
  • obj – 저장할 데이터 객체 (pandas.DataFrame, polars.DataFrame, numpy.ndarray)

  • -
  • target_path – 저장할 파일 경로 (파일 저장 시 필수)

  • -
  • format – 저장 형식 (‘csv’, ‘parquet’, ‘excel’, ‘json’, ‘sql’, ‘database’)

  • -
  • show_progress – 진행률 표시 여부 (기본값: False)

  • -
  • verbose – 상세 성능 정보 출력 여부 (기본값: False)

  • -
  • **kwargs

    형식별 추가 매개변수

    -

  • -
-
-
반환:
-

None

-
-
Raises:
-

ValueError, IOError, DatabaseError

-
-
-

사용 예제:

-
import atio
-import pandas as pd
-
-df = pd.DataFrame({"a": [1, 2, 3]})
-
-# 기본 사용법
-atio.write(df, "data.parquet", format="parquet")
-
-# 진행률 표시
-atio.write(df, "data.parquet", format="parquet", show_progress=True)
-
-# 성능 정보 출력
-atio.write(df, "data.parquet", format="parquet", verbose=True)
-
-
-
- -
-
-

write_snapshot()

-

데이터 스냅샷을 생성하여 버전 관리를 수행합니다.

-
-
-atio.write_snapshot(obj, table_name, format='parquet', **kwargs)
-
-
매개변수:
-
    -
  • obj – 저장할 데이터 객체

  • -
  • table_name – 테이블 이름 (스냅샷 디렉토리명)

  • -
  • format – 저장 형식

  • -
  • **kwargs

    추가 매개변수

    -

  • -
-
-
반환:
-

생성된 스냅샷 ID

-
-
-

사용 예제:

-
# 스냅샷 생성
-snapshot_id = atio.write_snapshot(df, "users", format="parquet")
-print(f"생성된 스냅샷 ID: {snapshot_id}")
-
-
-
- -
-
-

read_table()

-

스냅샷에서 데이터를 읽어옵니다.

-
-
-atio.read_table(table_name, snapshot_id='latest', format='parquet', **kwargs)
-
-
매개변수:
-
    -
  • table_name – 테이블 이름

  • -
  • snapshot_id – 스냅샷 ID (기본값: ‘latest’)

  • -
  • format – 읽을 형식

  • -
  • **kwargs

    추가 매개변수

    -

  • -
-
-
반환:
-

데이터 객체

-
-
-

사용 예제:

-
# 최신 스냅샷 읽기
-df = atio.read_table("users", format="parquet")
-
-# 특정 스냅샷 읽기
-df = atio.read_table("users", snapshot_id="20240101_120000", format="parquet")
-
-
-
- -
-
-

expire_snapshots()

-

오래된 스냅샷을 정리합니다.

-
-
-atio.expire_snapshots(table_name, days=30, format='parquet')
-
-
매개변수:
-
    -
  • table_name – 테이블 이름

  • -
  • days – 보관할 일수 (기본값: 30)

  • -
  • format – 형식

  • -
-
-
반환:
-

삭제된 스냅샷 수

-
-
-

사용 예제:

-
# 30일 이상 된 스냅샷 정리
-deleted_count = atio.expire_snapshots("users", days=30)
-print(f"삭제된 스냅샷 수: {deleted_count}")
-
-
-
- -
-
-

Plugins 모듈

-
-
-atio.plugins.register_writer(obj_type, fmt, handler)[소스]
-

(객체 타입, 포맷) 쌍으로 쓰기 핸들러를 등록

-
- -
-
-atio.plugins.get_writer(obj, fmt)[소스]
-

객체의 타입과 포맷에 맞는 핸들러를 조회

-
- -
-
-

Utils 모듈

-
-
-atio.utils.setup_logger(name='atio', debug_level=False)[소스]
-
- -
-
-atio.utils.check_file_exists(path)[소스]
-
- -
-
-class atio.utils.ProgressBar(filepath: str, stop_event: Event, description: str = 'Writing')[소스]
-

기반 클래스: object

-

파일 쓰기 진행 상황을 콘솔에 표시하는 클래스. -스피너, 처리된 용량, 처리 속도, 경과 시간을 표시합니다.

-
-
-__init__(filepath: str, stop_event: Event, description: str = 'Writing')[소스]
-
- -
-
-run()[소스]
-

진행도 막대를 실행하는 메인 루프. -이 함수가 모니터링 스레드에서 실행됩니다.

-
- -
- -
-
-atio.utils.read_json(path: str)[소스]
-
- -
-
-atio.utils.write_json(data: dict, path: str)[소스]
-
- -
-
-

지원하는 형식

-
-

CSV 형식

-
atio.write(df, "data.csv", format="csv", index=False, encoding='utf-8')
-
-
-

지원 매개변수: -- index: 인덱스 포함 여부 -- encoding: 인코딩 방식 -- sep: 구분자 -- na_rep: NA 값 표현

-
-
-

Parquet 형식

-
atio.write(df, "data.parquet", format="parquet", compression='snappy')
-
-
-

지원 매개변수: -- compression: 압축 방식 (‘snappy’, ‘gzip’, ‘brotli’) -- engine: 엔진 (‘pyarrow’, ‘fastparquet’)

-
-
-

Excel 형식

-
atio.write(df, "data.xlsx", format="excel", sheet_name="Sheet1")
-
-
-

지원 매개변수: -- sheet_name: 시트 이름 -- engine: 엔진 (‘openpyxl’, ‘xlsxwriter’)

-
-
-

JSON 형식

-
atio.write(df, "data.json", format="json", orient="records")
-
-
-

지원 매개변수: -- orient: 방향 (‘records’, ‘split’, ‘index’, ‘columns’, ‘values’, ‘table’)

-
-
-

SQL 형식

-
atio.write(df, format="sql", name="table_name", con=engine, if_exists="replace")
-
-
-

지원 매개변수: -- name: 테이블 이름 -- con: 데이터베이스 연결 -- if_exists: 테이블 존재 시 동작 (‘fail’, ‘replace’, ‘append’)

-
-
-
-

예외 처리

-

Atio는 다음과 같은 예외를 발생시킬 수 있습니다:

-
    -
  • ValueError: 잘못된 매개변수나 형식

  • -
  • IOError: 파일 시스템 오류

  • -
  • DatabaseError: 데이터베이스 연결 오류

  • -
  • ImportError: 필요한 패키지가 설치되지 않은 경우

  • -
-

예외 처리 예제:

-
try:
-    atio.write(df, "data.parquet", format="parquet")
-except ValueError as e:
-    print(f"매개변수 오류: {e}")
-except IOError as e:
-    print(f"파일 시스템 오류: {e}")
-except Exception as e:
-    print(f"예상치 못한 오류: {e}")
-
-
-
-
- - -
-
- -
-
-
-
- - - - \ No newline at end of file diff --git a/docs/build/html/configuration.html b/docs/build/html/configuration.html deleted file mode 100644 index 6cb5489..0000000 --- a/docs/build/html/configuration.html +++ /dev/null @@ -1,629 +0,0 @@ - - - - - - - - - 설정 및 구성 — Atio 2.0.0 문서 - - - - - - - - - - - - - - - - - -
- - -
- -
-
-
- -
-
-
-
- -
-

설정 및 구성

-

Atio의 다양한 설정 옵션과 구성 방법을 설명합니다.

-
-

로깅 설정

-

Atio는 상세한 로깅을 통해 작업 과정을 추적할 수 있습니다.

-
-

기본 로깅

-
import atio
-import pandas as pd
-
-df = pd.DataFrame({"a": [1, 2, 3]})
-
-# 기본 로깅 (INFO 레벨)
-atio.write(df, "data.parquet", format="parquet")
-
-
-

출력 예시: -` -[INFO] 임시 디렉토리 생성: /tmp/tmp12345 -[INFO] 임시 파일 경로: /tmp/tmp12345/data.parquet -[INFO] 사용할 writer: to_parquet (format: parquet) -[INFO] 데이터 임시 파일에 저장 완료: /tmp/tmp12345/data.parquet -[INFO] 원자적 교체 완료: /tmp/tmp12345/data.parquet -> data.parquet -[INFO] _SUCCESS 플래그 파일 생성: .data.parquet._SUCCESS -[INFO] Atomic write completed successfully (took 0.1234s) -`

-
-
-

상세 로깅

-
# 상세한 성능 정보 출력 (DEBUG 레벨)
-atio.write(df, "data.parquet", format="parquet", verbose=True)
-
-
-

출력 예시: -` -[INFO] 임시 디렉토리 생성: /tmp/tmp12345 -[INFO] 임시 파일 경로: /tmp/tmp12345/data.parquet -[INFO] 사용할 writer: to_parquet (format: parquet) -[INFO] 데이터 임시 파일에 저장 완료: /tmp/tmp12345/data.parquet -[INFO] 원자적 교체 완료: /tmp/tmp12345/data.parquet -> data.parquet -[INFO] _SUCCESS 플래그 파일 생성: .data.parquet._SUCCESS -[DEBUG] Atomic write step timings (SUCCESS): setup=0.0012s, write_call=0.0987s, replace=0.0001s, success_flag=0.0001s, total=0.1001s -[INFO] Atomic write completed successfully (took 0.1001s) -`

-
-
-
-

진행도 표시

-

대용량 파일 처리 시 진행 상황을 실시간으로 확인할 수 있습니다.

-
-

기본 진행도 표시

-
import atio
-import pandas as pd
-import numpy as np
-
-# 대용량 데이터 생성
-large_df = pd.DataFrame(np.random.randn(1000000, 10))
-
-# 진행도 표시와 함께 저장
-atio.write(large_df, "large_data.parquet",
-           format="parquet",
-           show_progress=True)
-
-
-

출력 예시: -` - Writing large_data.parquet... [ 45.2 MB | 12.3 MB/s | 00:03 ] - Writing large_data.parquet... [ 67.8 MB | 11.9 MB/s | 00:05 ] - Writing large_data.parquet... [ 89.1 MB | 12.1 MB/s | 00:07 ] - Writing completed successfully (89.1 MB in 7s) -`

-
-
-

진행도 표시 옵션

-

진행도 표시는 다음과 같은 정보를 제공합니다:

-
    -
  • 스피너: 작업 진행 상태를 시각적으로 표시

  • -
  • 파일 크기: 현재까지 저장된 데이터 크기

  • -
  • 처리 속도: 초당 처리되는 데이터 양

  • -
  • 경과 시간: 작업 시작 후 경과한 시간

  • -
-
-
-
-

성능 최적화 설정

-
-

메모리 사용량 최적화

-
# 대용량 데이터 처리 시 메모리 효율적인 설정
-atio.write(large_df, "data.parquet", format="parquet",
-           compression='snappy',  # 빠른 압축
-           index=False)          # 인덱스 제외로 메모리 절약
-
-
-
-
-

압축 설정

-
# 속도 우선 (압축 없음)
-atio.write(df, "data.parquet", format="parquet", compression=None)
-
-# 균형 (snappy 압축)
-atio.write(df, "data.parquet", format="parquet", compression='snappy')
-
-# 용량 우선 (gzip 압축)
-atio.write(df, "data.parquet", format="parquet", compression='gzip')
-
-
-
-
-
-

임시 디렉토리 설정

-

기본적으로 Atio는 시스템의 임시 디렉토리를 사용합니다.

-
-

사용자 정의 임시 디렉토리

-
import os
-import tempfile
-
-# 임시 디렉토리 설정
-tempfile.tempdir = "/path/to/custom/temp"
-
-# 또는 환경 변수 설정
-os.environ['TMPDIR'] = "/path/to/custom/temp"
-
-
-

주의사항: -- 임시 디렉토리는 충분한 디스크 공간이 있어야 합니다 -- 쓰기 권한이 있어야 합니다 -- 빠른 I/O 성능을 위해 SSD를 권장합니다

-
-
-
-

에러 처리 설정

-

Atio는 다양한 에러 상황에 대해 안전하게 처리합니다.

-
-

롤백 동작

-
# 기본적으로 롤백이 자동으로 수행됩니다
-try:
-    atio.write(df, "data.parquet", format="parquet")
-except Exception as e:
-    # 에러 발생 시 원본 파일은 보존됩니다
-    print(f"저장 실패: {e}")
-    # 임시 파일은 자동으로 정리됩니다
-
-
-
-
-

백업 파일 관리

-
# 백업 파일은 작업 성공 시 자동으로 삭제됩니다
-# 실패 시에는 롤백 후 삭제됩니다
-
-# 백업 파일이 남아있는 경우 수동으로 확인
-import os
-backup_file = "data.parquet._backup"
-if os.path.exists(backup_file):
-    print("백업 파일이 존재합니다. 수동 확인이 필요할 수 있습니다.")
-
-
-
-
-
-

완료 플래그 시스템

-

Atio는 작업 완료를 확인할 수 있는 플래그 파일을 생성합니다.

-
-

플래그 파일 확인

-
import os
-
-# 저장 완료 후 플래그 파일 확인
-atio.write(df, "data.parquet", format="parquet")
-
-# 플래그 파일 경로
-flag_file = ".data.parquet._SUCCESS"
-
-if os.path.exists(flag_file):
-    print("저장이 성공적으로 완료되었습니다.")
-else:
-    print("저장이 완료되지 않았거나 실패했습니다.")
-
-
-
-
-

플래그 파일 활용

-
# 배치 처리에서 완료 여부 확인
-files_to_process = ["data1.parquet", "data2.parquet", "data3.parquet"]
-
-for file in files_to_process:
-    flag_file = f".{file}._SUCCESS"
-    if not os.path.exists(flag_file):
-        print(f"{file} 처리가 완료되지 않았습니다.")
-        # 재처리 로직
-
-
-
-
-
-

스냅샷 설정

-

스냅샷 시스템의 다양한 설정 옵션을 설명합니다.

-
-

스냅샷 모드

-
# overwrite 모드 (기본값)
-atio.write_snapshot(df, "table_path", mode="overwrite", format="parquet")
-
-# append 모드 (기존 데이터에 추가)
-atio.write_snapshot(df, "table_path", mode="append", format="parquet")
-
-
-
-
-

스냅샷 정리 설정

-
from datetime import timedelta
-
-# 7일 이상 된 스냅샷 삭제
-atio.expire_snapshots("table_path",
-                     keep_for=timedelta(days=7),
-                     dry_run=True)  # 실제 삭제 전 확인
-
-# 30일 이상 된 스냅샷 삭제
-atio.expire_snapshots("table_path",
-                     keep_for=timedelta(days=30),
-                     dry_run=False)  # 실제 삭제
-
-
-
-
-
-

환경 변수 설정

-

Atio의 동작을 제어하는 환경 변수들을 설정할 수 있습니다.

-
-

로깅 레벨 설정

-
import os
-
-# DEBUG 레벨로 로깅 설정
-os.environ['ATIO_LOG_LEVEL'] = 'DEBUG'
-
-# INFO 레벨로 로깅 설정 (기본값)
-os.environ['ATIO_LOG_LEVEL'] = 'INFO'
-
-
-
-
-

임시 디렉토리 설정

-
# 임시 디렉토리 경로 설정
-os.environ['ATIO_TEMP_DIR'] = '/path/to/temp'
-
-# 또는 시스템 임시 디렉토리 설정
-os.environ['TMPDIR'] = '/path/to/temp'
-
-
-
-
-

성능 모니터링 설정

-
# 성능 모니터링 활성화
-os.environ['ATIO_PERFORMANCE_MONITORING'] = 'true'
-
-# 성능 모니터링 비활성화
-os.environ['ATIO_PERFORMANCE_MONITORING'] = 'false'
-
-
-
-
-
-

플러그인 설정

-

커스텀 플러그인을 등록하여 새로운 형식을 지원할 수 있습니다.

-
-

플러그인 등록

-
from atio.plugins import register_writer
-import pandas as pd
-
-# 커스텀 형식 등록
-def custom_writer(df, path, **kwargs):
-    # 커스텀 저장 로직
-    with open(path, 'w') as f:
-        f.write("Custom format\n")
-        f.write(df.to_string())
-
-# 등록
-register_writer(pd.DataFrame, "custom", custom_writer)
-
-
-
-
-

플러그인 확인

-
from atio.plugins import WRITER_MAPPING
-
-# 등록된 플러그인 확인
-for obj_type, formats in WRITER_MAPPING.items():
-    print(f"Object type: {obj_type.__name__}")
-    for fmt, handler in formats.items():
-        print(f"  - {fmt}: {handler}")
-
-
-
-
-
-

설정 파일 사용

-

설정을 파일로 관리하여 일관된 설정을 유지할 수 있습니다.

-
-

JSON 설정 파일

-
import json
-
-# 설정 파일 생성
-config = {
-    "default_format": "parquet",
-    "compression": "snappy",
-    "show_progress": True,
-    "verbose": False,
-    "temp_dir": "/path/to/temp"
-}
-
-with open("atio_config.json", "w") as f:
-    json.dump(config, f, indent=2)
-
-# 설정 파일 읽기
-with open("atio_config.json", "r") as f:
-    config = json.load(f)
-
-# 설정 적용
-atio.write(df, "data.parquet",
-           format=config.get("default_format", "parquet"),
-           compression=config.get("compression", "snappy"),
-           show_progress=config.get("show_progress", False),
-           verbose=config.get("verbose", False))
-
-
-
-
-

YAML 설정 파일

-
import yaml
-
-# 설정 파일 생성
-config = {
-    "default_format": "parquet",
-    "compression": "snappy",
-    "show_progress": True,
-    "verbose": False,
-    "temp_dir": "/path/to/temp"
-}
-
-with open("atio_config.yaml", "w") as f:
-    yaml.dump(config, f)
-
-# 설정 파일 읽기
-with open("atio_config.yaml", "r") as f:
-    config = yaml.safe_load(f)
-
-
-
-
-
-

모범 사례

-
-

프로덕션 환경 설정

-
# 프로덕션 환경을 위한 설정
-import os
-import tempfile
-
-# 1. 전용 임시 디렉토리 설정
-tempfile.tempdir = "/var/tmp/atio"
-os.makedirs(tempfile.tempdir, exist_ok=True)
-
-# 2. 로깅 레벨 설정
-os.environ['ATIO_LOG_LEVEL'] = 'INFO'
-
-# 3. 성능 최적화 설정
-def safe_write(df, path, **kwargs):
-    return atio.write(df, path,
-                     format="parquet",
-                     compression="snappy",
-                     show_progress=True,
-                     verbose=False,
-                     **kwargs)
-
-
-
-
-

개발 환경 설정

-
# 개발 환경을 위한 설정
-import os
-
-# 1. 상세 로깅 활성화
-os.environ['ATIO_LOG_LEVEL'] = 'DEBUG'
-
-# 2. 성능 모니터링 활성화
-os.environ['ATIO_PERFORMANCE_MONITORING'] = 'true'
-
-# 3. 개발용 설정
-def dev_write(df, path, **kwargs):
-    return atio.write(df, path,
-                     format="parquet",
-                     compression=None,  # 압축 없음으로 빠른 처리
-                     show_progress=True,
-                     verbose=True,  # 상세 정보 출력
-                     **kwargs)
-
-
-
-
-
-

설정 검증

-

설정이 올바르게 적용되었는지 확인하는 방법을 설명합니다.

-
-

기본 검증

-
import atio
-import pandas as pd
-import tempfile
-
-# 테스트 데이터 생성
-df = pd.DataFrame({"test": [1, 2, 3]})
-
-# 설정 테스트
-def test_config():
-    # 임시 디렉토리 확인
-    print(f"임시 디렉토리: {tempfile.gettempdir()}")
-
-    # 로깅 테스트
-    atio.write(df, "test.parquet", format="parquet", verbose=True)
-
-    # 플래그 파일 확인
-    import os
-    if os.path.exists(".test.parquet._SUCCESS"):
-        print("설정이 올바르게 작동합니다.")
-    else:
-        print("설정에 문제가 있을 수 있습니다.")
-
-
-
-
-

성능 테스트

-
import time
-import pandas as pd
-import numpy as np
-
-# 성능 테스트
-def performance_test():
-    # 대용량 데이터 생성
-    large_df = pd.DataFrame(np.random.randn(100000, 10))
-
-    # 성능 측정
-    start_time = time.time()
-    atio.write(large_df, "performance_test.parquet",
-               format="parquet",
-               show_progress=True)
-    end_time = time.time()
-
-    print(f"처리 시간: {end_time - start_time:.2f}초")
-
-    # 파일 크기 확인
-    import os
-    file_size = os.path.getsize("performance_test.parquet")
-    print(f"파일 크기: {file_size / 1024 / 1024:.2f} MB")
-
-
-
-
-
- - -
-
- -
-
-
-
- - - - \ No newline at end of file diff --git a/docs/build/html/examples.html b/docs/build/html/examples.html deleted file mode 100644 index 75ea738..0000000 --- a/docs/build/html/examples.html +++ /dev/null @@ -1,539 +0,0 @@ - - - - - - - - - 사용 예제 — Atio 2.0.0 문서 - - - - - - - - - - - - - - - - - - -
- - -
- -
-
-
- -
-
-
-
- -
-

사용 예제

-

Atio의 다양한 사용 사례와 고급 기능을 살펴보세요.

-
-

기본 예제

-
-

간단한 데이터 저장

-
import atio
-import pandas as pd
-
-# 샘플 데이터 생성
-data = {
-    "id": [1, 2, 3, 4, 5],
-    "name": ["Alice", "Bob", "Charlie", "Diana", "Eve"],
-    "age": [25, 30, 35, 28, 32],
-    "city": ["Seoul", "Busan", "Incheon", "Daegu", "Daejeon"],
-    "salary": [50000, 60000, 70000, 55000, 65000]
-}
-
-df = pd.DataFrame(data)
-
-# 다양한 형식으로 저장
-atio.write(df, "employees.parquet", format="parquet")
-atio.write(df, "employees.csv", format="csv", index=False)
-atio.write(df, "employees.xlsx", format="excel", sheet_name="Employees")
-
-
-
-
-
-

대용량 데이터 처리

-
-

진행률 표시와 성능 모니터링

-
import numpy as np
-import pandas as pd
-import atio
-
-# 대용량 데이터 생성 (100만 행)
-large_data = {
-    "id": range(1, 1000001),
-    "value": np.random.randn(1000000),
-    "category": np.random.choice(["A", "B", "C"], 1000000),
-    "timestamp": pd.date_range("2024-01-01", periods=1000000, freq="S")
-}
-
-large_df = pd.DataFrame(large_data)
-
-# 진행률 표시와 성능 모니터링 활성화
-atio.write(
-    large_df,
-    "large_dataset.parquet",
-    format="parquet",
-    show_progress=True,
-    verbose=True,
-    compression='snappy'
-)
-
-
-
-
-
-

데이터베이스 연동

-
-

PostgreSQL 데이터베이스 저장

-
import atio
-import pandas as pd
-from sqlalchemy import create_engine
-
-# 데이터베이스 연결
-engine = create_engine('postgresql://username:password@localhost:5432/mydb')
-
-# 샘플 데이터
-sales_data = {
-    "order_id": [1001, 1002, 1003, 1004, 1005],
-    "product_name": ["Laptop", "Mouse", "Keyboard", "Monitor", "Headphones"],
-    "quantity": [1, 2, 1, 1, 3],
-    "price": [1200, 25, 75, 300, 150],
-    "order_date": pd.date_range("2024-01-01", periods=5)
-}
-
-sales_df = pd.DataFrame(sales_data)
-
-# 데이터베이스에 안전하게 저장
-atio.write(
-    sales_df,
-    format="sql",
-    name="sales_orders",
-    con=engine,
-    if_exists="replace",
-    index=False
-)
-
-
-
-
-
-

스냅샷 기반 버전 관리

-
-

데이터 버전 관리

-
import atio
-import pandas as pd
-from datetime import datetime, timedelta
-
-# 초기 데이터
-initial_data = {
-    "user_id": [1, 2, 3],
-    "name": ["Alice", "Bob", "Charlie"],
-    "status": ["active", "active", "inactive"]
-}
-
-df = pd.DataFrame(initial_data)
-
-# 초기 스냅샷 생성
-snapshot_id_1 = atio.write_snapshot(df, "users", format="parquet")
-print(f"초기 스냅샷 생성: {snapshot_id_1}")
-
-# 데이터 업데이트
-df.loc[df['user_id'] == 3, 'status'] = 'active'
-df = df.append({"user_id": 4, "name": "Diana", "status": "active"}, ignore_index=True)
-
-# 업데이트된 스냅샷 생성
-snapshot_id_2 = atio.write_snapshot(df, "users", format="parquet")
-print(f"업데이트 스냅샷 생성: {snapshot_id_2}")
-
-# 최신 데이터 읽기
-latest_df = atio.read_table("users", format="parquet")
-print("최신 데이터:")
-print(latest_df)
-
-# 특정 스냅샷 읽기
-initial_df = atio.read_table("users", snapshot_id=snapshot_id_1, format="parquet")
-print("초기 데이터:")
-print(initial_df)
-
-# 오래된 스냅샷 정리 (7일 이상)
-deleted_count = atio.expire_snapshots("users", days=7, format="parquet")
-print(f"삭제된 스냅샷 수: {deleted_count}")
-
-
-
-
-
-

Polars DataFrame 활용

-
-

고성능 데이터 처리

-
import atio
-import polars as pl
-import numpy as np
-
-# Polars DataFrame 생성
-polars_data = {
-    "id": range(1, 10001),
-    "value": np.random.randn(10000),
-    "category": np.random.choice(["A", "B", "C", "D"], 10000),
-    "score": np.random.uniform(0, 100, 10000)
-}
-
-polars_df = pl.DataFrame(polars_data)
-
-# Polars DataFrame 저장
-atio.write(
-    polars_df,
-    "polars_data.parquet",
-    format="parquet",
-    compression='snappy',
-    show_progress=True
-)
-
-# 데이터 변환 후 저장
-filtered_df = polars_df.filter(pl.col("score") > 50)
-aggregated_df = filtered_df.group_by("category").agg(
-    pl.col("value").mean().alias("avg_value"),
-    pl.col("score").mean().alias("avg_score")
-)
-
-atio.write(aggregated_df, "aggregated_data.parquet", format="parquet")
-
-
-
-
-
-

에러 처리 및 복구

-
-

안전한 데이터 처리

-
import atio
-import pandas as pd
-import os
-
-def safe_data_processing():
-    try:
-        # 원본 파일이 있는지 확인
-        if os.path.exists("important_data.parquet"):
-            print("원본 파일이 존재합니다.")
-
-        # 데이터 처리 및 저장
-        df = pd.DataFrame({
-            "id": [1, 2, 3],
-            "data": ["important", "data", "here"]
-        })
-
-        atio.write(df, "important_data.parquet", format="parquet")
-        print("데이터가 안전하게 저장되었습니다.")
-
-        # SUCCESS 파일 확인
-        if os.path.exists("important_data.parquet_SUCCESS"):
-            print("저장 완료 플래그가 생성되었습니다.")
-
-    except Exception as e:
-        print(f"오류 발생: {e}")
-        print("원본 파일이 보존되었습니다.")
-
-        # 임시 파일 정리
-        temp_files = [f for f in os.listdir(".") if f.startswith("important_data.parquet.tmp")]
-        for temp_file in temp_files:
-            try:
-                os.remove(temp_file)
-                print(f"임시 파일 정리: {temp_file}")
-            except:
-                pass
-
-# 안전한 데이터 처리 실행
-safe_data_processing()
-
-
-
-
-
-

배치 처리

-
-

여러 파일 동시 처리

-
import atio
-import pandas as pd
-import os
-from pathlib import Path
-
-def process_multiple_files():
-    # 처리할 파일 목록
-    files_to_process = [
-        {"name": "users", "data": pd.DataFrame({"id": [1, 2], "name": ["Alice", "Bob"]})},
-        {"name": "products", "data": pd.DataFrame({"id": [1, 2], "product": ["Laptop", "Mouse"]})},
-        {"name": "orders", "data": pd.DataFrame({"id": [1, 2], "amount": [100, 200]})}
-    ]
-
-    # 각 파일을 안전하게 처리
-    for file_info in files_to_process:
-        try:
-            file_path = f"{file_info['name']}.parquet"
-            atio.write(
-                file_info['data'],
-                file_path,
-                format="parquet",
-                show_progress=True
-            )
-            print(f"{file_info['name']} 파일 처리 완료")
-
-        except Exception as e:
-            print(f"{file_info['name']} 파일 처리 실패: {e}")
-            continue
-
-# 배치 처리 실행
-process_multiple_files()
-
-
-
-
-
-

성능 최적화

-
-

압축 및 최적화 설정

-
import atio
-import pandas as pd
-import numpy as np
-
-# 대용량 데이터 생성
-large_df = pd.DataFrame({
-    "id": range(1, 100001),
-    "value": np.random.randn(100000),
-    "text": ["sample text"] * 100000
-})
-
-# 다양한 압축 설정으로 성능 비교
-compression_settings = [
-    ("snappy", "fast_compression.parquet"),
-    ("gzip", "balanced_compression.parquet"),
-    ("brotli", "high_compression.parquet")
-]
-
-for compression, filename in compression_settings:
-    print(f"\n{compression} 압축으로 저장 중...")
-    atio.write(
-        large_df,
-        filename,
-        format="parquet",
-        compression=compression,
-        show_progress=True,
-        verbose=True
-    )
-
-    # 파일 크기 확인
-    file_size = os.path.getsize(filename) / (1024 * 1024)  # MB
-    print(f"파일 크기: {file_size:.2f} MB")
-
-
-
-
-
-

실제 사용 사례

-
-

데이터 파이프라인

-
import atio
-import pandas as pd
-from datetime import datetime, timedelta
-
-class DataPipeline:
-    def __init__(self, base_path="data"):
-        self.base_path = Path(base_path)
-        self.base_path.mkdir(exist_ok=True)
-
-    def extract_data(self):
-        """데이터 추출 (시뮬레이션)"""
-        # 실제로는 API나 데이터베이스에서 데이터를 가져옴
-        data = {
-            "timestamp": pd.date_range(datetime.now(), periods=1000, freq="H"),
-            "value": np.random.randn(1000),
-            "source": ["api"] * 1000
-        }
-        return pd.DataFrame(data)
-
-    def transform_data(self, df):
-        """데이터 변환"""
-        # 시간별 집계
-        df['hour'] = df['timestamp'].dt.hour
-        df['day'] = df['timestamp'].dt.date
-
-        # 일별 통계
-        daily_stats = df.groupby('day').agg({
-            'value': ['mean', 'std', 'min', 'max']
-        }).round(2)
-
-        return daily_stats
-
-    def load_data(self, df, table_name):
-        """데이터 로드"""
-        # 스냅샷 생성
-        snapshot_id = atio.write_snapshot(
-            df,
-            table_name,
-            format="parquet"
-        )
-
-        # 최신 데이터도 별도 저장
-        latest_path = self.base_path / f"{table_name}_latest.parquet"
-        atio.write(df, str(latest_path), format="parquet")
-
-        return snapshot_id
-
-    def run_pipeline(self):
-        """파이프라인 실행"""
-        print("데이터 파이프라인 시작...")
-
-        # 1. 데이터 추출
-        raw_data = self.extract_data()
-        print(f"추출된 데이터: {len(raw_data)} 행")
-
-        # 2. 데이터 변환
-        processed_data = self.transform_data(raw_data)
-        print(f"처리된 데이터: {len(processed_data)} 행")
-
-        # 3. 데이터 로드
-        snapshot_id = self.load_data(processed_data, "daily_stats")
-        print(f"스냅샷 생성 완료: {snapshot_id}")
-
-        # 4. 오래된 스냅샷 정리
-        deleted_count = atio.expire_snapshots("daily_stats", days=30)
-        print(f"정리된 스냅샷: {deleted_count}개")
-
-        print("파이프라인 완료!")
-
-# 파이프라인 실행
-pipeline = DataPipeline()
-pipeline.run_pipeline()
-
-
-
-
-
- - -
-
- -
-
-
-
- - - - \ No newline at end of file diff --git a/docs/build/html/formats.html b/docs/build/html/formats.html deleted file mode 100644 index 7d12e18..0000000 --- a/docs/build/html/formats.html +++ /dev/null @@ -1,516 +0,0 @@ - - - - - - - - - 지원하는 파일 형식 — Atio 2.0.0 문서 - - - - - - - - - - - - - - - - -
- - -
- -
-
-
- -
-
-
-
- -
-

지원하는 파일 형식

-

Atio는 다양한 데이터 형식을 지원합니다. 각 형식별로 지원하는 라이브러리와 사용법을 설명합니다.

-
-

Pandas DataFrame 형식

-

Pandas DataFrame은 가장 많은 형식을 지원합니다.

-
-

CSV (Comma-Separated Values)

-
import atio
-import pandas as pd
-
-df = pd.DataFrame({
-    "name": ["Alice", "Bob", "Charlie"],
-    "age": [25, 30, 35],
-    "city": ["Seoul", "Busan", "Incheon"]
-})
-
-# 기본 CSV 저장
-atio.write(df, "users.csv", format="csv")
-
-# 추가 옵션과 함께 저장
-atio.write(df, "users.csv", format="csv",
-           index=False,
-           encoding='utf-8',
-           sep=';')
-
-
-

지원 옵션: -- index: 인덱스 포함 여부 (기본값: True) -- encoding: 인코딩 방식 (기본값: ‘utf-8’) -- sep: 구분자 (기본값: ‘,’) -- header: 헤더 포함 여부 (기본값: True)

-
-
-

Parquet

-
# Parquet 형식으로 저장
-atio.write(df, "users.parquet", format="parquet")
-
-# 압축 옵션과 함께 저장
-atio.write(df, "users.parquet", format="parquet",
-           compression='snappy')
-
-
-

지원 옵션: -- compression: 압축 방식 (‘snappy’, ‘gzip’, ‘brotli’, None) -- index: 인덱스 포함 여부 (기본값: True)

-
-
-

Excel

-
# Excel 파일로 저장
-atio.write(df, "users.xlsx", format="excel")
-
-# 시트명과 옵션 지정
-atio.write(df, "users.xlsx", format="excel",
-           sheet_name="Users",
-           index=False)
-
-
-

지원 옵션: -- sheet_name: 시트 이름 (기본값: ‘Sheet1’) -- index: 인덱스 포함 여부 (기본값: True) -- engine: 엔진 (‘openpyxl’, ‘xlsxwriter’)

-

필요 라이브러리: pip install openpyxl

-
-
-

JSON

-
# JSON 형식으로 저장
-atio.write(df, "users.json", format="json")
-
-# 들여쓰기와 함께 저장
-atio.write(df, "users.json", format="json",
-           indent=2,
-           orient='records')
-
-
-

지원 옵션: -- orient: JSON 구조 (‘split’, ‘records’, ‘index’, ‘columns’, ‘values’, ‘table’) -- indent: 들여쓰기 크기 -- date_format: 날짜 형식

-
-
-

Pickle

-
# Pickle 형식으로 저장
-atio.write(df, "users.pkl", format="pickle")
-
-# 압축과 함께 저장
-atio.write(df, "users.pkl", format="pickle",
-           compression='gzip')
-
-
-

지원 옵션: -- compression: 압축 방식 (‘gzip’, ‘bz2’, ‘xz’, None)

-
-
-

HTML

-
# HTML 테이블로 저장
-atio.write(df, "users.html", format="html")
-
-# 스타일과 함께 저장
-atio.write(df, "users.html", format="html",
-           index=False,
-           classes='table table-striped')
-
-
-

지원 옵션: -- classes: CSS 클래스 -- index: 인덱스 포함 여부 (기본값: True)

-
-
-

SQL

-
import atio
-import pandas as pd
-from sqlalchemy import create_engine
-
-# 데이터베이스 연결
-engine = create_engine('postgresql://user:password@localhost/dbname')
-
-df = pd.DataFrame({
-    "id": [1, 2, 3],
-    "name": ["Alice", "Bob", "Charlie"]
-})
-
-# SQL 데이터베이스에 저장
-atio.write(df, format="sql",
-           name="users",
-           con=engine,
-           if_exists='replace')
-
-
-

지원 옵션: -- name: 테이블 이름 (필수) -- con: 데이터베이스 연결 객체 (필수) -- if_exists: 테이블이 존재할 때 동작 (‘fail’, ‘replace’, ‘append’) -- index: 인덱스를 컬럼으로 저장 여부 (기본값: True)

-

필요 라이브러리: pip install sqlalchemy

-
-
-
-

Polars DataFrame 형식

-

Polars는 빠른 데이터 처리를 위한 현대적인 DataFrame 라이브러리입니다.

-
-

CSV

-
import atio
-import polars as pl
-
-df = pl.DataFrame({
-    "name": ["Alice", "Bob", "Charlie"],
-    "age": [25, 30, 35],
-    "city": ["Seoul", "Busan", "Incheon"]
-})
-
-# CSV 저장
-atio.write(df, "users.csv", format="csv")
-
-# 구분자와 함께 저장
-atio.write(df, "users.csv", format="csv",
-           separator=';')
-
-
-

지원 옵션: -- separator: 구분자 (기본값: ‘,’) -- include_header: 헤더 포함 여부 (기본값: True)

-
-
-

Parquet

-
# Parquet 저장
-atio.write(df, "users.parquet", format="parquet")
-
-# 압축과 함께 저장
-atio.write(df, "users.parquet", format="parquet",
-           compression="snappy")
-
-
-

지원 옵션: -- compression: 압축 방식 (‘snappy’, ‘gzip’, ‘brotli’, ‘lz4raw’, ‘zstd’, None)

-
-
-

JSON

-
# JSON 저장
-atio.write(df, "users.json", format="json")
-
-# 파일별 저장
-atio.write(df, "users.json", format="json",
-           file=True)
-
-
-

지원 옵션: -- file: 파일별 저장 여부 (기본값: False)

-
-
-

IPC (Arrow)

-
# IPC (Arrow) 형식으로 저장
-atio.write(df, "users.arrow", format="ipc")
-
-# 압축과 함께 저장
-atio.write(df, "users.arrow", format="ipc",
-           compression="lz4")
-
-
-

지원 옵션: -- compression: 압축 방식 (‘lz4’, ‘zstd’, None)

-
-
-

Avro

-
# Avro 형식으로 저장
-atio.write(df, "users.avro", format="avro")
-
-
-

필요 라이브러리: pip install fastavro

-
-
-

Excel

-
# Excel 저장
-atio.write(df, "users.xlsx", format="excel")
-
-
-

필요 라이브러리: pip install xlsx2csv openpyxl

-
-
-

Database

-
# 데이터베이스에 저장
-atio.write(df, format="database",
-           table_name="users",
-           connection_uri="postgresql://user:password@localhost/dbname")
-
-
-

지원 옵션: -- table_name: 테이블 이름 (필수) -- connection_uri: 데이터베이스 연결 URI (필수)

-

필요 라이브러리: pip install connectorx

-
-
-
-

NumPy 배열 형식

-

NumPy 배열은 수치 데이터 처리에 최적화된 형식을 지원합니다.

-
-

NPY (NumPy Binary)

-
import atio
-import numpy as np
-
-arr = np.array([[1, 2, 3], [4, 5, 6]])
-
-# .npy 파일로 저장
-atio.write(arr, "array.npy", format="npy")
-
-
-

특징: -- 단일 배열을 효율적으로 저장 -- 메타데이터와 함께 저장 -- 빠른 읽기/쓰기 속도

-
-
-

NPZ (NumPy Compressed)

-
# 여러 배열을 딕셔너리로 저장
-arrays = {
-    "features": np.random.randn(1000, 10),
-    "labels": np.random.randint(0, 2, 1000),
-    "metadata": np.array([1, 2, 3, 4, 5])
-}
-
-# 압축되지 않은 .npz 파일로 저장
-atio.write(arrays, "data.npz", format="npz")
-
-# 압축된 .npz 파일로 저장
-atio.write(arrays, "data.npz", format="npz_compressed")
-
-
-

특징: -- 여러 배열을 하나의 파일에 저장 -- 압축 옵션으로 저장 공간 절약 -- 딕셔너리 형태로 데이터 구조화

-
-
-

CSV

-
# CSV로 저장
-atio.write(arr, "array.csv", format="csv")
-
-# 구분자와 함께 저장
-atio.write(arr, "array.csv", format="csv",
-           delimiter=';',
-           fmt='%.2f')
-
-
-

지원 옵션: -- delimiter: 구분자 (기본값: ‘,’) -- fmt: 숫자 형식 (예: ‘%.2f’, ‘%.4e’) -- header: 헤더 포함 여부 -- comments: 주석 문자

-
-
-
-

형식별 성능 비교

-

다양한 형식의 성능 특성을 비교해보겠습니다.

-
-

속도 비교

-
    -
  1. 가장 빠른 형식: -- NumPy: .npy, .npz -- Polars: .ipc (Arrow) -- Pandas: .parquet (snappy 압축)

  2. -
  3. 중간 속도: -- CSV (단순한 구조) -- JSON (중간 복잡도)

  4. -
  5. 상대적으로 느린 형식: -- Excel (복잡한 구조) -- Pickle (Python 특화)

  6. -
-
-
-

용량 비교

-
    -
  1. 가장 작은 용량: -- .parquet (컬럼 기반 압축) -- .npz_compressed (압축된 NumPy) -- .ipc (Arrow 압축)

  2. -
  3. 중간 용량: -- .npy (단일 배열) -- JSON (텍스트 기반)

  4. -
  5. 상대적으로 큰 용량: -- CSV (텍스트 기반) -- Excel (복잡한 구조)

  6. -
-
-
-

호환성 비교

-
    -
  1. 최고 호환성: -- CSV (모든 시스템에서 지원) -- JSON (웹 표준)

  2. -
  3. 좋은 호환성: -- Excel (비즈니스 환경) -- Parquet (빅데이터 생태계)

  4. -
  5. 제한적 호환성: -- .npy/.npz (Python/NumPy 특화) -- .ipc (Arrow 생태계)

  6. -
-
-
-
-

권장 사용 사례

-
-

데이터 분석 및 머신러닝

-
# 학습 데이터: 빠른 읽기/쓰기를 위해 Parquet 사용
-atio.write(training_data, "train.parquet", format="parquet")
-
-# 모델 가중치: NumPy 배열로 저장
-atio.write(model_weights, "weights.npy", format="npy")
-
-# 실험 결과: JSON으로 저장 (가독성)
-atio.write(results, "experiment_results.json", format="json")
-
-
-
-
-

웹 애플리케이션

-
# API 응답: JSON 형식
-atio.write(api_data, "response.json", format="json")
-
-# 대용량 데이터: Parquet 형식
-atio.write(large_dataset, "dataset.parquet", format="parquet")
-
-
-
-
-

데이터 파이프라인

-
# 중간 결과: 빠른 처리를 위해 IPC 사용
-atio.write(intermediate_data, "step1.arrow", format="ipc")
-
-# 최종 결과: 호환성을 위해 CSV 사용
-atio.write(final_data, "output.csv", format="csv")
-
-
-
-
-

비즈니스 보고서

-
# 엑셀 보고서
-atio.write(report_data, "monthly_report.xlsx", format="excel")
-
-# HTML 대시보드
-atio.write(dashboard_data, "dashboard.html", format="html")
-
-
-
-
-
-

형식 확장하기

-

새로운 형식을 추가하려면 플러그인 시스템을 사용하세요.

-
from atio.plugins import register_writer
-import pandas as pd
-
-# 커스텀 형식 등록
-def yaml_writer(df, path, **kwargs):
-    import yaml
-    data = df.to_dict('records')
-    with open(path, 'w') as f:
-        yaml.dump(data, f, **kwargs)
-
-# 등록
-register_writer(pd.DataFrame, "yaml", yaml_writer)
-
-# 사용
-atio.write(df, "data.yaml", format="yaml")
-
-
-
-
- - -
-
- -
-
-
-
- - - - \ No newline at end of file diff --git a/docs/build/html/genindex.html b/docs/build/html/genindex.html deleted file mode 100644 index 5d6b9d5..0000000 --- a/docs/build/html/genindex.html +++ /dev/null @@ -1,265 +0,0 @@ - - - - - - - - 색인 — Atio 2.0.0 문서 - - - - - - - - - - - - - - - - -
- - -
- -
-
-
-
    -
  • - -
  • -
  • -
-
-
- - -
-
-
-
- - - - \ No newline at end of file diff --git a/docs/build/html/index.html b/docs/build/html/index.html deleted file mode 100644 index fd3d738..0000000 --- a/docs/build/html/index.html +++ /dev/null @@ -1,440 +0,0 @@ - - - - - - - - - Atio Documentation — Atio 2.0.0 문서 - - - - - - - - - - - - - - - - - -
- - -
- -
-
-
- -
-
-
-
- -
-

Atio Documentation

-

Atio 🛡️는 안전하고 원자적인 파일 쓰기를 지원하는 경량 Python 라이브러리입니다.

-

Pandas, Polars, NumPy 등 데이터 객체 저장 시 파일 손상 없이, **트랜잭션처럼 안전하게 처리**할 수 있습니다.

-
-

주요 기능

-
-
🔒 Atomic File Writing

Safe writing using temporary files

-
-
📊 Multiple Format Support

CSV, Parquet, Excel, JSON, etc.

-
-
🗄️ Database Support

Direct SQL and Database writing

-
-
📈 Progress Display

Progress monitoring for large data processing

-
-
🔄 Rollback Function

Automatic recovery when errors occur

-
-
🎯 Simple API

Intuitive and easy-to-use interface

-
-
📋 Version Management

Snapshot-based data version management

-
-
🧹 Auto Cleanup

Automatic deletion of old data

-
-
-
-
-

빠른 시작

-
import atio
-import pandas as pd
-
-# 간단한 DataFrame 생성
-df = pd.DataFrame({
-    "name": ["Alice", "Bob", "Charlie"],
-    "age": [25, 30, 35],
-    "city": ["Seoul", "Busan", "Incheon"]
-})
-
-# 안전한 파일 쓰기
-atio.write(df, "users.parquet", format="parquet")
-
-# 진행도 표시와 함께 저장
-atio.write(df, "users.csv", format="csv", show_progress=True)
-
-
-
-
-

지원하는 형식

- - ------ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
지원하는 파일 형식

형식

Pandas

Polars

NumPy

CSV

Parquet

Excel

JSON

Pickle

HTML

SQL

Database

NPY/NPZ

-
-
-

사용 사례

-
-
🔹 데이터 파이프라인

ETL 과정에서 중간 데이터 안전하게 저장

-
-
🔹 실험 데이터 관리

머신러닝 실험 결과의 버전 관리

-
-
🔹 대용량 데이터 처리

대용량 파일의 안전한 저장 및 진행도 모니터링

-
-
🔹 데이터베이스 연동

Pandas/Polars 데이터를 SQL/NoSQL DB에 안전하게 저장

-
-
-
-
-

목차

- - -
-
-
-

API Reference

-
-

핵심 함수들

-

Atio: 안전한 원자적 파일 쓰기 라이브러리

-

progress 적용 후 write 함수

-
-
-atio.core.write(obj, target_path=None, format=None, show_progress=False, verbose=False, **kwargs)[소스]
-

데이터 객체(obj)를 안전하게 target_path 또는 데이터베이스에 저장합니다.

-
    -
  • 파일 기반 쓰기 (format: ‘csv’, ‘parquet’, ‘excel’ 등): -- target_path (str): 필수. 데이터가 저장될 파일 경로입니다. -- 롤백 기능이 있는 원자적 쓰기를 수행합니다.

  • -
  • 데이터베이스 기반 쓰기 (format: ‘sql’, ‘database’): -- target_path: 사용되지 않습니다. -- kwargs (dict): 데이터베이스 쓰기에 필요한 추가 인자들입니다.

    -
    -
      -
    • pandas.to_sql: ‘name’(테이블명), ‘con’(커넥션 객체)가 필수입니다.

    • -
    • polars.write_database: ‘table_name’, ‘connection_uri’가 필수입니다.

    • -
    -
    -
  • -
-
-
매개변수:
-
    -
  • obj – 저장할 데이터 객체 (e.g., pandas.DataFrame, polars.DataFrame, np.ndarray).

  • -
  • target_path (str, optional) – 파일 저장 경로. 파일 기반 쓰기 시 필수. Defaults to None.

  • -
  • format (str, optional) – 저장할 포맷. Defaults to None.

  • -
  • show_progress (bool) – 진행도 표시 여부. Defaults to False.

  • -
  • verbose (bool) – 상세한 성능 진단 정보 출력 여부. Defaults to False.

  • -
  • **kwargs – 각 쓰기 함수에 전달될 추가 키워드 인자.

  • -
-
-
-
- -
-
-atio.core.write_snapshot(obj, table_path, mode='overwrite', format='parquet', **kwargs)[소스]
-
- -
-
-atio.core.read_table(table_path, version=None, output_as='pandas')[소스]
-
- -
-
-atio.core.expire_snapshots(table_path, keep_for=datetime.timedelta(days=7), dry_run=True)[소스]
-

설정된 보관 기간(keep_for)보다 오래된 스냅샷과 -더 이상 참조되지 않는 데이터 파일을 삭제합니다.

-
- -
-
-atio.plugins.register_writer(obj_type, fmt, handler)[소스]
-

(객체 타입, 포맷) 쌍으로 쓰기 핸들러를 등록

-
- -
-
-atio.plugins.get_writer(obj, fmt)[소스]
-

객체의 타입과 포맷에 맞는 핸들러를 조회

-
- -
-
-atio.utils.setup_logger(name='atio', debug_level=False)[소스]
-
- -
-
-atio.utils.check_file_exists(path)[소스]
-
- -
-
-class atio.utils.ProgressBar(filepath: str, stop_event: Event, description: str = 'Writing')[소스]
-

파일 쓰기 진행 상황을 콘솔에 표시하는 클래스. -스피너, 처리된 용량, 처리 속도, 경과 시간을 표시합니다.

-
-
-__init__(filepath: str, stop_event: Event, description: str = 'Writing')[소스]
-
- -
-
-run()[소스]
-

진행도 막대를 실행하는 메인 루프. -이 함수가 모니터링 스레드에서 실행됩니다.

-
- -
- -
-
-atio.utils.read_json(path: str)[소스]
-
- -
-
-atio.utils.write_json(data: dict, path: str)[소스]
-
- -
-
-
-

Indices and tables

- -
- - -
-
- -
-
-
-
- - - - \ No newline at end of file diff --git a/docs/build/html/installation.html b/docs/build/html/installation.html deleted file mode 100644 index 6e08980..0000000 --- a/docs/build/html/installation.html +++ /dev/null @@ -1,310 +0,0 @@ - - - - - - - - - 설치 가이드 — Atio 2.0.0 문서 - - - - - - - - - - - - - - - - - - -
- - -
- -
-
-
- -
-
-
-
- -
-

설치 가이드

-

Atio를 설치하는 방법을 안내합니다.

-
-

PyPI를 통한 설치

-

가장 간단한 설치 방법은 PyPI를 사용하는 것입니다:

-
pip install atio
-
-
-
-

특정 버전 설치

-

특정 버전을 설치하려면:

-
pip install atio==2.0.0
-
-
-
-
-

개발 버전 설치

-

최신 개발 버전을 설치하려면:

-
pip install git+https://github.com/seojaeohcode/atio.git
-
-
-
-
-
-

의존성

-
-

필수 의존성

-
    -
  • Python 3.8+

  • -
  • pandas

  • -
  • numpy

  • -
-
-
-

선택적 의존성

-

특정 형식을 사용하려면 추가 라이브러리가 필요합니다:

-

Parquet 형식: -.. code-block:: bash

-
-

pip install pyarrow -# 또는 -pip install fastparquet

-
-

Excel 형식: -.. code-block:: bash

-
-

pip install openpyxl -# 또는 -pip install xlsxwriter

-
-

SQL 데이터베이스: -.. code-block:: bash

-
-

pip install sqlalchemy

-
-

Polars 지원: -.. code-block:: bash

-
-

pip install polars

-
-

Avro 형식 (Polars): -.. code-block:: bash

-
-

pip install fastavro

-
-

Polars Excel 지원: -.. code-block:: bash

-
-

pip install xlsx2csv openpyxl

-
-

Polars 데이터베이스 지원: -.. code-block:: bash

-
-

pip install connectorx

-
-
-
-

모든 의존성 설치

-

모든 기능을 사용하려면:

-
pip install atio[all]
-
-
-

또는 개별적으로:

-
pip install atio
-pip install pyarrow openpyxl sqlalchemy polars fastavro xlsx2csv connectorx
-
-
-
-
-
-

환경 확인

-

설치가 완료되었는지 확인하려면:

-
import atio
-print(f"Atio 버전: {atio.__version__}")
-
-# 기본 기능 테스트
-import pandas as pd
-df = pd.DataFrame({"test": [1, 2, 3]})
-atio.write(df, "test.parquet", format="parquet")
-print("설치가 성공적으로 완료되었습니다!")
-
-
-
-
-

가상환경 사용 권장

-

프로젝트별로 독립적인 환경을 유지하기 위해 가상환경 사용을 권장합니다:

-
# 가상환경 생성
-python -m venv atio_env
-
-# 가상환경 활성화 (Windows)
-atio_env\Scripts\activate
-
-# 가상환경 활성화 (macOS/Linux)
-source atio_env/bin/activate
-
-# Atio 설치
-pip install atio
-
-
-
-
-

Conda 사용

-

Conda를 사용하는 경우:

-
# Conda 환경 생성
-conda create -n atio_env python=3.8
-conda activate atio_env
-
-# Atio 설치
-pip install atio
-
-
-
-
-

문제 해결

-

설치 중 문제가 발생하는 경우:

-

권한 오류: -.. code-block:: bash

-
-

pip install atio –user

-
-

캐시 문제: -.. code-block:: bash

-
-

pip install atio –no-cache-dir

-
-

의존성 충돌: -.. code-block:: bash

-
-

pip install atio –force-reinstall

-
-

특정 Python 버전: -.. code-block:: bash

-
-

python3.8 -m pip install atio

-
-
-
-

업그레이드

-

최신 버전으로 업그레이드:

-
pip install --upgrade atio
-
-
-

특정 버전으로 다운그레이드:

-
pip install atio==1.0.0
-
-
-
-
-

제거

-

Atio를 제거하려면:

-
pip uninstall atio
-
-
-
-
- - -
-
- -
-
-
-
- - - - \ No newline at end of file diff --git a/docs/build/html/objects.inv b/docs/build/html/objects.inv deleted file mode 100644 index 1b00a34..0000000 Binary files a/docs/build/html/objects.inv and /dev/null differ diff --git a/docs/build/html/py-modindex.html b/docs/build/html/py-modindex.html deleted file mode 100644 index 2ec5a74..0000000 --- a/docs/build/html/py-modindex.html +++ /dev/null @@ -1,144 +0,0 @@ - - - - - - - - Python 모듈 목록 — Atio 2.0.0 문서 - - - - - - - - - - - - - - - - - - - -
- - -
- -
-
-
-
    -
  • - -
  • -
  • -
-
-
-
-
- - -

Python 모듈 목록

- -
- a -
- - - - - - - - - - - - - - - - -
 
- a
- atio -
    - atio.core -
    - atio.plugins -
    - atio.utils -
- - -
-
- -
-
-
-
- - - - \ No newline at end of file diff --git a/docs/build/html/quickstart.html b/docs/build/html/quickstart.html deleted file mode 100644 index 445bdea..0000000 --- a/docs/build/html/quickstart.html +++ /dev/null @@ -1,238 +0,0 @@ - - - - - - - - - 빠른 시작 — Atio 2.0.0 문서 - - - - - - - - - - - - - - - - - - -
- - -
- -
-
-
- -
-
-
-
- -
-

빠른 시작

-

Atio를 사용하여 안전한 파일 쓰기를 시작해보세요.

-
-

기본 사용법

-

가장 간단한 사용법부터 시작해보겠습니다:

-
import atio
-import pandas as pd
-
-# 샘플 데이터 생성
-df = pd.DataFrame({
-    "name": ["Alice", "Bob", "Charlie"],
-    "age": [25, 30, 35],
-    "city": ["Seoul", "Busan", "Incheon"]
-})
-
-# 안전한 파일 쓰기
-atio.write(df, "users.parquet", format="parquet")
-
-
-

이 코드는 다음과 같은 안전장치를 제공합니다:

-
    -
  • ✅ 임시 파일에 먼저 저장

  • -
  • ✅ 저장 완료 후 원자적으로 파일 교체

  • -
  • ✅ 실패 시 원본 파일 보존

  • -
  • _SUCCESS 플래그 파일 생성

  • -
-
-
-

다양한 형식 지원

-

Atio는 다양한 데이터 형식을 지원합니다:

-
# CSV 형식
-atio.write(df, "users.csv", format="csv", index=False)
-
-# Excel 형식
-atio.write(df, "users.xlsx", format="excel", sheet_name="Users")
-
-# JSON 형식
-atio.write(df, "users.json", format="json", orient="records")
-
-# Parquet 형식 (권장)
-atio.write(df, "users.parquet", format="parquet")
-
-
-
-
-

진행률 표시

-

대용량 데이터 처리 시 진행률을 확인할 수 있습니다:

-
# 진행률 표시 활성화
-atio.write(large_df, "big_data.parquet", format="parquet", show_progress=True)
-
-
-
-
-

성능 모니터링

-

상세한 성능 정보를 확인하려면:

-
# 성능 정보 출력
-atio.write(df, "data.parquet", format="parquet", verbose=True)
-
-
-
-
-

Polars DataFrame 지원

-

Polars DataFrame도 지원합니다:

-
import polars as pl
-
-# Polars DataFrame 생성
-polars_df = pl.DataFrame({
-    "a": [1, 2, 3],
-    "b": [4, 5, 6]
-})
-
-# Polars DataFrame 저장
-atio.write(polars_df, "data.parquet", format="parquet")
-
-
-
-
-

데이터베이스 저장

-

SQL 데이터베이스에 직접 저장할 수도 있습니다:

-
from sqlalchemy import create_engine
-
-# 데이터베이스 연결
-engine = create_engine('postgresql://user:password@localhost/dbname')
-
-# 데이터베이스에 저장
-atio.write(df, format="sql", name="users", con=engine, if_exists="replace")
-
-
-
-
-

스냅샷 기능

-

데이터 버전 관리를 위한 스냅샷 기능:

-
# 스냅샷 생성
-atio.write_snapshot(df, "users", format="parquet")
-
-# 스냅샷 읽기
-df = atio.read_table("users", snapshot_id="latest")
-
-# 오래된 스냅샷 정리
-atio.expire_snapshots("users", days=30)
-
-
-
-
-

다음 단계

- -
-
- - -
-
- -
-
-
-
- - - - \ No newline at end of file diff --git a/docs/build/html/search.html b/docs/build/html/search.html deleted file mode 100644 index 29cc9bb..0000000 --- a/docs/build/html/search.html +++ /dev/null @@ -1,129 +0,0 @@ - - - - - - - - 검색 — Atio 2.0.0 문서 - - - - - - - - - - - - - - - - - - - -
- - -
- -
-
-
-
    -
  • - -
  • -
  • -
-
-
-
-
- - - - -
- -
- -
-
- -
-
-
-
- - - - - - - - - \ No newline at end of file diff --git a/docs/build/html/searchindex.js b/docs/build/html/searchindex.js deleted file mode 100644 index b78a68e..0000000 --- a/docs/build/html/searchindex.js +++ /dev/null @@ -1 +0,0 @@ -Search.setIndex({"alltitles":{"API Reference":[[5,"api-reference"]],"API \ucc38\uc870":[[1,null]],"API \ucc38\uc870:":[[5,null]],"Atio Documentation":[[5,null]],"Avro":[[4,"avro"]],"CSV":[[4,"csv"],[4,"id5"]],"CSV (Comma-Separated Values)":[[4,"csv-comma-separated-values"]],"CSV \ud615\uc2dd":[[1,"csv"]],"Conda \uc0ac\uc6a9":[[6,"conda"]],"Core \ubaa8\ub4c8":[[1,"core"]],"Database":[[4,"database"]],"ETL \ud30c\uc774\ud504\ub77c\uc778":[[0,"etl"]],"Excel":[[4,"excel"],[4,"id4"]],"Excel \ud615\uc2dd":[[1,"excel"]],"HTML":[[4,"html"]],"IPC (Arrow)":[[4,"ipc-arrow"]],"Indices and tables":[[5,"indices-and-tables"]],"JSON":[[4,"json"],[4,"id3"]],"JSON \uc124\uc815 \ud30c\uc77c":[[2,"json"]],"JSON \ud615\uc2dd":[[1,"json"]],"NPY (NumPy Binary)":[[4,"npy-numpy-binary"]],"NPZ (NumPy Compressed)":[[4,"npz-numpy-compressed"]],"NumPy \ubc30\uc5f4 \ucc98\ub9ac":[[0,"numpy"]],"NumPy \ubc30\uc5f4 \ud615\uc2dd":[[4,"numpy"]],"Pandas DataFrame \ud615\uc2dd":[[4,"pandas-dataframe"]],"Pandas SQL \uc5f0\ub3d9":[[0,"pandas-sql"]],"Parquet":[[4,"parquet"],[4,"id2"]],"Parquet \ud615\uc2dd":[[1,"parquet"]],"Pickle":[[4,"pickle"]],"Plugins \ubaa8\ub4c8":[[1,"plugins"]],"Polars DataFrame \uc9c0\uc6d0":[[7,"polars-dataframe"]],"Polars DataFrame \ud615\uc2dd":[[4,"polars-dataframe"]],"Polars DataFrame \ud65c\uc6a9":[[3,"polars-dataframe"]],"Polars \ub370\uc774\ud130\ubca0\uc774\uc2a4 \uc5f0\ub3d9":[[0,"polars"]],"PostgreSQL \ub370\uc774\ud130\ubca0\uc774\uc2a4 \uc800\uc7a5":[[3,"postgresql"]],"PyPI\ub97c \ud1b5\ud55c \uc124\uce58":[[6,"pypi"]],"SQL":[[4,"sql"]],"SQL \ud615\uc2dd":[[1,"sql"]],"Utils \ubaa8\ub4c8":[[1,"utils"]],"YAML \uc124\uc815 \ud30c\uc77c":[[2,"yaml"]],"expire_snapshots()":[[1,"expire-snapshots"]],"read_table()":[[1,"read-table"]],"write()":[[1,"write"]],"write_snapshot()":[[1,"write-snapshot"]],"\uac00\uc0c1\ud658\uacbd \uc0ac\uc6a9 \uad8c\uc7a5":[[6,"id9"]],"\uac04\ub2e8\ud55c \ub370\uc774\ud130 \uc800\uc7a5":[[3,"id3"]],"\uac1c\ubc1c \ubc84\uc804 \uc124\uce58":[[6,"id3"]],"\uac1c\ubc1c \ud658\uacbd \uc124\uc815":[[2,"id32"]],"\uace0\uae09 \uc0ac\uc6a9\ubc95":[[0,null]],"\uace0\uc131\ub2a5 \ub370\uc774\ud130 \ucc98\ub9ac":[[3,"id9"]],"\uad8c\uc7a5 \uc0ac\uc6a9 \uc0ac\ub840":[[4,"id10"]],"\uae30\ubcf8 \uac80\uc99d":[[2,"id34"]],"\uae30\ubcf8 \ub85c\uae45":[[2,"id3"]],"\uae30\ubcf8 \uc0ac\uc6a9\ubc95":[[7,"id2"]],"\uae30\ubcf8 \uc2a4\ub0c5\uc0f7 \uc4f0\uae30":[[0,"id3"]],"\uae30\ubcf8 \uc608\uc81c":[[3,"id2"]],"\uae30\ubcf8 \uc9c4\ud589\ub3c4 \ud45c\uc2dc":[[2,"id6"]],"\ub2e4\uc591\ud55c \ud615\uc2dd \uc9c0\uc6d0":[[7,"id3"]],"\ub2e4\uc74c \ub2e8\uacc4":[[7,"id8"]],"\ub2e8\uc77c \ubc30\uc5f4 \uc800\uc7a5":[[0,"id16"]],"\ub300\uc6a9\ub7c9 \ub370\uc774\ud130 \ucc98\ub9ac":[[3,"id4"]],"\ub370\uc774\ud130 \ubc84\uc804 \uad00\ub9ac":[[3,"id8"]],"\ub370\uc774\ud130 \ubd84\uc11d \ubc0f \uba38\uc2e0\ub7ec\ub2dd":[[4,"id11"]],"\ub370\uc774\ud130 \ud30c\uc774\ud504\ub77c\uc778":[[3,"id17"],[4,"id13"]],"\ub370\uc774\ud130\ubca0\uc774\uc2a4 \uc5d0\ub7ec":[[0,"id13"]],"\ub370\uc774\ud130\ubca0\uc774\uc2a4 \uc5f0\ub3d9":[[0,"id6"],[3,"id6"]],"\ub370\uc774\ud130\ubca0\uc774\uc2a4 \uc800\uc7a5":[[7,"id6"]],"\ub85c\uae45 \ub808\ubca8 \uc124\uc815":[[2,"id23"]],"\ub85c\uae45 \uc124\uc815":[[2,"id2"]],"\ub864\ubc31 \ub3d9\uc791":[[2,"id14"]],"\uba38\uc2e0\ub7ec\ub2dd \ud30c\uc774\ud504\ub77c\uc778":[[0,"id19"]],"\uba54\ubaa8\ub9ac \uc0ac\uc6a9\ub7c9 \ucd5c\uc801\ud654":[[2,"id9"]],"\ubaa8\ub4e0 \uc758\uc874\uc131 \uc124\uce58":[[6,"id7"]],"\ubaa8\ubc94 \uc0ac\ub840":[[2,"id30"]],"\ubaa9\ucc28":[[5,"id7"]],"\ubb38\uc81c \ud574\uacb0":[[6,"id10"]],"\ubc30\uce58 \ucc98\ub9ac":[[3,"id12"]],"\ubc31\uc5c5 \ud30c\uc77c \uad00\ub9ac":[[2,"id15"]],"\ube44\uc988\ub2c8\uc2a4 \ubcf4\uace0\uc11c":[[4,"id14"]],"\ube60\ub978 \uc2dc\uc791":[[5,"id4"],[7,null]],"\uc0ac\uc6a9 \uc0ac\ub840":[[5,"id6"]],"\uc0ac\uc6a9 \uc608\uc81c":[[3,null]],"\uc0ac\uc6a9\uc790 \uac00\uc774\ub4dc:":[[5,null]],"\uc0ac\uc6a9\uc790 \uc815\uc758 \uc784\uc2dc \ub514\ub809\ud1a0\ub9ac":[[2,"id12"]],"\uc0c1\uc138 \ub85c\uae45":[[0,"id9"],[2,"id4"]],"\uc120\ud0dd\uc801 \uc758\uc874\uc131":[[6,"id6"]],"\uc124\uc815 \uac80\uc99d":[[2,"id33"]],"\uc124\uc815 \ubc0f \uad6c\uc131":[[2,null]],"\uc124\uc815 \ud30c\uc77c \uc0ac\uc6a9":[[2,"id29"]],"\uc124\uce58 \uac00\uc774\ub4dc":[[6,null]],"\uc131\ub2a5 \ubaa8\ub2c8\ud130\ub9c1":[[7,"id5"]],"\uc131\ub2a5 \ubaa8\ub2c8\ud130\ub9c1 \uc124\uc815":[[2,"id25"]],"\uc131\ub2a5 \ucd5c\uc801\ud654":[[0,"id7"],[3,"id14"]],"\uc131\ub2a5 \ucd5c\uc801\ud654 \uc124\uc815":[[2,"id8"]],"\uc131\ub2a5 \ud14c\uc2a4\ud2b8":[[2,"id35"]],"\uc18d\ub3c4 \ube44\uad50":[[4,"id7"]],"\uc2a4\ub0c5\uc0f7 \uae30\ub2a5":[[7,"id7"]],"\uc2a4\ub0c5\uc0f7 \uae30\ubc18 \ubc84\uc804 \uad00\ub9ac":[[0,"id2"],[3,"id7"]],"\uc2a4\ub0c5\uc0f7 \ubaa8\ub4dc":[[2,"id20"]],"\uc2a4\ub0c5\uc0f7 \uc124\uc815":[[2,"id19"]],"\uc2a4\ub0c5\uc0f7 \uc77d\uae30":[[0,"id4"]],"\uc2a4\ub0c5\uc0f7 \uc815\ub9ac":[[0,"id5"]],"\uc2a4\ub0c5\uc0f7 \uc815\ub9ac \uc124\uc815":[[2,"id21"]],"\uc2e4\uc81c \uc0ac\uc6a9 \uc0ac\ub840":[[0,"id18"],[3,"id16"]],"\uc548\uc804\ud55c \ub370\uc774\ud130 \ucc98\ub9ac":[[3,"id11"]],"\uc555\ucd95 \ubc0f \ucd5c\uc801\ud654 \uc124\uc815":[[3,"id15"]],"\uc555\ucd95 \uc124\uc815":[[2,"id10"]],"\uc5c5\uadf8\ub808\uc774\ub4dc":[[6,"id11"]],"\uc5d0\ub7ec \ucc98\ub9ac":[[0,"id10"]],"\uc5d0\ub7ec \ucc98\ub9ac \ubc0f \ubcf5\uad6c":[[3,"id10"]],"\uc5d0\ub7ec \ucc98\ub9ac \uc124\uc815":[[2,"id13"]],"\uc5ec\ub7ec \ubc30\uc5f4 \uc800\uc7a5":[[0,"id17"]],"\uc5ec\ub7ec \ud30c\uc77c \ub3d9\uc2dc \ucc98\ub9ac":[[3,"id13"]],"\uc608\uc678 \ucc98\ub9ac":[[1,"id9"]],"\uc644\ub8cc \ud50c\ub798\uadf8 \uc2dc\uc2a4\ud15c":[[2,"id16"]],"\uc6a9\ub7c9 \ube44\uad50":[[4,"id8"]],"\uc6f9 \uc560\ud50c\ub9ac\ucf00\uc774\uc158":[[4,"id12"]],"\uc758\uc874\uc131":[[6,"id4"]],"\uc784\uc2dc \ub514\ub809\ud1a0\ub9ac \uc124\uc815":[[2,"id11"],[2,"id24"]],"\uc81c\uac70":[[6,"id12"]],"\uc8fc\uc694 \uae30\ub2a5":[[5,"id3"]],"\uc8fc\uc694 \ud568\uc218":[[1,"id1"]],"\uc9c0\uc6d0\ud558\ub294 \ud30c\uc77c \ud615\uc2dd":[[4,null],[5,"id9"]],"\uc9c0\uc6d0\ud558\ub294 \ud615\uc2dd":[[1,"id8"],[5,"id5"]],"\uc9c4\ud589\ub3c4 \ud45c\uc2dc":[[0,"id8"],[2,"id5"]],"\uc9c4\ud589\ub3c4 \ud45c\uc2dc \uc635\uc158":[[2,"id7"]],"\uc9c4\ud589\ub960 \ud45c\uc2dc":[[7,"id4"]],"\uc9c4\ud589\ub960 \ud45c\uc2dc\uc640 \uc131\ub2a5 \ubaa8\ub2c8\ud130\ub9c1":[[3,"id5"]],"\ucee4\uc2a4\ud140 \ud615\uc2dd \ub4f1\ub85d":[[0,"id15"]],"\ud2b9\uc815 \ubc84\uc804 \uc124\uce58":[[6,"id2"]],"\ud30c\uc77c \uc2dc\uc2a4\ud15c \uc5d0\ub7ec":[[0,"id11"]],"\ud3ec\ub9f7 \uc5d0\ub7ec":[[0,"id12"]],"\ud504\ub85c\ub355\uc158 \ud658\uacbd \uc124\uc815":[[2,"id31"]],"\ud50c\ub798\uadf8 \ud30c\uc77c \ud655\uc778":[[2,"id17"]],"\ud50c\ub798\uadf8 \ud30c\uc77c \ud65c\uc6a9":[[2,"id18"]],"\ud50c\ub7ec\uadf8\uc778 \ub4f1\ub85d":[[2,"id27"]],"\ud50c\ub7ec\uadf8\uc778 \uc124\uc815":[[2,"id26"]],"\ud50c\ub7ec\uadf8\uc778 \ud655\uc778":[[2,"id28"]],"\ud50c\ub7ec\uadf8\uc778 \ud655\uc7a5":[[0,"id14"]],"\ud544\uc218 \uc758\uc874\uc131":[[6,"id5"]],"\ud575\uc2ec \ud568\uc218\ub4e4":[[5,"module-atio"]],"\ud615\uc2dd \ud655\uc7a5\ud558\uae30":[[4,"id15"]],"\ud615\uc2dd\ubcc4 \uc131\ub2a5 \ube44\uad50":[[4,"id6"]],"\ud638\ud658\uc131 \ube44\uad50":[[4,"id9"]],"\ud658\uacbd \ubcc0\uc218 \uc124\uc815":[[2,"id22"]],"\ud658\uacbd \ud655\uc778":[[6,"id8"]]},"docnames":["advanced_usage","api","configuration","examples","formats","index","installation","quickstart"],"envversion":{"sphinx":65,"sphinx.domains.c":3,"sphinx.domains.changeset":1,"sphinx.domains.citation":1,"sphinx.domains.cpp":9,"sphinx.domains.index":1,"sphinx.domains.javascript":3,"sphinx.domains.math":2,"sphinx.domains.python":4,"sphinx.domains.rst":2,"sphinx.domains.std":2,"sphinx.ext.intersphinx":1,"sphinx.ext.viewcode":1},"filenames":["advanced_usage.rst","api.rst","configuration.rst","examples.rst","formats.rst","index.rst","installation.rst","quickstart.rst"],"indexentries":{"__init__() (atio.utils.progressbar \uba54\uc11c\ub4dc)":[[1,"atio.utils.ProgressBar.__init__",false],[5,"atio.utils.ProgressBar.__init__",false]],"atio":[[1,"module-atio",false],[5,"module-atio",false]],"atio.core":[[1,"module-atio.core",false],[5,"module-atio.core",false]],"atio.expire_snapshots() (atio.core \ubaa8\ub4c8)":[[1,"atio.core.atio.expire_snapshots",false]],"atio.plugins":[[1,"module-atio.plugins",false],[5,"module-atio.plugins",false]],"atio.read_table() (atio.core \ubaa8\ub4c8)":[[1,"atio.core.atio.read_table",false]],"atio.utils":[[1,"module-atio.utils",false],[5,"module-atio.utils",false]],"atio.write() (atio.core \ubaa8\ub4c8)":[[1,"atio.core.atio.write",false]],"atio.write_snapshot() (atio.core \ubaa8\ub4c8)":[[1,"atio.core.atio.write_snapshot",false]],"check_file_exists() (atio.utils \ubaa8\ub4c8)":[[1,"atio.utils.check_file_exists",false],[5,"atio.utils.check_file_exists",false]],"expire_snapshots() (atio.core \ubaa8\ub4c8)":[[1,"atio.core.expire_snapshots",false],[5,"atio.core.expire_snapshots",false]],"get_writer() (atio.plugins \ubaa8\ub4c8)":[[1,"atio.plugins.get_writer",false],[5,"atio.plugins.get_writer",false]],"module":[[1,"module-atio",false],[1,"module-atio.core",false],[1,"module-atio.plugins",false],[1,"module-atio.utils",false],[5,"module-atio",false],[5,"module-atio.core",false],[5,"module-atio.plugins",false],[5,"module-atio.utils",false]],"progressbar (atio.utils \ud074\ub798\uc2a4)":[[1,"atio.utils.ProgressBar",false],[5,"atio.utils.ProgressBar",false]],"read_json() (atio.utils \ubaa8\ub4c8)":[[1,"atio.utils.read_json",false],[5,"atio.utils.read_json",false]],"read_table() (atio.core \ubaa8\ub4c8)":[[1,"atio.core.read_table",false],[5,"atio.core.read_table",false]],"register_writer() (atio.plugins \ubaa8\ub4c8)":[[1,"atio.plugins.register_writer",false],[5,"atio.plugins.register_writer",false]],"run() (atio.utils.progressbar \uba54\uc11c\ub4dc)":[[1,"atio.utils.ProgressBar.run",false],[5,"atio.utils.ProgressBar.run",false]],"setup_logger() (atio.utils \ubaa8\ub4c8)":[[1,"atio.utils.setup_logger",false],[5,"atio.utils.setup_logger",false]],"write() (atio.core \ubaa8\ub4c8)":[[1,"atio.core.write",false],[5,"atio.core.write",false]],"write_json() (atio.utils \ubaa8\ub4c8)":[[1,"atio.utils.write_json",false],[5,"atio.utils.write_json",false]],"write_snapshot() (atio.core \ubaa8\ub4c8)":[[1,"atio.core.write_snapshot",false],[5,"atio.core.write_snapshot",false]]},"objects":{"":[[5,0,0,"-","atio"]],"atio":[[5,0,0,"-","core"],[5,0,0,"-","plugins"],[5,0,0,"-","utils"]],"atio.core":[[5,1,1,"","expire_snapshots"],[5,1,1,"","read_table"],[5,1,1,"","write"],[5,1,1,"","write_snapshot"]],"atio.core.atio":[[1,1,1,"","expire_snapshots"],[1,1,1,"","read_table"],[1,1,1,"","write"],[1,1,1,"","write_snapshot"]],"atio.plugins":[[5,1,1,"","get_writer"],[5,1,1,"","register_writer"]],"atio.utils":[[5,2,1,"","ProgressBar"],[5,1,1,"","check_file_exists"],[5,1,1,"","read_json"],[5,1,1,"","setup_logger"],[5,1,1,"","write_json"]],"atio.utils.ProgressBar":[[5,3,1,"","__init__"],[5,3,1,"","run"]]},"objnames":{"0":["py","module","Python \ubaa8\ub4c8"],"1":["py","function","Python \ud568\uc218"],"2":["py","class","Python \ud074\ub798\uc2a4"],"3":["py","method","Python \uba54\uc11c\ub4dc"]},"objtypes":{"0":"py:module","1":"py:function","2":"py:class","3":"py:method"},"terms":{"":[2,3],"0":[0,2,3,4,6],"00":2,"0001":2,"0012":2,"01":3,"03":2,"05":2,"07":2,"0987":2,"1":[0,1,2,3,4,6,7],"10":[0,2,4],"100":3,"1000":[0,3,4],"10000":3,"100000":[2,3],"1000000":[0,2,3],"1000001":3,"100001":3,"10001":3,"1001":[2,3],"1002":3,"1003":3,"1004":3,"1005":3,"100\ub9cc":3,"1024":[2,3],"11":2,"12":2,"1200":3,"1234":2,"150":3,"2":[0,1,2,3,4,6,7],"200":3,"2024":3,"20240101_120000":1,"25":[3,4,5,7],"28":3,"2f":[2,3,4],"3":[0,1,2,3,4,6,7],"30":[1,2,3,4,5,7],"300":3,"30\uc77c":[1,2],"32":3,"35":[3,4,5,7],"4":[0,3,4,7],"45":2,"4e":4,"5":[0,3,4,7],"50":3,"50000":3,"5432":3,"55000":3,"6":[0,4,7],"60000":3,"65000":3,"67":2,"7":[0,1,2,3,5],"70000":3,"75":3,"7\uc77c":[0,2,3],"8":[1,2,4,6],"89":2,"9":2,"A":3,"__init__":[1,3,5],"__name__":2,"__version__":6,"_backup":2,"_latest":3,"_success":[2,7],"activ":[3,6],"actual":0,"ag":[3,4,5,7],"agg":3,"aggregated_data":3,"aggregated_df":3,"alia":3,"alic":[0,3,4,5,7],"all":6,"amount":3,"api":[3,4,7],"api_data":4,"api\ub098":3,"append":[0,1,2,3,4],"arr":[0,4],"arrai":[0,4],"atio":[0,1,2,3,4,6,7],"atio_config":2,"atio_env":6,"atio_log_level":2,"atio_performance_monitor":2,"atio_temp_dir":2,"atio\ub294":[0,1,2,4,7],"atio\ub97c":[6,7],"atio\uc758":[0,1,2,3],"atom":[2,5],"auto":5,"automat":5,"avg_scor":3,"avg_valu":3,"avro":6,"axi":0,"b":[3,7],"backup_fil":2,"balanced_compress":3,"base":5,"base_path":3,"bash":6,"big_data":7,"bin":6,"block":6,"bob":[0,3,4,5,7],"bool":[1,5],"brotli":[1,3,4],"busan":[3,4,5,7],"bz2":4,"c":3,"cach":6,"categori":3,"charli":[0,3,4,5,7],"check_file_exist":[1,5],"choic":3,"citi":[3,4,5,7],"class":[1,3,4,5],"cleaned_data":0,"cleanup":5,"code":6,"col":3,"column":[1,4],"com":6,"comment":4,"complet":2,"compress":[1,2,3],"compression_set":3,"con":[0,1,3,4,5,7],"conda":5,"conda\ub97c":6,"config":2,"connection_uri":[0,1,4,5],"connectorx":[4,6],"continu":3,"core":5,"creat":6,"create_engin":[0,3,4,7],"css":4,"csv":[0,3,5,7],"csv\ub85c":4,"custom":[0,2],"custom_writ":[0,2],"d":3,"daegu":3,"daejeon":3,"dai":[0,1,2,3,5,7],"daily_process":0,"daily_stat":3,"dashboard":4,"dashboard_data":4,"data":[0,1,2,3,4,5,7],"data1":2,"data2":2,"data3":2,"databas":[0,1,5],"databaseerror":1,"datafram":[0,1,2,5,6],"dataframe\ub3c4":7,"dataframe\uc5d0":0,"dataframe\uc740":4,"datapipelin":3,"dataset":4,"date":3,"date_format":4,"date_rang":3,"datetim":[0,1,2,3,5],"david":0,"dbname":[0,4,7],"db\uc5d0":5,"debug":2,"debug_level":[1,5],"def":[0,2,3,4],"default":[1,5],"default_format":2,"delet":5,"deleted_count":[1,3],"delimit":4,"descript":[1,5],"dev_writ":2,"df":[0,1,2,3,4,5,6,7],"df_new":0,"diana":3,"dict":[1,5],"dir":6,"direct":5,"displai":5,"drop":0,"dropna":0,"dry":0,"dry_run":[0,1,2,5],"dt":3,"dump":[2,4],"e":[0,1,2,3,5],"easi":5,"els":2,"employe":3,"encod":[1,4],"end_tim":2,"engin":[0,1,3,4,7],"ensembl":0,"environ":2,"error":5,"etc":5,"etl":5,"ev":3,"event":[1,5],"excel":[3,5,6,7],"except":[0,1,2,3],"exist":[2,3],"exist_ok":[2,3],"experiment_result":4,"expire_snapshot":[0,2,3,5,7],"extract_data":3,"f":[0,1,2,3,4,6],"fail":[1,4],"fals":[0,1,2,3,4,5,7],"fast_compress":3,"fastavro":[4,6],"fastparquet":[1,6],"featur":[0,4],"file":[2,4,5],"file_info":3,"file_path":3,"file_s":[2,3],"filenam":3,"filepath":[1,5],"files_to_process":[2,3],"filter":3,"filtered_df":3,"final_data":4,"fit":0,"flag_fil":2,"fmt":[1,2,4,5],"forc":6,"format":[0,1,2,3,4,5,6,7],"freq":3,"from":[0,2,3,4,7],"function":5,"g":[1,5],"get":2,"get_writ":[1,5],"getsiz":[2,3],"gettempdir":2,"git":6,"github":6,"group_bi":3,"groupbi":3,"gzip":[1,2,3,4],"h":3,"handler":[1,2,5],"header":4,"headphon":3,"here":3,"high_compress":3,"hour":3,"html":5,"http":6,"i":2,"id":[0,1,3,4],"if_exist":[0,1,3,4,7],"ignore_index":3,"import":[0,1,2,3,4,5,6,7],"important_data":3,"importerror":1,"inact":3,"incheon":[3,4,5,7],"include_head":4,"indent":[2,4],"index":[1,2,3,4,7],"info":2,"initial_data":3,"initial_df":3,"instal":[4,6],"interfac":5,"intermediate_data":4,"intuit":5,"invalid_connect":0,"ioerror":1,"item":2,"json":[5,7],"json\uc73c\ub85c":4,"keep_for":[0,1,2,5],"keyboard":3,"kwarg":[0,1,2,4,5],"label":[0,4],"laptop":3,"larg":5,"large_data":[0,2,3],"large_dataset":[3,4],"large_df":[0,2,3,7],"latest":[1,7],"latest_data":0,"latest_df":3,"latest_path":3,"len":3,"linux":6,"listdir":3,"load":2,"load_data":3,"loc":3,"localhost":[0,3,4,7],"lz4":4,"lz4raw":4,"m":6,"maco":6,"makedir":2,"manag":5,"max":3,"mb":[2,3],"mean":3,"metadata":[0,4],"min":3,"mkdir":3,"mode":[0,1,2,5],"model":0,"model_select":0,"model_weight":4,"monitor":[3,5],"monthly_report":4,"mous":3,"multipl":5,"mydb":3,"n":[0,2,3,6],"na":1,"na_rep":1,"name":[0,1,3,4,5,7],"ndarrai":[1,5],"none":[1,2,4,5],"nosql":5,"now":3,"np":[0,1,2,3,4,5],"npy":[0,5],"npz":[0,5],"npz_compress":[0,4],"numpi":[1,2,3,5,6],"o":[2,3],"obj":[1,5],"obj_typ":[1,2,5],"object":[1,2],"occur":5,"old":5,"open":[0,2,4],"openpyxl":[1,4,6],"option":[1,5],"order":3,"order_d":3,"order_id":3,"orient":[1,4,7],"output":4,"output_a":[0,1,5],"overwrit":[1,2,5],"panda":[1,2,3,5,6,7],"pandas\uc640":0,"parquet":[0,2,3,5,6,7],"parquet_success":3,"pass":3,"password":[0,3,4,7],"path":[0,1,2,3,4,5],"pathlib":3,"pd":[0,1,2,3,4,5,6,7],"performance_test":2,"period":3,"permissionerror":0,"pickl":5,"pip":[4,6],"pipelin":3,"pkl":4,"pl":[0,3,4,7],"plugin":[0,2,4,5],"polar":[1,5,6],"polars_data":[0,3],"polars_df":[3,7],"polars\ub294":4,"polars\ub85c":0,"polars\ub97c":0,"postgresql":[0,4,7],"predict":0,"price":3,"print":[0,1,2,3,6],"process":5,"process_multiple_fil":3,"processed_data":[0,3],"processed_t":0,"product":3,"product_nam":3,"progress":[1,5],"progressbar":[1,5],"pyarrow":[1,6],"pypi\ub97c":5,"python":[4,5,6],"python3":6,"quantiti":3,"r":2,"rais":1,"randint":[0,4],"randn":[0,2,3,4],"random":[0,2,3,4],"randomforestclassifi":0,"rang":3,"raw_data":[0,3],"read_csv":0,"read_json":[1,5],"read_tabl":[0,3,5,7],"record":[1,4,7],"recoveri":5,"register_writ":[0,1,2,4,5],"reinstal":6,"remov":3,"replac":[0,1,2,3,4,7],"report_data":4,"respons":4,"result":4,"results_df":0,"return":[2,3],"rollback":5,"root":0,"round":3,"run":[0,1,5],"run_pipelin":3,"safe":5,"safe_data_process":3,"safe_load":2,"safe_writ":2,"salari":3,"sales_data":3,"sales_df":3,"sales_ord":3,"sampl":3,"score":3,"script":6,"self":3,"seojaeohcod":6,"seoul":[3,4,5,7],"sep":[1,4],"setup":2,"setup_logg":[1,5],"sheet1":[1,4],"sheet_nam":[1,3,4,7],"show_progress":[0,1,2,3,5,7],"simpl":5,"sklearn":0,"snappi":[1,2,3,4],"snapshot":5,"snapshot_id":[1,3,7],"snapshot_id_1":3,"snapshot_id_2":3,"sourc":[3,6],"source_data":0,"split":[1,4],"sql":[3,5,6,7],"sqlalchemi":[0,3,4,6,7],"ssd\ub97c":2,"start_tim":2,"startswith":3,"statu":3,"std":3,"step":2,"step1":4,"stop_ev":[1,5],"str":[1,3,5],"stripe":4,"success":[2,3],"success_flag":2,"successfulli":2,"support":5,"tabl":[1,4],"table_nam":[0,1,3,4,5],"table_path":[1,2,5],"target":0,"target_path":[1,5],"temp":2,"temp_dir":2,"temp_fil":3,"tempdir":2,"tempfil":2,"temporari":5,"test":[2,6],"test_config":2,"test_data":0,"test_siz":0,"text":3,"time":2,"timedelta":[0,1,2,3,5],"timestamp":3,"tmp":[2,3],"tmp12345":2,"tmpdir":2,"to_dict":4,"to_parquet":2,"to_sql":[1,5],"to_str":[0,2],"took":2,"total":2,"train":4,"train_test_split":0,"training_data":[0,4],"transform_data":3,"true":[0,1,2,3,4,5,7],"try":[0,1,2,3],"type":2,"uniform":3,"uninstal":6,"unknown":0,"upgrad":6,"uri":4,"us":5,"user":[0,1,3,4,5,6,7],"user_id":3,"usernam":3,"users_t":0,"utf":[1,4],"util":5,"valu":[0,1,3],"valueerror":[0,1],"var":2,"venv":6,"verbos":[0,1,2,3,5,7],"version":[0,1,5],"version_1_data":0,"w":[0,2,4],"warehous":0,"weight":4,"when":5,"window":6,"write":[0,2,3,4,5,6,7],"write_cal":2,"write_databas":[1,5],"write_json":[1,5],"write_snapshot":[0,2,3,5,7],"writer":2,"writer_map":2,"x_test":0,"x_train":0,"xlsx":[1,3,4,7],"xlsx2csv":[4,6],"xlsxwriter":[1,4,6],"xz":4,"y_test":0,"y_train":0,"yaml":4,"yaml_writ":4,"zstd":4,"\uac00":[1,5],"\uac00\ub3c5\uc131":4,"\uac00\uc0c1\ud658\uacbd":5,"\uac00\uc774\ub4dc":7,"\uac00\uc7a5":[4,6,7],"\uac00\uc838\uc634":3,"\uac00\uc911\uce58":4,"\uac01":[0,1,3,4,5],"\uac04\ub2e8\ud55c":[5,6,7],"\uac12":1,"\uac19\uc740":[0,1,2,7],"\uac1c":3,"\uac1c\ubc1c\uc6a9":2,"\uac1c\ubcc4\uc801\uc73c\ub85c":6,"\uac1d\uccb4":[1,4,5],"\uac1d\uccb4\uc758":[1,5],"\uac80\uc0c9":5,"\uac80\uc99d":5,"\uac83\uc785\ub2c8\ub2e4":6,"\uacb0\uacfc":4,"\uacb0\uacfc\ub97c":0,"\uacb0\uacfc\uc758":5,"\uacbd\uacfc":[1,2,5],"\uacbd\uacfc\ud55c":2,"\uacbd\ub7c9":5,"\uacbd\ub85c":[1,2,5],"\uacbd\ub85c\uc785\ub2c8\ub2e4":[1,5],"\uacbd\uc6b0":[1,2,6],"\uace0\uae09":[3,5,7],"\uacf5\uac04":4,"\uacf5\uac04\uc774":2,"\uacfc\uc815":0,"\uacfc\uc815\uc5d0\uc11c":5,"\uacfc\uc815\uc744":2,"\uad00\ub9ac":5,"\uad00\ub9ac\ub97c":[1,7],"\uad00\ub9ac\ud558\uc5ec":2,"\uad00\ub9ac\ud560":0,"\uad50\uccb4":[0,2,7],"\uad6c\ubd84\uc790":[1,4],"\uad6c\ubd84\uc790\uc640":4,"\uad6c\uc131":5,"\uad6c\uc870":4,"\uad6c\uc870\ud654":4,"\uad8c\uc7a5":[5,7],"\uad8c\uc7a5\ud569\ub2c8\ub2e4":[2,6],"\uad8c\ud55c":[0,6],"\uad8c\ud55c\uc774":[0,2],"\uade0\ud615":2,"\uadf8\ub300\ub85c":0,"\uae30\uac04":[1,5],"\uae30\ub2a5":6,"\uae30\ub2a5\ub4e4\uc744":0,"\uae30\ub2a5\uc744":[3,6],"\uae30\ub2a5\uc774":[1,5],"\uae30\ubc18":[1,4,5],"\uae30\ubcf8":[1,4,5,6],"\uae30\ubcf8\uac12":[1,2,4],"\uae30\ubcf8\uc801\uc73c\ub85c":2,"\uae30\uc874":2,"\ub0a0\uc9dc":4,"\ub0a8\uc544\uc788\ub294":2,"\ub290\ub9b0":4,"\ub294":5,"\ub2e4\ub8f9\ub2c8\ub2e4":0,"\ub2e4\uc591\ud55c":[0,2,3,4,5],"\ub2e4\uc6b4\uadf8\ub808\uc774\ub4dc":6,"\ub2e4\uc74c":5,"\ub2e4\uc74c\uacfc":[0,1,2,7],"\ub2e8\uacc4":5,"\ub2e8\uacc4\ubcc4":0,"\ub2e8\uc21c\ud55c":4,"\ub2e8\uc77c":4,"\ub300\uc2dc\ubcf4\ub4dc":4,"\ub300\uc6a9\ub7c9":[0,2,4,5,7],"\ub300\ud55c":[0,1],"\ub300\ud574":[0,2],"\ub354":[1,5],"\ub370\uc774\ud130":[0,1,2,5,7],"\ub370\uc774\ud130\uac00":[1,3,5],"\ub370\uc774\ud130\ub3c4":3,"\ub370\uc774\ud130\ub85c":0,"\ub370\uc774\ud130\ub97c":[0,1,3,5],"\ub370\uc774\ud130\ubca0\uc774\uc2a4":[1,4,5,6],"\ub370\uc774\ud130\ubca0\uc774\uc2a4\uc5d0":[0,1,3,4,5,7],"\ub370\uc774\ud130\ubca0\uc774\uc2a4\uc5d0\uc11c":3,"\ub370\uc774\ud130\uc5d0":2,"\ub370\uc774\ud130\uc758":0,"\ub3c5\ub9bd\uc801\uc778":6,"\ub3d9\uc791":[1,4],"\ub3d9\uc791\uc744":2,"\ub41c":[0,1,2],"\ub4e4\uc5ec\uc4f0\uae30":4,"\ub4e4\uc5ec\uc4f0\uae30\uc640":4,"\ub4f1":[1,5],"\ub4f1\ub85d":[1,4,5],"\ub4f1\ub85d\ub41c":2,"\ub4f1\ub85d\ud558\uc5ec":2,"\ub514\ub809\ud1a0\ub9ac":5,"\ub514\ub809\ud1a0\ub9ac\ub294":2,"\ub514\ub809\ud1a0\ub9ac\ub97c":2,"\ub514\ub809\ud1a0\ub9ac\uba85":1,"\ub514\ub809\ud1a0\ub9ac\uc5d0":0,"\ub514\uc2a4\ud06c":2,"\ub515\uc154\ub108\ub9ac":4,"\ub515\uc154\ub108\ub9ac\ub85c":[0,4],"\ub54c":4,"\ub610\ub294":[1,2,5,6],"\ub77c\uc774\ube0c\ub7ec\ub9ac":[1,4,5],"\ub77c\uc774\ube0c\ub7ec\ub9ac\uac00":6,"\ub77c\uc774\ube0c\ub7ec\ub9ac\uc640":4,"\ub77c\uc774\ube0c\ub7ec\ub9ac\uc785\ub2c8\ub2e4":[4,5],"\ub808\ubca8\ub85c":2,"\ub85c\uae45":5,"\ub85c\uae45\uc744":[0,2],"\ub85c\ub4dc":[0,3],"\ub85c\uc9c1":[0,2],"\ub864\ubc31":[0,1,5],"\ub864\ubc31\uc774":2,"\ub8e8\ud504":[1,5],"\ub97c":[1,5],"\ub9c9\ub300\ub97c":[1,5],"\ub9ce\uc740":4,"\ub9de\ub294":[1,5],"\ub9e4\uac1c\ubcc0\uc218":[1,5],"\ub9e4\uac1c\ubcc0\uc218\ub098":1,"\uba38\uc2e0\ub7ec\ub2dd":5,"\uba3c\uc800":7,"\uba54\uc778":[1,5],"\uba54\ud0c0\ub370\uc774\ud130\uc640":4,"\ubaa8\ub2c8\ud130\ub9c1":[1,5],"\ubaa8\ub378":[0,4],"\ubaa8\ub4c8":5,"\ubaa8\ub4dc\ub85c":0,"\ubaa8\ub4e0":[1,4],"\ubaa8\ubc94":5,"\ubaa9\ub85d":[3,5],"\ubabb\ud55c":1,"\ubb38\uc11c\uc785\ub2c8\ub2e4":1,"\ubb38\uc790":4,"\ubb38\uc81c":5,"\ubb38\uc81c\uac00":[2,6],"\ubc0f":[0,5],"\ubc18\ud658":1,"\ubc1c\uc0dd":[2,3],"\ubc1c\uc0dd\uc2dc\ud0ac":1,"\ubc1c\uc0dd\ud558\ub294":6,"\ubc29\ubc95\uc740":6,"\ubc29\ubc95\uc744":[2,6],"\ubc29\uc2dd":[1,4],"\ubc29\uc2dd\uc744":0,"\ubc29\ud5a5":1,"\ubc30\uc5f4":5,"\ubc30\uc5f4\ub85c":4,"\ubc30\uc5f4\uc740":4,"\ubc30\uc5f4\uc744":[0,4],"\ubc30\uc5f4\uc758":0,"\ubc30\uce58":[2,5],"\ubc31\uc5c5":0,"\ubc84\uc804":[1,5,7],"\ubc84\uc804\uc73c\ub85c":6,"\ubc84\uc804\uc744":[0,6],"\ubcc0\uc218":5,"\ubcc0\uc218\ub4e4\uc744":2,"\ubcc0\ud658":3,"\ubcc4\ub3c4":3,"\ubcd1\ubaa9\uc810":0,"\ubcf4\uad00":[1,5],"\ubcf4\uad00\ud560":1,"\ubcf4\ub2e4":[1,5],"\ubcf4\uc874":7,"\ubcf4\uc874\ub418\uc5c8\uc2b5\ub2c8\ub2e4":3,"\ubcf4\uc874\ub428":0,"\ubcf4\uc874\ub429\ub2c8\ub2e4":2,"\ubcf5\uad6c":5,"\ubcf5\uc7a1\ub3c4":4,"\ubcf5\uc7a1\ud55c":4,"\ubd84\uc11d":0,"\ubd84\ud560":0,"\ubd84\ud560\ub41c":0,"\ube44\uad50":3,"\ube44\uad50\ud574\ubcf4\uaca0\uc2b5\ub2c8\ub2e4":4,"\ube44\ud65c\uc131\ud654":2,"\ube45\ub370\uc774\ud130":4,"\ube60\ub978":[2,4],"\uc0ac\ub840\uc640":3,"\uc0ac\uc6a9":[1,7],"\uc0ac\uc6a9\ub418\uc9c0":[1,5],"\uc0ac\uc6a9\ubc95":[1,5],"\uc0ac\uc6a9\ubc95\ubd80\ud130":7,"\uc0ac\uc6a9\ubc95\uc744":4,"\uc0ac\uc6a9\uc744":6,"\uc0ac\uc6a9\ud558\ub294":6,"\uc0ac\uc6a9\ud558\ub824\uba74":6,"\uc0ac\uc6a9\ud558\uc138\uc694":4,"\uc0ac\uc6a9\ud558\uc5ec":[0,7],"\uc0ac\uc6a9\ud560":2,"\uc0ac\uc6a9\ud569\ub2c8\ub2e4":2,"\uc0ad\uc81c":[0,2],"\uc0ad\uc81c\ub41c":[1,3],"\uc0ad\uc81c\ub429\ub2c8\ub2e4":2,"\uc0ad\uc81c\ud569\ub2c8\ub2e4":[1,5],"\uc0b4\ud3b4\ubcf4\uc138\uc694":3,"\uc0c1\ub300\uc801\uc73c\ub85c":4,"\uc0c1\uc138":1,"\uc0c1\uc138\ud55c":[0,1,2,5,7],"\uc0c1\ud0dc\ub97c":2,"\uc0c1\ud669\uc5d0":[0,2],"\uc0c1\ud669\uc744":[0,1,2,5],"\uc0c8\ub85c\uc6b4":[0,2,4],"\uc0c9\uc778":5,"\uc0d8\ud50c":[3,7],"\uc0dd\uc131":[0,1,2,3,5,6,7],"\uc0dd\uc131\ub418\uc5c8\uc2b5\ub2c8\ub2e4":3,"\uc0dd\uc131\ub41c":1,"\uc0dd\uc131\ud558\uc5ec":1,"\uc0dd\uc131\ud569\ub2c8\ub2e4":2,"\uc0dd\ud0dc\uacc4":4,"\uc124\uba85\ud569\ub2c8\ub2e4":[2,4],"\uc124\uc815":5,"\uc124\uc815\ub41c":[1,5],"\uc124\uc815\uc5d0":2,"\uc124\uc815\uc73c\ub85c":3,"\uc124\uc815\uc744":2,"\uc124\uc815\uc774":2,"\uc124\uc815\ud560":2,"\uc124\uce58":[5,7],"\uc124\uce58\uac00":6,"\uc124\uce58\ub418\uc9c0":1,"\uc124\uce58\ud558\ub294":6,"\uc124\uce58\ud558\ub824\uba74":6,"\uc131\uacf5":2,"\uc131\uacf5\uc801\uc73c\ub85c":[2,6],"\uc131\ub2a5":[1,5],"\uc131\ub2a5\uc744":2,"\uc139\uc158\uc5d0\uc11c\ub294":0,"\uc18c\uc2a4":[1,5],"\uc18c\uc694":0,"\uc18d\ub3c4":[1,2,5],"\uc190\uc0c1":5,"\uc218":[0,1,2,3,5,7],"\uc218\ub3c4":7,"\uc218\ub3d9":2,"\uc218\ub3d9\uc73c\ub85c":2,"\uc218\uce58":4,"\uc218\ud589\ub429\ub2c8\ub2e4":2,"\uc218\ud589\ud558\ub294":1,"\uc218\ud589\ud569\ub2c8\ub2e4":[1,5],"\uc22b\uc790":4,"\uc27d\uac8c":0,"\uc2a4\ub0c5\uc0f7":[1,5],"\uc2a4\ub0c5\uc0f7\uacfc":[1,5],"\uc2a4\ub0c5\uc0f7\uc5d0\uc11c":1,"\uc2a4\ub0c5\uc0f7\uc73c\ub85c":0,"\uc2a4\ub0c5\uc0f7\uc744":1,"\uc2a4\ub808\ub4dc\uc5d0\uc11c":[1,5],"\uc2a4\ud0c0\uc77c\uacfc":4,"\uc2a4\ud53c\ub108":[1,2,5],"\uc2dc":[0,1,2,5,7],"\uc2dc\uac01\uc801\uc73c\ub85c":2,"\uc2dc\uac04":[0,2],"\uc2dc\uac04\ubcc4":3,"\uc2dc\uac04\uc744":[1,5],"\uc2dc\ub3c4":0,"\uc2dc\ubbac\ub808\uc774\uc158":3,"\uc2dc\uc2a4\ud15c":[1,5],"\uc2dc\uc2a4\ud15c\uc5d0\uc11c":4,"\uc2dc\uc2a4\ud15c\uc744":[0,4],"\uc2dc\uc2a4\ud15c\uc758":2,"\uc2dc\uc5d0\ub294":2,"\uc2dc\uc791":[2,3],"\uc2dc\uc791\ud574\ubcf4\uaca0\uc2b5\ub2c8\ub2e4":7,"\uc2dc\uc791\ud574\ubcf4\uc138\uc694":7,"\uc2dc\ud2b8":[1,4],"\uc2dc\ud2b8\uba85\uacfc":4,"\uc2e4\uc2dc\uac04\uc73c\ub85c":[0,2],"\uc2e4\uc81c":[2,5],"\uc2e4\uc81c\ub85c\ub294":3,"\uc2e4\ud328":[2,3,7],"\uc2e4\ud328\ud588\uc2b5\ub2c8\ub2e4":2,"\uc2e4\ud589":[0,3],"\uc2e4\ud589\ub429\ub2c8\ub2e4":[1,5],"\uc2e4\ud589\ud558\ub294":[1,5],"\uc2e4\ud5d8":[4,5],"\uc30d\uc73c\ub85c":[1,5],"\uc4f0\uae30":[1,2,4,5,7],"\uc4f0\uae30\ub97c":[1,4,5,7],"\uc4f0\uae30\uc5d0":[1,5],"\uc544\ud0a4\ud14d\ucc98\ub97c":0,"\uc548\ub0b4\ud569\ub2c8\ub2e4":6,"\uc548\uc804\uc7a5\uce58\ub97c":7,"\uc548\uc804\ud558\uac8c":[0,1,2,3,5],"\uc548\uc804\ud558\uace0":5,"\uc548\uc804\ud55c":[1,5,7],"\uc54a\ub294":[0,1,5],"\uc54a\uc2b5\ub2c8\ub2e4":[1,5],"\uc54a\uc558\uac70\ub098":2,"\uc54a\uc558\uc2b5\ub2c8\ub2e4":2,"\uc54a\uc740":[1,4],"\uc555\ucd95":[1,4],"\uc555\ucd95\uacfc":4,"\uc555\ucd95\ub418\uc9c0":4,"\uc555\ucd95\ub41c":[0,4],"\uc555\ucd95\uc73c\ub85c":3,"\uc591":2,"\uc5c5\uadf8\ub808\uc774\ub4dc":5,"\uc5c5\ub370\uc774\ud2b8":[0,3],"\uc5c5\ub370\uc774\ud2b8\ub41c":3,"\uc5c6\ub294":0,"\uc5c6\uc74c":2,"\uc5c6\uc74c\uc73c\ub85c":2,"\uc5c6\uc774":5,"\uc5d0\ub7ec":5,"\uc5d1\uc140":4,"\uc5d4\uc9c4":[1,4],"\uc5ec\ub7ec":4,"\uc5ec\ubd80":[1,2,4,5],"\uc5f0\uacb0":[0,1,3,4,7],"\uc5f0\ub3d9":5,"\uc608":4,"\uc608\uc0c1\uce58":1,"\uc608\uc2dc":2,"\uc608\uc678":5,"\uc608\uc678\ub97c":1,"\uc608\uc81c":[1,5,7],"\uc608\uce21":0,"\uc624\ub798\ub41c":[1,3,5,7],"\uc624\ub958":[1,3,6],"\uc62c\ubc14\ub974\uac8c":2,"\uc635\uc158":4,"\uc635\uc158\uacfc":[2,4],"\uc635\uc158\uc73c\ub85c":4,"\uc635\uc158\uc744":2,"\uc644\ub8cc":[3,5,7],"\uc644\ub8cc\ub418\uc5c8\ub294\uc9c0":6,"\uc644\ub8cc\ub418\uc5c8\uc2b5\ub2c8\ub2e4":[2,6],"\uc644\ub8cc\ub418\uc9c0":2,"\uc644\ub8cc\ub97c":2,"\uc6a9\ub7c9":[1,2,5],"\uc6b0\uc120":2,"\uc6d0\ubcf8":[0,2,3,7],"\uc6d0\uc790\uc801":[1,2,5],"\uc6d0\uc790\uc801\uc73c\ub85c":7,"\uc6d0\uc790\uc801\uc778":5,"\uc704\ud55c":[0,2,4,7],"\uc704\ud574":[2,4,6],"\uc720\uc9c0\ud558\uae30":6,"\uc720\uc9c0\ud560":2,"\uc751\ub2f5":4,"\uc758\uc874\uc131":5,"\uc774":[0,1,5,7],"\uc774\ub97c":0,"\uc774\ub984":[1,4],"\uc774\uc0c1":[0,1,2,3,5],"\uc778\ub371\uc2a4":[1,2,4],"\uc778\ub371\uc2a4\ub97c":4,"\uc778\uc790":[1,5],"\uc778\uc790\ub4e4\uc785\ub2c8\ub2e4":[1,5],"\uc778\ucf54\ub529":[1,4],"\uc77c\uad00\ub41c":2,"\uc77c\ubcc4":3,"\uc77c\uc218":1,"\uc77d\uae30":[1,2,3,4,7],"\uc77d\uc5b4\uc635\ub2c8\ub2e4":1,"\uc77d\uc744":1,"\uc784\uc2dc":[0,3,5,7],"\uc788\ub294":[0,1,2,5],"\uc788\ub294\uc9c0":3,"\uc788\uc2b5\ub2c8\ub2e4":[0,1,2,5,7],"\uc788\uc5b4\uc57c":2,"\uc788\uc744":2,"\uc790\ub3d9\uc73c\ub85c":2,"\uc791\ub3d9\ud569\ub2c8\ub2e4":2,"\uc791\uc5c5":2,"\uc791\uc740":4,"\uc798\ubabb\ub41c":[0,1],"\uc7ac\ucc98\ub9ac":2,"\uc800\uc7a5":[1,2,4,5],"\uc800\uc7a5\ub418\uc5c8\uc2b5\ub2c8\ub2e4":3,"\uc800\uc7a5\ub41c":2,"\uc800\uc7a5\ub420":[1,5],"\uc800\uc7a5\uc774":2,"\uc800\uc7a5\ud560":[0,1,5,7],"\uc800\uc7a5\ud569\ub2c8\ub2e4":[1,5],"\uc801\uc6a9":[1,2,5],"\uc801\uc6a9\ub418\uc5c8\ub294\uc9c0":2,"\uc804":2,"\uc804\ub2ec\ub420":[1,5],"\uc804\uc6a9":2,"\uc804\ucc98\ub9ac":0,"\uc804\ucc98\ub9ac\ub41c":0,"\uc804\uccb4":7,"\uc808\uc57d":[2,4],"\uc815\ub9ac":[1,3,7],"\uc815\ub9ac\ub41c":3,"\uc815\ub9ac\ub429\ub2c8\ub2e4":2,"\uc815\ub9ac\ud569\ub2c8\ub2e4":1,"\uc815\ubcf4":[0,1,2,5,7],"\uc815\ubcf4\ub97c":[0,2,7],"\uc815\uc81c":0,"\uc815\uc81c\ub41c":0,"\uc81c\uac70":5,"\uc81c\uac70\ud558\ub824\uba74":6,"\uc81c\uacf5\ud569\ub2c8\ub2e4":[0,2,7],"\uc81c\uc5b4\ud558\ub294":2,"\uc81c\uc678\ub85c":2,"\uc81c\ud55c\uc801":4,"\uc870\ud68c":[1,5],"\uc874\uc7ac":1,"\uc874\uc7ac\ud560":4,"\uc874\uc7ac\ud569\ub2c8\ub2e4":[2,3],"\uc88b\uc740":4,"\uc8fc\uc11d":4,"\uc8fc\uc758\uc0ac\ud56d":2,"\uc911":[3,6],"\uc911\uac04":[4,5],"\uc9c0\uc6d0":[1,4,5,6],"\uc9c0\uc6d0\ud558\uc9c0":0,"\uc9c0\uc6d0\ud560":2,"\uc9c0\uc6d0\ud569\ub2c8\ub2e4":[0,4,7],"\uc9c0\uc815":4,"\uc9c1\uc811":7,"\uc9c4\ub2e8":[1,5],"\uc9c4\ub2e8\uc744":0,"\uc9c4\ud589":[0,1,2,5],"\uc9c4\ud589\ub3c4":[1,5],"\uc9c4\ud589\ub960":[1,5],"\uc9c4\ud589\ub960\uc744":7,"\uc9d1\uacc4":3,"\ucc38\uc870":7,"\ucc38\uc870\ub418\uc9c0":[1,5],"\ucc98\ub9ac":[5,7],"\ucc98\ub9ac\uac00":2,"\ucc98\ub9ac\ub418\ub294":2,"\ucc98\ub9ac\ub41c":[1,3,5],"\ucc98\ub9ac\ub97c":4,"\ucc98\ub9ac\uc5d0":4,"\ucc98\ub9ac\uc5d0\uc11c":2,"\ucc98\ub9ac\ud560":3,"\ucc98\ub9ac\ud569\ub2c8\ub2e4":[0,2],"\ucd08":2,"\ucd08\uae30":3,"\ucd08\ub2f9":2,"\ucd5c\uace0":4,"\ucd5c\uc2e0":[0,1,3,6],"\ucd5c\uc801\ud654":5,"\ucd5c\uc801\ud654\ub41c":4,"\ucd5c\uc885":4,"\ucd94\uac00":[0,1,2,4,5,6],"\ucd94\uac00\ud558\ub824\uba74":4,"\ucd94\uac00\ud560":0,"\ucd94\uc801\ud560":2,"\ucd94\ucd9c":3,"\ucd94\ucd9c\ub41c":3,"\ucd9c\ub825":[0,1,2,5,7],"\ucda9\ub3cc":6,"\ucda9\ubd84\ud55c":2,"\uce21\uc815":2,"\uce90\uc2dc":6,"\ucee4\ub125\uc158":[1,5],"\ucee4\uc2a4\ud140":[2,4],"\uceec\ub7fc":4,"\uceec\ub7fc\uc73c\ub85c":4,"\ucf54\ub4dc\ub294":7,"\ucf58\uc194\uc5d0":[1,5],"\ud06c\uae30":[2,3,4],"\ud070":4,"\ud074\ub798\uc2a4":[1,4,5],"\ud074\ub798\uc2a4\uc5d0":1,"\ud0a4\uc6cc\ub4dc":[1,5],"\ud0c0\uc785":[1,5],"\ud0c0\uc785\uacfc":[1,5],"\ud14c\uc2a4\ud2b8":[0,6],"\ud14c\uc774\ube14":[1,4],"\ud14c\uc774\ube14\ub85c":4,"\ud14c\uc774\ube14\uba85":[1,5],"\ud14c\uc774\ube14\uc774":4,"\ud14d\uc2a4\ud2b8":4,"\ud1b5\uacc4":3,"\ud1b5\ud55c":5,"\ud1b5\ud574":[0,2],"\ud2b8\ub79c\uc7ad\uc158\ucc98\ub7fc":5,"\ud2b9\uc131\uc744":4,"\ud2b9\uc815":[0,1,3],"\ud2b9\uc9d5":4,"\ud2b9\ud654":4,"\ud30c\uc774\ud504\ub77c\uc778":5,"\ud30c\uc77c":[1,7],"\ud30c\uc77c\ub85c":[0,2,4],"\ud30c\uc77c\ubcc4":4,"\ud30c\uc77c\uc5d0":[2,4,7],"\ud30c\uc77c\uc740":[0,2],"\ud30c\uc77c\uc744":[1,2,3,5],"\ud30c\uc77c\uc758":5,"\ud30c\uc77c\uc774":[2,3],"\ud328\ud0a4\uc9c0\uac00":1,"\ud398\uc774\uc9c0":5,"\ud3ec\ub9f7":[1,5],"\ud3ec\ub9f7\uc5d0":[1,5],"\ud3ec\ud568":[1,4],"\ud45c\uc2dc":[1,5],"\ud45c\uc2dc\ub294":2,"\ud45c\uc2dc\uc640":[0,2,5],"\ud45c\uc2dc\ud558\ub294":[1,5],"\ud45c\uc2dc\ud569\ub2c8\ub2e4":[1,5],"\ud45c\uc900":4,"\ud45c\ud604":1,"\ud504\ub85c\uc81d\ud2b8\ubcc4\ub85c":6,"\ud50c\ub798\uadf8":[5,7],"\ud50c\ub798\uadf8\uac00":3,"\ud50c\ub7ec\uadf8\uc778":[4,5],"\ud50c\ub7ec\uadf8\uc778\uc744":2,"\ud544\uc218":[1,4,5],"\ud544\uc218\uc785\ub2c8\ub2e4":[1,5],"\ud544\uc694":4,"\ud544\uc694\ud55c":[1,5],"\ud544\uc694\ud560":2,"\ud544\uc694\ud569\ub2c8\ub2e4":6,"\ud558\ub098\uc758":4,"\ud559\uc2b5":[0,4],"\ud560":5,"\ud568\uaed8":[0,2,4,5],"\ud568\uc218":5,"\ud568\uc218\uac00":[1,5],"\ud568\uc218\uc5d0":[1,5],"\ud568\uc218\uc640":1,"\ud568\uc218\uc785\ub2c8\ub2e4":1,"\ud569\ub2c8\ub2e4":2,"\ud574\uacb0":5,"\ud578\ub4e4\ub7ec\ub97c":[1,5],"\ud589":3,"\ud5e4\ub354":4,"\ud604\ub300\uc801\uc778":4,"\ud604\uc7ac\uae4c\uc9c0":2,"\ud615\uc2dd":[2,6],"\ud615\uc2dd\ubcc4":1,"\ud615\uc2dd\ubcc4\ub85c":4,"\ud615\uc2dd\uc73c\ub85c":[3,4],"\ud615\uc2dd\uc744":[0,2,4,6,7],"\ud615\uc2dd\uc758":4,"\ud615\ud0dc\ub85c":4,"\ud638\ud658\uc131\uc744":4,"\ud655\uc778":[3,5],"\ud655\uc778\uc774":2,"\ud655\uc778\ud558\ub294":2,"\ud655\uc778\ud558\ub824\uba74":[6,7],"\ud655\uc778\ud560":[0,2,7],"\ud655\uc7a5":5,"\ud658\uacbd":[4,5],"\ud658\uacbd\uc744":[2,6],"\ud65c\uc131\ud654":[2,3,6,7],"\ud65c\uc131\ud654\ud560":0,"\ud65c\uc6a9":5,"\ud6a8\uc728\uc801\uc73c\ub85c":4,"\ud6a8\uc728\uc801\uc778":2,"\ud6c4":[1,2,3,5,7]},"titles":["\uace0\uae09 \uc0ac\uc6a9\ubc95","API \ucc38\uc870","\uc124\uc815 \ubc0f \uad6c\uc131","\uc0ac\uc6a9 \uc608\uc81c","\uc9c0\uc6d0\ud558\ub294 \ud30c\uc77c \ud615\uc2dd","Atio Documentation","\uc124\uce58 \uac00\uc774\ub4dc","\ube60\ub978 \uc2dc\uc791"],"titleterms":{"api":[1,5],"arrow":4,"atio":5,"avro":4,"binari":4,"comma":4,"compress":4,"conda":6,"core":1,"csv":[1,4],"databas":4,"datafram":[3,4,7],"document":5,"etl":0,"excel":[1,4],"expire_snapshot":1,"html":4,"indic":5,"ipc":4,"json":[1,2,4],"npy":4,"npz":4,"numpi":[0,4],"panda":[0,4],"parquet":[1,4],"pickl":4,"plugin":1,"polar":[0,3,4,7],"postgresql":3,"pypi\ub97c":6,"read_tabl":1,"refer":5,"separ":4,"sql":[0,1,4],"tabl":5,"util":1,"valu":4,"write":1,"write_snapshot":1,"yaml":2,"\uac00\uc0c1\ud658\uacbd":6,"\uac00\uc774\ub4dc":[5,6],"\uac04\ub2e8\ud55c":3,"\uac1c\ubc1c":[2,6],"\uac80\uc99d":2,"\uace0\uae09":0,"\uace0\uc131\ub2a5":3,"\uad00\ub9ac":[0,2,3],"\uad6c\uc131":2,"\uad8c\uc7a5":[4,6],"\uae30\ub2a5":[5,7],"\uae30\ubc18":[0,3],"\uae30\ubcf8":[0,2,3,7],"\ub2e4\uc591\ud55c":7,"\ub2e4\uc74c":7,"\ub2e8\uacc4":7,"\ub2e8\uc77c":0,"\ub300\uc6a9\ub7c9":3,"\ub370\uc774\ud130":[3,4],"\ub370\uc774\ud130\ubca0\uc774\uc2a4":[0,3,7],"\ub3d9\uc2dc":3,"\ub3d9\uc791":2,"\ub4f1\ub85d":[0,2],"\ub514\ub809\ud1a0\ub9ac":2,"\ub808\ubca8":2,"\ub85c\uae45":[0,2],"\ub864\ubc31":2,"\uba38\uc2e0\ub7ec\ub2dd":[0,4],"\uba54\ubaa8\ub9ac":2,"\ubaa8\ub2c8\ud130\ub9c1":[2,3,7],"\ubaa8\ub4c8":1,"\ubaa8\ub4dc":2,"\ubaa8\ub4e0":6,"\ubaa8\ubc94":2,"\ubaa9\ucc28":5,"\ubb38\uc81c":6,"\ubc0f":[2,3,4],"\ubc30\uc5f4":[0,4],"\ubc30\uce58":3,"\ubc31\uc5c5":2,"\ubc84\uc804":[0,3,6],"\ubcc0\uc218":2,"\ubcf4\uace0\uc11c":4,"\ubcf5\uad6c":3,"\ubd84\uc11d":4,"\ube44\uad50":4,"\ube44\uc988\ub2c8\uc2a4":4,"\ube60\ub978":[5,7],"\uc0ac\ub840":[0,2,3,4,5],"\uc0ac\uc6a9":[0,2,3,4,5,6],"\uc0ac\uc6a9\ub7c9":2,"\uc0ac\uc6a9\ubc95":[0,7],"\uc0ac\uc6a9\uc790":[2,5],"\uc0c1\uc138":[0,2],"\uc120\ud0dd\uc801":6,"\uc124\uc815":[2,3],"\uc124\uce58":6,"\uc131\ub2a5":[0,2,3,4,7],"\uc18d\ub3c4":4,"\uc2a4\ub0c5\uc0f7":[0,2,3,7],"\uc2dc\uc2a4\ud15c":[0,2],"\uc2dc\uc791":[5,7],"\uc2e4\uc81c":[0,3],"\uc4f0\uae30":0,"\uc548\uc804\ud55c":3,"\uc555\ucd95":[2,3],"\uc560\ud50c\ub9ac\ucf00\uc774\uc158":4,"\uc5c5\uadf8\ub808\uc774\ub4dc":6,"\uc5d0\ub7ec":[0,2,3],"\uc5ec\ub7ec":[0,3],"\uc5f0\ub3d9":[0,3],"\uc608\uc678":1,"\uc608\uc81c":3,"\uc635\uc158":2,"\uc644\ub8cc":2,"\uc6a9\ub7c9":4,"\uc6f9":4,"\uc758\uc874\uc131":6,"\uc77d\uae30":0,"\uc784\uc2dc":2,"\uc800\uc7a5":[0,3,7],"\uc815\ub9ac":[0,2],"\uc815\uc758":2,"\uc81c\uac70":6,"\uc8fc\uc694":[1,5],"\uc9c0\uc6d0":7,"\uc9c0\uc6d0\ud558\ub294":[1,4,5],"\uc9c4\ud589\ub3c4":[0,2],"\uc9c4\ud589\ub960":[3,7],"\ucc38\uc870":[1,5],"\ucc98\ub9ac":[0,1,2,3],"\ucd5c\uc801\ud654":[0,2,3],"\ucee4\uc2a4\ud140":0,"\ud14c\uc2a4\ud2b8":2,"\ud1b5\ud55c":6,"\ud2b9\uc815":6,"\ud30c\uc774\ud504\ub77c\uc778":[0,3,4],"\ud30c\uc77c":[0,2,3,4,5],"\ud3ec\ub9f7":0,"\ud45c\uc2dc":[0,2,7],"\ud45c\uc2dc\uc640":3,"\ud504\ub85c\ub355\uc158":2,"\ud50c\ub798\uadf8":2,"\ud50c\ub7ec\uadf8\uc778":[0,2],"\ud544\uc218":6,"\ud568\uc218":1,"\ud568\uc218\ub4e4":5,"\ud574\uacb0":6,"\ud575\uc2ec":5,"\ud615\uc2dd":[0,1,4,5,7],"\ud615\uc2dd\ubcc4":4,"\ud638\ud658\uc131":4,"\ud655\uc778":[2,6],"\ud655\uc7a5":0,"\ud655\uc7a5\ud558\uae30":4,"\ud658\uacbd":[2,6],"\ud65c\uc6a9":[2,3]}}) \ No newline at end of file