diff --git a/docplex/mp/cplex_engine.py b/docplex/mp/cplex_engine.py index 1af3611..314fe74 100644 --- a/docplex/mp/cplex_engine.py +++ b/docplex/mp/cplex_engine.py @@ -21,6 +21,7 @@ from docplex.mp.constants import ConflictStatus from docplex.mp.constr import IndicatorConstraint, RangeConstraint, BinaryConstraint, \ EquivalenceConstraint +from docplex.mp.format import ExchangeFormat from docplex.mp.progress import ProgressData from docplex.mp.qprogress import QProgressData from docplex.mp.solution import SolveSolution, SolutionPool @@ -2547,6 +2548,9 @@ def var_by_index(idx): return ConflictRefinerResult(conflicts, refined_by=self.name) def export(self, out, exchange_format): + if exchange_format is not None and not isinstance(exchange_format, ExchangeFormat): + self._model.fatal("Not a valid exchange format: {0}", exchange_format) + self.sync_cplex() if is_string(out): path = out @@ -2563,7 +2567,7 @@ def export(self, out, exchange_format): else: raise DOcplexException("CPLEX error in SAV export: {0!s}", cpx_se) else: - # assume a file-like object + # delegate to cplex, assume write and close methods. filetype = exchange_format.filetype return self._cplex.write_to_stream(out, filetype) diff --git a/docplex/mp/model.py b/docplex/mp/model.py index 07391e2..709b9d7 100644 --- a/docplex/mp/model.py +++ b/docplex/mp/model.py @@ -5494,13 +5494,17 @@ def _resolve_path(self, path_arg, basename_arg, extension): def _make_output_path(self, extension, basename, path=None): return make_output_path2(self.name, extension, basename, path) + def _new_lp_printer(self): + printer_kwargs = {'full_obj': self._print_full_obj} + lp_printer = LPModelPrinter(**printer_kwargs) + return lp_printer + def _get_printer(self, format_spec, do_raise=False, silent=False): # INTERNAL - printer_kwargs = {'full_obj': self._print_full_obj} format_ = parse_format(format_spec) printer = None if format_.name == 'LP': - printer = LPModelPrinter(**printer_kwargs) + printer = self._new_lp_printer() else: if do_raise: self.fatal("Unsupported output format: {0!s}", format_spec) @@ -5648,7 +5652,6 @@ def export_as_savgz(self, path=None, basename=None): """ return self._export_from_cplex(path, basename, format_spec="sav.gz") - def _export_from_cplex(self, path=None, basename=None, hide_user_names=False, format_spec="lp"): return self._export(path, basename, @@ -5713,7 +5716,13 @@ def _export_to_stream(self, stream, hide_user_names=False, format_spec="lp"): printer.set_mangle_names(hide_user_names) printer.printModel(self, stream) else: - self.__engine.export(stream, format_spec) + self.__engine.export(stream, format_) + + def _export_to_lp_stream(self, out_stream, hide_user_names=False): + lp_printer = self._new_lp_printer() + assert lp_printer + lp_printer.set_mangle_names(hide_user_names) + lp_printer.printModel(self, out_stream) def export_to_stream(self, stream, hide_user_names=False, format_spec="lp"): """ Export the model to an output stream in LP format. @@ -5731,7 +5740,9 @@ def export_to_stream(self, stream, hide_user_names=False, format_spec="lp"): and `c1`, `c2`, ,... for constraints. Default is to keep user names. """ - self._export_to_stream(stream, hide_user_names, format_spec) + if format_spec != "lp": + self.fatal("Model.export_to_stream() is only available for LP format, \"{0}\" not supported", format_spec) + self._export_to_lp_stream(stream, hide_user_names) def export_as_lp_string(self, hide_user_names=False): """ Exports the model to a string in LP format. @@ -5746,7 +5757,9 @@ def export_as_lp_string(self, hide_user_names=False): Returns: A string, containing the model exported in LP format. """ - return self.export_to_string(hide_user_names, "lp") + oss = StringIO() + self._export_to_lp_stream(oss, hide_user_names) + return oss.getvalue() @property def lp_string(self): @@ -5788,20 +5801,10 @@ def _export_as_cplex_string(self, format_spec): self.__engine.export(bs, _format) raw_res = bs.getvalue() if _format.is_binary: - # for b, by in enumerate(raw_res): - # nl = (b % 21 == 20) - # print(f" {by}", end='\n' if nl else '') - # print() return raw_res else: return raw_res.decode(self.parameters.read.fileencoding.get()) - def export_to_string(self, hide_user_names=False, format_spec="lp"): - # INTERNAL - oss = StringIO() - self._export_to_stream(oss, hide_user_names, format_spec) - return oss.getvalue() - def export_parameters_as_prm(self, path=None, basename=None): # path is either a nonempty path string or None self._checker.typecheck_string(path, accept_none=True, accept_empty=False) diff --git a/docplex/mp/tck.py b/docplex/mp/tck.py index 769a13b..0805452 100644 --- a/docplex/mp/tck.py +++ b/docplex/mp/tck.py @@ -487,7 +487,8 @@ def typecheck_string(self, arg, accept_empty=False, accept_none=False, caller='' elif not (arg is None and accept_none): s_caller = resolve_caller_as_string(caller) qualifier = "non-empty " if not accept_empty else "" - self.fatal("{0}Expecting a {2}string, got: {1!r}", s_caller, arg, qualifier) + s_none = " or None" if accept_none else "" + self.fatal("{0}Expecting a {2}string{3}, got: {1!r}", s_caller, arg, qualifier, s_none) def typecheck_string_seq(self, arg, accept_empty=False, accept_none=False, caller=''): checked_strings = list(arg)