def input_data( ctx: typer.Context, path_out: str = typer.Argument("./tmp", help="Path to example output directory."), ): """Generate example input data.""" output_path_string = validate_output_path(path_out) output_path = Path(output_path_string) / Path("examples") typer.echo(f"Examples will be saved to {output_path.resolve()}") save_callback_examples(output_path) report_finished_task(ctx)
def workorder( ctx: typer.Context, path_in: str = typer.Argument(..., help="Path to the workorder file."), path_out: str = typer.Argument( "./tmp", help="Path to be prepended to the workorder output path."), dry_run: bool = typer.Option( False, "-d", "--dry-run", help=""" Not implemented yet. Dry-run will perform all operations up to but not including making the actual http requests. This will detect some missed settings and parameters, but does not find mistakes that can only be checked on the server, eg. a non-existant type_id. """, ), ): """Load a workorder and do it.""" if dry_run: typer.BadParameter("not implemented yet.") path_in = validate_input_path(path_in) file_path = Path(path_in) try: esi_work_order = EsiWorkOrder.deserialize_file(file_path) except Exception as ex: logger.exception( "Error deserializing workorder from file: %s. Error: %s, msg: %s", file_path, ex.__class__.__name__, ex, ) raise typer.BadParameter( f"Error decoding workorder at {file_path}, msg: {ex}") # NOTE: path is not checked with results of template values. path_out = validate_output_path(path_out) output_path_string = str(path_out / Path(esi_work_order.output_path)) esi_work_order.update_attributes({"ewo_output_path": output_path_string}) operation_manifest = ctx.obj["operation_manifest"] observer = EsiObserver() try: do_workorder(esi_work_order, operation_manifest, observers=[observer]) except Exception as ex: raise typer.BadParameter( f"Error doing the job. {ex.__class__.__name__}: {ex}") report_on_jobs(esi_work_order.jobs) report_finished_task(ctx)
def browse( ctx: typer.Context, op_id: str = typer.Argument( "get_markets_prices", autocompletion=completion_op_id, callback=check_for_op_id, help="A valid op-id. e.g. get_markets_prices", ), ): """Browse schema by op_id.""" operation_manifest: OperationManifest = ctx.obj["operation_manifest"] try: op_info = operation_manifest.op_info(op_id) except ValueError: raise typer.BadParameter(f"Invalid op_id: {op_id}") typer.echo(yaml.dump(dataclasses.asdict(op_info), sort_keys=False)) report_finished_task(ctx)
def download( ctx: typer.Context, url: str = typer.Option( "https://esi.evetech.net/latest/swagger.json", "--url", help="The url to the ESI schema.", ), std_out: bool = typer.Option(False, "-s", "--std-out", help="Print schema to std out"), app_data: bool = typer.Option( True, help="Save the schema to the app data directory."), file_path: Path = typer.Option(None, "-f", "--file-path", help="Custom path for saving schema."), ): """Download a schema, use --help for more options.""" config: EveEsiJobConfig = ctx.obj["config"] url = config.schema_url schema: Optional[Dict] = download_json(url) if schema is None: raise typer.BadParameter(f"Unable to download schema from {url}") if app_data: # pylint: disable=unsubscriptable-object version = schema["info"]["version"] # type: ignore params = {"version": version} save_path = save_json_to_app_data(schema, config.app_dir, "schema", params) typer.echo(f"Schema saved to {save_path}") if std_out: typer.echo(json.dumps(schema, indent=2)) typer.Exit() if file_path is not None: try: file_path.parent.mkdir(parents=True, exist_ok=True) file_path.write_text(json.dumps(schema)) except Exception as ex: raise typer.BadParameter( f"Error saving schema to {file_path}. Error: {ex.__class__.__name__}, msg: {ex}" ) typer.echo(f"Schema saved to {file_path.resolve()}") report_finished_task(ctx)
def list_op_ids( ctx: typer.Context, output: OpidOutput = typer.Option( "raw-list", "-o", "--output", show_choices=True, help="Output format.", ), ): """List available op_ids.""" operation_manifest: OperationManifest = ctx.obj["operation_manifest"] op_id_keys = operation_manifest.available_op_ids() op_id_keys.sort() if output == OpidOutput.JSON: op_ids = json.dumps(op_id_keys, indent=2) else: op_ids = "\n".join(op_id_keys) typer.echo(op_ids) report_finished_task(ctx)
def workorder( ctx: typer.Context, path_in: Path = typer.Argument( ..., help="Path to the job file(s).", ), path_out: Path = typer.Argument( "./tmp", help= "Parent path for saving the new workorder, will be prepended to --file-name.", ), format_id: FormatChoices = typer.Option( FormatChoices.json, "-f", "--format-id", show_choices=True, help="Output file format.", ), file_name: Path = typer.Option( "workorders/${ewo_iso_date_time}/workorder-${ewo_uid}", "-n", "--file-name", help= ("File name for the new workorder. Can include directories, " "and the file type suffix will be added based on --format-id if necessary." ), ), ewo_path: Optional[Path] = typer.Option( None, "-w", "--existing-work-order", help="Path to an existing workorder.", ), ): """Create a workorder, and add existing jobs to it. Can also add jobs to an existing Workorder. """ _ = ctx if not path_in.exists(): raise typer.BadParameter(f"{path_in} does not exist.") if path_in.is_file(): maybe_jobs = [path_in] else: maybe_jobs = [*path_in.glob("*.json"), *path_in.glob("*.yaml")] loaded_jobs = [] for maybe_job in maybe_jobs: try: loaded_job = EsiJob.deserialize_file(maybe_job) except Exception as ex: raise typer.BadParameter( f"Error decoding job at {maybe_job}, msg:{ex}") loaded_jobs.append(loaded_job) if not loaded_jobs: raise typer.BadParameter(f"No jobs found at {path_in}") if ewo_path is None: ewo_ = get_default_workorder() else: try: ewo_ = EsiWorkOrder.deserialize_file(ewo_path) except Exception as ex: raise typer.BadParameter( f"Error decoding workorder string. {ex.__class__.__name__}, {ex}" ) ewo_.jobs.extend(loaded_jobs) output_path = path_out / file_name out_template = Template(str(output_path)) file_path = Path(out_template.substitute(ewo_.attributes())) try: saved_path = ewo_.serialize_file(file_path, format_id) typer.echo(f"Workorder saved to {saved_path}") report_finished_task(ctx) except Exception as ex: raise typer.BadParameter( f"Error saving workorder to {path_out}. {ex.__class__.__name__}, {ex}" )
def jobs( ctx: typer.Context, op_id: str = typer.Argument( ..., autocompletion=completion_op_id, callback=check_for_op_id, help="A valid op-id. e.g. get_markets_prices", ), param_string: Optional[str] = typer.Option( None, "--param-string", "-p", help= "Optional. Full or partial parameters as a json encoded dictionary string. " "Keys must be valid parameters for selected op_id.", ), default_params: bool = typer.Option( False, "-d", "--default-params", help="Include all parameters that are required, or have default values. " "Missing values will be 'NOTSET'.", ), callback_path: Optional[Path] = typer.Option( None, "-c", "--callbacks", help="Optional. Path to custom callbacks to be used. ", ), file_name: str = typer.Option( "created-jobs/${esi_job_op_id}-${esi_job_uid}", "-n", "--file-name", help=("File name for the new job, must be unique if multiple jobs. " "Can include directories, " "and the file type suffix will be added based on --format-id."), ), data_path: Optional[Path] = typer.Option( None, "--data-file", "-i", help= ("Optional. Path to json, csv, or yaml file with full or partial parameters. " "Must result in a list of dicts."), ), format_id: FormatChoices = typer.Option( FormatChoices.json, "-f", "--format-id", show_choices=True, help="Output file format.", ), path_out: Path = typer.Argument( "./tmp", help= "Parent path for saving the new jobs, will be prepended to --file-name.", ), ): """Create one or more jobs from an op_id. Required parameters can be supplied as a combination of --param-string and file data. This allows supplying one region_id through param-string, and a list of type_ids from a csv file to get multiple jobs. Csv input files must have properly labeled columns. """ operation_manifest: OperationManifest = ctx.obj["operation_manifest"] # path_out = optional_object(path_out, Path, ".") if path_out.is_file: typer.BadParameter("path_out must not be a file.") file_data: Optional[List[Dict]] = get_params_from_file(data_path) parameters: Dict = decode_param_string(param_string) if callback_path is None: callback_collection = default_callback_collection() else: callback_collection = load_callbacks(callback_path) jobs_: List[EsiJob] = [] try: op_info = operation_manifest.op_info(op_id) if not file_data: job = op_info.create_job( parameters, callback_collection, include_default_params=default_params, # only_required_default_params=False, # allow_notset=False, ) jobs_.append(job) else: for params in file_data: params.update(parameters) job = op_info.create_job( params, callback_collection, include_default_params=default_params, # only_required_default_params=False, # allow_notset=False, ) jobs_.append(job) except Exception as ex: raise typer.BadParameter( f"Exception creating job. {ex.__class__.__name__}: {ex}") for job in jobs_: file_path = resolve_job_file_path(job, file_name, path_out) try: save_path = job.serialize_file(file_path, format_id) except Exception as ex: raise typer.BadParameter( f"Error saving job to {save_path}. {ex.__class__.__name__}, {ex}" ) logger.info("Saved job %s at %s", job.uid, file_path) typer.echo(f"{len(jobs_)} jobs saved to {path_out}") report_finished_task(ctx)