chrisbase
Advanced tools
+2
-1
| Metadata-Version: 2.1 | ||
| Name: chrisbase | ||
| Version: 0.5.4 | ||
| Version: 0.5.5 | ||
| Summary: Base library for python coding | ||
@@ -24,2 +24,3 @@ Home-page: https://github.com/chrisjihee/chrisbase | ||
| Requires-Dist: pymongo | ||
| Requires-Dist: pydantic | ||
| Requires-Dist: openpyxl | ||
@@ -26,0 +27,0 @@ Requires-Dist: tabulate |
+2
-1
| [metadata] | ||
| name = chrisbase | ||
| version = 0.5.4 | ||
| version = 0.5.5 | ||
| author = Jihee Ryu | ||
@@ -33,2 +33,3 @@ author_email = chrisjihee@naver.com | ||
| pymongo | ||
| pydantic | ||
| openpyxl | ||
@@ -35,0 +36,0 @@ tabulate |
| Metadata-Version: 2.1 | ||
| Name: chrisbase | ||
| Version: 0.5.4 | ||
| Version: 0.5.5 | ||
| Summary: Base library for python coding | ||
@@ -24,2 +24,3 @@ Home-page: https://github.com/chrisjihee/chrisbase | ||
| Requires-Dist: pymongo | ||
| Requires-Dist: pydantic | ||
| Requires-Dist: openpyxl | ||
@@ -26,0 +27,0 @@ Requires-Dist: tabulate |
@@ -8,2 +8,3 @@ tqdm | ||
| pymongo | ||
| pydantic | ||
| openpyxl | ||
@@ -10,0 +11,0 @@ tabulate |
+44
-32
@@ -24,3 +24,3 @@ import json | ||
| from chrisbase.io import get_hostname, get_hostaddr, current_file, first_or, cwd, hr, flush_or, make_parent_dir, get_ip_addrs, setup_unit_logger, setup_dual_logger, open_file, file_lines, to_table_lines | ||
| from chrisbase.io import get_hostname, get_hostaddr, current_file, first_or, cwd, hr, flush_or, make_parent_dir, get_ip_addrs, setup_unit_logger, setup_dual_logger, open_file, file_lines, to_table_lines, new_path | ||
| from chrisbase.time import now, str_delta | ||
@@ -75,3 +75,3 @@ from chrisbase.util import tupled, SP, NO, to_dataframe | ||
| reset: bool = field(default=False) | ||
| strict: bool = field(default=False) | ||
| required: bool = field(default=False) | ||
@@ -99,3 +99,3 @@ def __post_init__(self): | ||
| find: dict = field(default_factory=dict) | ||
| timeout: int = field(default=5000) | ||
| timeout: int = field(default=30 * 1000) | ||
@@ -134,4 +134,4 @@ | ||
| self.reset() | ||
| elif self.opt.strict: | ||
| assert self.usable(), f"Could not open source: opt={self.opt}" | ||
| elif self.opt.required: | ||
| assert self.usable(), f"Could not open source: {self.opt}" | ||
| return self | ||
@@ -238,3 +238,3 @@ | ||
| if "w" in self.opt.mode or "a" in self.opt.mode: | ||
| self.path.touch() | ||
| make_parent_dir(self.path).touch() | ||
| if self.path.exists() and self.path.is_file(): | ||
@@ -261,2 +261,3 @@ self.fp = open_file( | ||
| self.table: pymongo.collection.Collection | None = None | ||
| self.server_info: dict | None = None | ||
@@ -289,2 +290,6 @@ def __exit__(self, *exc_info): | ||
| self.cli = MongoClient(f"mongodb://{db_addr}/?timeoutMS={self.opt.timeout}") | ||
| try: | ||
| self.server_info = self.cli.server_info() | ||
| except pymongo.errors.ServerSelectionTimeoutError: | ||
| raise AssertionError(f"Could not connect to MongoDB: {self.opt.home}") | ||
| self.db = self.cli.get_database(db_name) | ||
@@ -299,8 +304,8 @@ self.table = self.db.get_collection(f"{self.opt.name}") | ||
| def count(self, query: Mapping[str, Any], exact: bool = False) -> int: | ||
| def count(self, query: Mapping[str, Any] = None) -> int: | ||
| if self.usable(): | ||
| if exact: | ||
| if not query: | ||
| return self.table.estimated_document_count() | ||
| else: | ||
| return self.table.count_documents(query) | ||
| else: | ||
| return self.table.estimated_document_count() | ||
| else: | ||
@@ -390,2 +395,3 @@ return -1 | ||
| inter: int = field(default=10000) | ||
| total: int = field(default=-1) | ||
| data: Iterable | None = field(default=None) | ||
@@ -398,3 +404,3 @@ file: FileOption | None = field(default=None) | ||
| class InputItems: | ||
| total: int | ||
| num_item: int | ||
@@ -436,14 +442,18 @@ @property | ||
| def ready_inputs(self, inputs: Iterable, total: int, str_to_dict: bool = False) -> "InputOption.SingleItems | InputOption.BatchItems": | ||
| def ready_inputs(self, inputs: Iterable, total: int = None, str_to_dict: bool = False) -> "InputOption.SingleItems | InputOption.BatchItems": | ||
| if str_to_dict: | ||
| inputs = map(self.safe_dict, inputs) | ||
| if total and total > 0: | ||
| self.total = total | ||
| num_item = max(0, self.total) | ||
| assert num_item > 0, f"Invalid total: num_item={num_item}, total={total}, self.total={self.total}" | ||
| if self.start > 0: | ||
| inputs = islice(inputs, self.start, total) | ||
| total = max(0, min(total, total - self.start)) | ||
| inputs = islice(inputs, self.start, self.total) | ||
| num_item = max(0, min(num_item, num_item - self.start)) | ||
| if self.limit > 0: | ||
| inputs = islice(inputs, self.limit) | ||
| total = min(total, self.limit) | ||
| num_item = min(num_item, self.limit) | ||
| if self.batch <= 1: | ||
| return InputOption.SingleItems( | ||
| total=total, | ||
| num_item=num_item, | ||
| singles=inputs, | ||
@@ -453,3 +463,3 @@ ) | ||
| return InputOption.BatchItems( | ||
| total=math.ceil(total / self.batch), | ||
| num_item=math.ceil(num_item / self.batch), | ||
| batches=ichunked(inputs, self.batch), | ||
@@ -484,8 +494,8 @@ ) | ||
| debugging: bool = field(default=False) | ||
| msg_level: int = field(default=logging.INFO) | ||
| msg_format: str = field(default=logging.BASIC_FORMAT) | ||
| date_format: str = field(default="[%m.%d %H:%M:%S]") | ||
| output_home: str | Path | None = field(default=None) | ||
| logging_home: str | Path | None = field(default=None) | ||
| logging_file: str | Path | None = field(default=None) | ||
| argument_file: str | Path | None = field(default=None) | ||
| date_format: str = field(default="[%m.%d %H:%M:%S]") | ||
| message_level: int = field(default=logging.INFO) | ||
| message_format: str = field(default=logging.BASIC_FORMAT) | ||
@@ -503,5 +513,5 @@ def __post_init__(self): | ||
| self.ip_addrs, self.num_ip_addrs = get_ip_addrs() | ||
| self.output_home = Path(self.output_home).absolute() if self.output_home else None | ||
| self.logging_file = Path(self.logging_file) if self.logging_file else None | ||
| self.argument_file = Path(self.argument_file) if self.argument_file else None | ||
| self.logging_home = Path(self.logging_home).absolute() if self.logging_home else None | ||
| self.logging_file = new_path(self.logging_file, post=self.time_stamp) if self.logging_file else None | ||
| self.argument_file = new_path(self.argument_file, post=self.time_stamp) if self.argument_file else None | ||
| self._setup_logger() | ||
@@ -515,6 +525,6 @@ | ||
| def _setup_logger(self): | ||
| if self.output_home and self.logging_file: | ||
| setup_dual_logger(level=self.msg_level, fmt=self.msg_format, datefmt=self.date_format, stream=sys.stdout, filename=self.output_home / self.logging_file) | ||
| if self.logging_home and self.logging_file: | ||
| setup_dual_logger(level=self.message_level, fmt=self.message_format, datefmt=self.date_format, stream=sys.stdout, filename=self.logging_home / self.logging_file) | ||
| else: | ||
| setup_unit_logger(level=self.msg_level, fmt=self.msg_format, datefmt=self.date_format, stream=sys.stdout) | ||
| setup_unit_logger(level=self.message_level, fmt=self.message_format, datefmt=self.date_format, stream=sys.stdout) | ||
| return self | ||
@@ -526,7 +536,7 @@ | ||
| def set_output_home(self, output_home: str | Path | None, absolute: bool = False): | ||
| def set_logging_home(self, output_home: str | Path | None, absolute: bool = False): | ||
| if absolute: | ||
| self.output_home = Path(output_home).absolute() if output_home else None | ||
| self.logging_home = Path(output_home).absolute() if output_home else None | ||
| else: | ||
| self.output_home = Path(output_home) if output_home else None | ||
| self.logging_home = Path(output_home) if output_home else None | ||
| self._setup_logger() | ||
@@ -574,4 +584,4 @@ | ||
| def save_args(self, to: Path | str = None) -> Path | None: | ||
| if self.env.output_home and self.env.argument_file: | ||
| args_file = to if to else self.env.output_home / self.env.argument_file | ||
| if self.env.logging_home and self.env.argument_file: | ||
| args_file = to if to else self.env.logging_home / self.env.argument_file | ||
| args_json = self.to_json(default=str, ensure_ascii=False, indent=2) | ||
@@ -603,2 +613,3 @@ make_parent_dir(args_file).write_text(args_json, encoding="utf-8") | ||
| output: OutputOption = field() | ||
| option: OptionData | None = field(default=None) | ||
@@ -621,2 +632,3 @@ def __post_init__(self): | ||
| to_dataframe(columns=columns, raw=self.output.index, data_prefix="output.index") if self.output.index else None, | ||
| to_dataframe(columns=columns, raw=self.option, data_prefix="option") if self.option else None, | ||
| ]).reset_index(drop=True) | ||
@@ -623,0 +635,0 @@ |
@@ -56,2 +56,3 @@ from __future__ import annotations | ||
| SQ = chr(39) # Single Quote | ||
| US = chr(95) # Underscore | ||
@@ -58,0 +59,0 @@ |
Alert delta unavailable
Currently unable to show alert delta for PyPI packages.
68196
1.34%1465
0.9%