diff --git a/cmake/samples/python/sample.py b/cmake/samples/python/sample.py index ebeb7be394..abd5f6ce16 100644 --- a/cmake/samples/python/sample.py +++ b/cmake/samples/python/sample.py @@ -13,6 +13,7 @@ # limitations under the License. """Sample to test or-tools installation.""" + import ortools # from ortools.algorithms import knapsack_solver diff --git a/examples/python/appointments.py b/examples/python/appointments.py index 328ac691f0..65fbc66031 100644 --- a/examples/python/appointments.py +++ b/examples/python/appointments.py @@ -180,7 +180,7 @@ def aggregate_item_collections_optimally( def get_optimal_schedule( - demand: list[tuple[float, str, int]] + demand: list[tuple[float, str, int]], ) -> list[tuple[int, list[tuple[int, str]]]]: """Computes the optimal schedule for the installation input. diff --git a/examples/python/balance_group_sat.py b/examples/python/balance_group_sat.py index 5f37f95605..10d0725075 100644 --- a/examples/python/balance_group_sat.py +++ b/examples/python/balance_group_sat.py @@ -19,6 +19,7 @@ be as close to the average as possible. Furthermore, if one color is an a group, at least k items with this color must be in that group. """ + from typing import Dict, Sequence from absl import app diff --git a/examples/python/bus_driver_scheduling_sat.py b/examples/python/bus_driver_scheduling_sat.py index 0a957febd2..64f77118d7 100644 --- a/examples/python/bus_driver_scheduling_sat.py +++ b/examples/python/bus_driver_scheduling_sat.py @@ -29,6 +29,7 @@ import math from absl import app from absl import flags + from google.protobuf import text_format from ortools.sat.python import cp_model @@ -81,7 +82,7 @@ SAMPLE_SHIFTS_TINY = [ [25, "15:40", "15:56", 940, 956, 16], [26, "15:58", "16:45", 958, 1005, 47], [27, "16:04", "17:30", 964, 1050, 86], -] # yapf:disable +] SAMPLE_SHIFTS_SMALL = [ # @@ -143,7 +144,7 @@ SAMPLE_SHIFTS_SMALL = [ [47, "18:34", "19:58", 1114, 1198, 84], [48, "19:56", "20:34", 1196, 1234, 38], [49, "20:05", "20:48", 1205, 1248, 43], -] # yapf:disable +] SAMPLE_SHIFTS_MEDIUM = [ [0, "04:30", "04:53", 270, 293, 23], @@ -346,7 +347,7 @@ SAMPLE_SHIFTS_MEDIUM = [ [197, "00:02", "00:12", 1442, 1452, 10], [198, "00:07", "00:39", 1447, 1479, 32], [199, "00:25", "01:12", 1465, 1512, 47], -] # yapf:disable +] SAMPLE_SHIFTS_LARGE = [ [0, "04:18", "05:00", 258, 300, 42], @@ -1705,7 +1706,7 @@ SAMPLE_SHIFTS_LARGE = [ [1353, "00:47", "01:26", 1487, 1526, 39], [1354, "00:54", "01:04", 1494, 1504, 10], [1355, "00:57", "01:07", 1497, 1507, 10], -] # yapf:disable +] def bus_driver_scheduling(minimize_drivers: bool, max_num_drivers: int) -> int: diff --git a/examples/python/cryptarithm_sat.py b/examples/python/cryptarithm_sat.py index c4e49e0873..9b28dbc97b 100644 --- a/examples/python/cryptarithm_sat.py +++ b/examples/python/cryptarithm_sat.py @@ -12,8 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -"""Use CP-SAT to solve a simple cryptarithmetic problem: SEND+MORE=MONEY. -""" +"""Use CP-SAT to solve a simple cryptarithmetic problem: SEND+MORE=MONEY.""" from absl import app from ortools.sat.python import cp_model diff --git a/examples/python/golomb8.py b/examples/python/golomb8.py index cb2a2423ca..ec720e3191 100755 --- a/examples/python/golomb8.py +++ b/examples/python/golomb8.py @@ -69,7 +69,7 @@ def main(_) -> None: branches = collector.Branches(i) failures = collector.Failures(i) print( - ("Solution #%i: value = %i, failures = %i, branches = %i," "time = %i ms") + "Solution #%i: value = %i, failures = %i, branches = %i,time = %i ms" % (i, obj_value, failures, branches, time) ) time = solver.WallTime() diff --git a/examples/python/golomb_sat.py b/examples/python/golomb_sat.py index 6b4e19cc06..0ed2240a6b 100644 --- a/examples/python/golomb_sat.py +++ b/examples/python/golomb_sat.py @@ -24,6 +24,7 @@ see: https://en.wikipedia.org/wiki/Golomb_ruler """ from typing import Sequence + from absl import app from absl import flags diff --git a/examples/python/knapsack_2d_sat.py b/examples/python/knapsack_2d_sat.py index e771821552..5014d246e8 100644 --- a/examples/python/knapsack_2d_sat.py +++ b/examples/python/knapsack_2d_sat.py @@ -26,7 +26,6 @@ import numpy as np import pandas as pd from google.protobuf import text_format - from ortools.sat.python import cp_model diff --git a/examples/python/line_balancing_sat.py b/examples/python/line_balancing_sat.py index c80a747d3a..5cb513c52b 100644 --- a/examples/python/line_balancing_sat.py +++ b/examples/python/line_balancing_sat.py @@ -33,6 +33,7 @@ from typing import Dict, Sequence from absl import app from absl import flags + from google.protobuf import text_format from ortools.sat.python import cp_model diff --git a/examples/python/linear_assignment_api.py b/examples/python/linear_assignment_api.py index 34514974e4..64c4de0532 100644 --- a/examples/python/linear_assignment_api.py +++ b/examples/python/linear_assignment_api.py @@ -14,9 +14,9 @@ """Test linear sum assignment on a 4x4 matrix. - Example taken from: - http://www.ee.oulu.fi/~mpa/matreng/eem1_2-1.htm with kCost[0][1] - modified so the optimum solution is unique. +Example taken from: +http://www.ee.oulu.fi/~mpa/matreng/eem1_2-1.htm with kCost[0][1] +modified so the optimum solution is unique. """ from typing import Sequence @@ -28,7 +28,12 @@ def run_assignment_on_4x4_matrix(): """Test linear sum assignment on a 4x4 matrix.""" num_sources = 4 num_targets = 4 - cost = [[90, 76, 75, 80], [35, 85, 55, 65], [125, 95, 90, 105], [45, 110, 95, 115]] + cost = [ + [90, 76, 75, 80], + [35, 85, 55, 65], + [125, 95, 90, 105], + [45, 110, 95, 115], + ] expected_cost = cost[0][3] + cost[1][2] + cost[2][1] + cost[3][0] assignment = linear_sum_assignment.SimpleLinearSumAssignment() diff --git a/examples/python/maximize_combinations_sat.py b/examples/python/maximize_combinations_sat.py index a23e90d384..853107deaf 100644 --- a/examples/python/maximize_combinations_sat.py +++ b/examples/python/maximize_combinations_sat.py @@ -15,6 +15,7 @@ """Maximize the number of valid combinations of Boolean variables.""" from typing import Sequence + from absl import app from ortools.sat.python import cp_model diff --git a/examples/python/maze_escape_sat.py b/examples/python/maze_escape_sat.py index 7a96e453d8..6d5e9c4796 100644 --- a/examples/python/maze_escape_sat.py +++ b/examples/python/maze_escape_sat.py @@ -20,6 +20,7 @@ visit all boxes in order, and walk on each block in a 4x4x4 map exactly once. Admissible moves are one step in one of the 6 directions: x+, x-, y+, y-, z+(up), z-(down) """ + from typing import Dict, Sequence, Tuple from absl import app diff --git a/examples/python/nqueens_sat.py b/examples/python/nqueens_sat.py index e2f29542a5..6fd102dcdc 100644 --- a/examples/python/nqueens_sat.py +++ b/examples/python/nqueens_sat.py @@ -18,6 +18,7 @@ import time from absl import app from absl import flags + from ortools.sat.python import cp_model _SIZE = flags.DEFINE_integer("size", 8, "Number of queens.") diff --git a/examples/python/pell_equation_sat.py b/examples/python/pell_equation_sat.py index 3583c5557d..75554e6a40 100644 --- a/examples/python/pell_equation_sat.py +++ b/examples/python/pell_equation_sat.py @@ -18,6 +18,7 @@ from collections.abc import Sequence from absl import app from absl import flags + from ortools.sat.python import cp_model diff --git a/examples/python/pyflow_example.py b/examples/python/pyflow_example.py index 55db850530..44f0498d4c 100644 --- a/examples/python/pyflow_example.py +++ b/examples/python/pyflow_example.py @@ -52,7 +52,12 @@ def min_cost_flow_api(): print("MinCostFlow on 4x4 matrix.") num_sources = 4 num_targets = 4 - costs = [[90, 75, 75, 80], [35, 85, 55, 65], [125, 95, 90, 105], [45, 110, 95, 115]] + costs = [ + [90, 75, 75, 80], + [35, 85, 55, 65], + [125, 95, 90, 105], + [45, 110, 95, 115], + ] expected_cost = 275 smcf = min_cost_flow.SimpleMinCostFlow() for source in range(0, num_sources): diff --git a/examples/python/rcpsp_sat.py b/examples/python/rcpsp_sat.py index 2b78e3d049..eb4fa3e1b7 100644 --- a/examples/python/rcpsp_sat.py +++ b/examples/python/rcpsp_sat.py @@ -27,9 +27,9 @@ from absl import app from absl import flags from google.protobuf import text_format -from ortools.sat.python import cp_model from ortools.scheduling import rcpsp_pb2 from ortools.scheduling.python import rcpsp +from ortools.sat.python import cp_model _INPUT = flags.DEFINE_string("input", "", "Input file to parse and solve.") _OUTPUT_PROTO = flags.DEFINE_string( diff --git a/examples/python/spread_robots_sat.py b/examples/python/spread_robots_sat.py index 27da1d65b9..b9fc5999e6 100644 --- a/examples/python/spread_robots_sat.py +++ b/examples/python/spread_robots_sat.py @@ -18,7 +18,6 @@ import math from typing import Sequence from absl import app from absl import flags - from google.protobuf import text_format from ortools.sat.python import cp_model diff --git a/examples/python/steel_mill_slab_sat.py b/examples/python/steel_mill_slab_sat.py index 6f79d85fbe..e84b490cf9 100644 --- a/examples/python/steel_mill_slab_sat.py +++ b/examples/python/steel_mill_slab_sat.py @@ -21,6 +21,7 @@ import time from absl import app from absl import flags + from google.protobuf import text_format from ortools.sat.python import cp_model diff --git a/examples/python/weighted_latency_problem_sat.py b/examples/python/weighted_latency_problem_sat.py index 36616bb26b..0abc315afe 100644 --- a/examples/python/weighted_latency_problem_sat.py +++ b/examples/python/weighted_latency_problem_sat.py @@ -16,6 +16,7 @@ import random from typing import Sequence + from absl import app from absl import flags @@ -27,7 +28,9 @@ _GRID_SIZE = flags.DEFINE_integer("grid_size", 20, "Size of the grid where nodes _PROFIT_RANGE = flags.DEFINE_integer("profit_range", 50, "Range of profit.") _SEED = flags.DEFINE_integer("seed", 0, "Random seed.") _PARAMS = flags.DEFINE_string( - "params", "num_search_workers:16, max_time_in_seconds:5", "Sat solver parameters." + "params", + "num_search_workers:16, max_time_in_seconds:5", + "Sat solver parameters.", ) _PROTO_FILE = flags.DEFINE_string( "proto_file", "", "If not empty, output the proto to this file." diff --git a/ortools/set_cover/samples/set_cover.py b/ortools/set_cover/samples/set_cover.py index c6d5b48aef..fd6e8f7055 100755 --- a/ortools/set_cover/samples/set_cover.py +++ b/ortools/set_cover/samples/set_cover.py @@ -17,6 +17,7 @@ # [START program] # [START import] from ortools.set_cover.python import set_cover + # [END import] diff --git a/tools/check_python_deps.py b/tools/check_python_deps.py index deeb558abd..f205680a93 100644 --- a/tools/check_python_deps.py +++ b/tools/check_python_deps.py @@ -111,7 +111,10 @@ if __name__ == "__main__": "-l", "--log", type="string", - help="Available levels are CRITICAL (3), ERROR (2), WARNING (1), INFO (0), DEBUG (-1)", + help=( + "Available levels are CRITICAL (3), ERROR (2), WARNING (1), INFO (0)," + " DEBUG (-1)" + ), default="INFO", ) options, args = parser.parse_args() diff --git a/tools/doc/doxygen_filter.py b/tools/doc/doxygen_filter.py index f9271df7a7..4fcb95b667 100644 --- a/tools/doc/doxygen_filter.py +++ b/tools/doc/doxygen_filter.py @@ -36,186 +36,182 @@ import sys class DoxygenFormatter: - """Transforms lines of a source file to make them Doxygen-friendly.""" + """Transforms lines of a source file to make them Doxygen-friendly.""" - ANYWHERE = 'anywhere' - COMMENT = 'comment' + ANYWHERE = "anywhere" + COMMENT = "comment" - def __init__(self, outfile): - # The file-like object to which we will write lines. - self.out = outfile + def __init__(self, outfile): + # The file-like object to which we will write lines. + self.out = outfile - # A buffer for storing empty lines which we can use later if we need to - # retroactively insert markup without causing line number offset problems. - self.empty_line_buffer = [] + # A buffer for storing empty lines which we can use later if we need to + # retroactively insert markup without causing line number offset problems. + self.empty_line_buffer = [] - # Whether we are currently inside an indented code block. - self.in_code_block = False + # Whether we are currently inside an indented code block. + self.in_code_block = False - self.CompileExpressions() + self.CompileExpressions() - def CompileExpressions(self): - """Pre-compiles frequently used regexps for improved performance. + def CompileExpressions(self): + """Pre-compiles frequently used regexps for improved performance. - The regexps are arranged as a list of 3-tuples, where the second value is - the replacement string (which may include backreferences) and the third - value is one of the context constants ANYWHERE or COMMENT. This is a list - of tuples instead of a dictionary because order matters: earlier regexps - will be applied first, and the resulting text (not the original) will be - what is seen by subsequent regexps. - """ - self.comment_regex = re.compile(r'^\s*//') + The regexps are arranged as a list of 3-tuples, where the second value is + the replacement string (which may include backreferences) and the third + value is one of the context constants ANYWHERE or COMMENT. This is a list + of tuples instead of a dictionary because order matters: earlier regexps + will be applied first, and the resulting text (not the original) will be + what is seen by subsequent regexps. + """ + self.comment_regex = re.compile(r"^\s*//") - self.substitutions = [ - # Remove copyright lines. - (re.compile(r'^\s*//\s*[Cc]opyright.*Google.*'), r'', self.ANYWHERE), + self.substitutions = [ + # Remove copyright lines. + (re.compile(r"^\s*//\s*[Cc]opyright.*Google.*"), r"", self.ANYWHERE), + # Remove any comment lines that consist of only punctuation (banners). + # We only allow a maximum of two spaces before the punctuation so we + # don't accidentally get rid of code examples with bare braces and + # whatnot. + (re.compile(r"(^\s*)//\s{0,2}[-=#/]+$"), r"\1//\n", self.ANYWHERE), + # If we find something that looks like a list item that is indented four + # or more spaces, pull it back to the left so doxygen's Markdown engine + # doesn't treat it like a code block. + (re.compile(r"(^\s*)//\s{4,}([-\d*].*)"), r"\1 \2", self.COMMENT), + # Replace TODO(user) in a comment with @todo (someone) + (re.compile(r"TODO"), r"@todo ", self.COMMENT), + # Replace leading 'Note:' or 'Note that' in a comment with @note + ( + re.compile(r"(\/\/\s+)Note(?:\:| that)", re.I), + r"\1@note", + self.COMMENT, + ), + # Replace leading 'Warning:' in a comment with @warning + (re.compile(r"(\/\/\s+)Warning:", re.I), r"\1@warning", self.COMMENT), + # Replace leading 'Deprecated' in a comment with @deprecated + ( + re.compile(r"(\/\/\s+)Deprecated[^\w\s]*", re.I), + r"\1@deprecated", + self.COMMENT, + ), + # Replace pipe-delimited parameter names with backtick-delimiters + (re.compile(r"\|(\w+)\|"), r"`\1`", self.COMMENT), + # Convert standalone comment lines to Doxygen style. + (re.compile(r"(^\s*)//(?=[^/])"), r"\1///", self.ANYWHERE), + # Strip trailing comments from preprocessor directives. + (re.compile(r"(^#.*)//.*"), r"\1", self.ANYWHERE), + # Convert remaining trailing comments to doxygen style, unless they are + # documenting the end of a block. + (re.compile(r"([^} ]\s+)//(?=[^/])"), r"\1///<", self.ANYWHERE), + ] - # Remove any comment lines that consist of only punctuation (banners). - # We only allow a maximum of two spaces before the punctuation so we - # don't accidentally get rid of code examples with bare braces and - # whatnot. - (re.compile(r'(^\s*)//\s{0,2}[-=#/]+$'), r'\1//\n', self.ANYWHERE), + def Transform(self, line): + """Performs the regexp transformations defined by self.substitutions. - # If we find something that looks like a list item that is indented four - # or more spaces, pull it back to the left so doxygen's Markdown engine - # doesn't treat it like a code block. - (re.compile(r'(^\s*)//\s{4,}([-\d*].*)'), r'\1 \2', self.COMMENT), + Args: + line: The line to transform. - # Replace TODO(user) in a comment with @todo (someone) - (re.compile(r'TODO'), r'@todo ', self.COMMENT), - - # Replace leading 'Note:' or 'Note that' in a comment with @note - (re.compile(r'(\/\/\s+)Note(?:\:| that)', re.I), r'\1@note', - self.COMMENT), - - # Replace leading 'Warning:' in a comment with @warning - (re.compile(r'(\/\/\s+)Warning:', re.I), r'\1@warning', self.COMMENT), - - # Replace leading 'Deprecated' in a comment with @deprecated - (re.compile(r'(\/\/\s+)Deprecated[^\w\s]*', re.I), r'\1@deprecated', - self.COMMENT), - - # Replace pipe-delimited parameter names with backtick-delimiters - (re.compile(r'\|(\w+)\|'), r'`\1`', self.COMMENT), - - # Convert standalone comment lines to Doxygen style. - (re.compile(r'(^\s*)//(?=[^/])'), r'\1///', self.ANYWHERE), - - # Strip trailing comments from preprocessor directives. - (re.compile(r'(^#.*)//.*'), r'\1', self.ANYWHERE), - - # Convert remaining trailing comments to doxygen style, unless they are - # documenting the end of a block. - (re.compile(r'([^} ]\s+)//(?=[^/])'), r'\1///<', self.ANYWHERE), - ] - - def Transform(self, line): - """Performs the regexp transformations defined by self.substitutions. - - Args: - line: The line to transform. - - Returns: - The resulting line. - """ - for (regex, repl, where) in self.substitutions: - if where is self.COMMENT and not self.comment_regex.match(line): + Returns: + The resulting line. + """ + for regex, repl, where in self.substitutions: + if where is self.COMMENT and not self.comment_regex.match(line): + return line + line = regex.sub(repl, line) return line - line = regex.sub(repl, line) - return line - def AppendToBufferedLine(self, text): - """Appends text to the last buffered empty line. + def AppendToBufferedLine(self, text): + """Appends text to the last buffered empty line. - Empty lines are buffered rather than being written out directly. This lets - us retroactively rewrite buffered lines to include markup that affects the - following line, while avoiding the line number offset that would result from - inserting a line that wasn't in the original source. + Empty lines are buffered rather than being written out directly. This lets + us retroactively rewrite buffered lines to include markup that affects the + following line, while avoiding the line number offset that would result from + inserting a line that wasn't in the original source. - Args: - text: The text to append to the line. + Args: + text: The text to append to the line. - Returns: - True if there was an available empty line to which text could be - appended, and False otherwise. - """ - if self.empty_line_buffer: - last_line = self.empty_line_buffer.pop().rstrip() - last_line += text + '\n' - self.empty_line_buffer.append(last_line) - return True - else: - return False + Returns: + True if there was an available empty line to which text could be + appended, and False otherwise. + """ + if self.empty_line_buffer: + last_line = self.empty_line_buffer.pop().rstrip() + last_line += text + "\n" + self.empty_line_buffer.append(last_line) + return True + else: + return False - def ConvertCodeBlock(self, line): - """Converts any code block that may begin or end on this line. + def ConvertCodeBlock(self, line): + """Converts any code block that may begin or end on this line. - Doxygen has (at least) two kinds of code blocks. Any block indented at - least four spaces gets formatted as code, but (for some reason) no syntax - highlighting is applied. Any block surrounded by "~~~" on both sides is - also treated as code, but these are syntax highlighted intelligently - depending on the file type. We typically write code blocks in the former - style, but we'd like them to be highlighted, so this function converts them - to the latter style by adding in the ~~~ lines. + Doxygen has (at least) two kinds of code blocks. Any block indented at + least four spaces gets formatted as code, but (for some reason) no syntax + highlighting is applied. Any block surrounded by "~~~" on both sides is + also treated as code, but these are syntax highlighted intelligently + depending on the file type. We typically write code blocks in the former + style, but we'd like them to be highlighted, so this function converts them + to the latter style by adding in the ~~~ lines. - To make this a bit more complicated, we would really prefer not to insert - new lines into the file, since that will make the line numbers shown in - doxygen not match the line numbers in the actual source code. For this - reason, we only perform the conversion if at least one "blank" line (empty - comment line) appears before the start of the code block. If we get down to - the bottom of the block and there's no blank line after it, we will be - forced to add a line, since we can't go back and undo what we already did. + To make this a bit more complicated, we would really prefer not to insert + new lines into the file, since that will make the line numbers shown in + doxygen not match the line numbers in the actual source code. For this + reason, we only perform the conversion if at least one "blank" line (empty + comment line) appears before the start of the code block. If we get down to + the bottom of the block and there's no blank line after it, we will be + forced to add a line, since we can't go back and undo what we already did. - Args: - line: The line to process. + Args: + line: The line to process. - Returns: - The converted line. - """ - if not self.in_code_block and re.match(r'\s*///\s{4,}', line): - if self.AppendToBufferedLine(' ~~~'): - # If this fails, we'll just leave it un-highlighted. - self.in_code_block = True - elif self.in_code_block and not re.match(r'\s*///\s{4,}', line): - if not self.AppendToBufferedLine(' ~~~'): - # This is bad. We don't have a buffered line to use to end the code - # block, so we'll have to insert one. This will cause the line - # numbers to stop matching the original source, unfortunately. - line = '/// ~~~\n' + line - self.in_code_block = False - return line + Returns: + The converted line. + """ + if not self.in_code_block and re.match(r"\s*///\s{4,}", line): + if self.AppendToBufferedLine(" ~~~"): + # If this fails, we'll just leave it un-highlighted. + self.in_code_block = True + elif self.in_code_block and not re.match(r"\s*///\s{4,}", line): + if not self.AppendToBufferedLine(" ~~~"): + # This is bad. We don't have a buffered line to use to end the code + # block, so we'll have to insert one. This will cause the line + # numbers to stop matching the original source, unfortunately. + line = "/// ~~~\n" + line + self.in_code_block = False + return line - def ProcessLine(self, line): - """Processes a line. + def ProcessLine(self, line): + """Processes a line. - If the line is an empty line inside a comment, we buffer it for possible - rewriting later on. Otherwise, we transform it using our regexps and - write it (as well as any buffered blank lines) out to the output. + If the line is an empty line inside a comment, we buffer it for possible + rewriting later on. Otherwise, we transform it using our regexps and + write it (as well as any buffered blank lines) out to the output. - Args: - line: The line to process. - """ - line = self.Transform(line) + Args: + line: The line to process. + """ + line = self.Transform(line) - if line.strip() == '///': - # We may repurpose this empty line later, so don't write it out yet. - self.empty_line_buffer.append(line) - else: - line = self.ConvertCodeBlock(line) - # Flush the line buffer and write this line as well. - for buffered_line in self.empty_line_buffer: - self.out.write(buffered_line) - self.empty_line_buffer = [] - self.out.write(line) + if line.strip() == "///": + # We may repurpose this empty line later, so don't write it out yet. + self.empty_line_buffer.append(line) + else: + line = self.ConvertCodeBlock(line) + # Flush the line buffer and write this line as well. + for buffered_line in self.empty_line_buffer: + self.out.write(buffered_line) + self.empty_line_buffer = [] + self.out.write(line) def main(argv): - sourcefile = argv[1] - with open(sourcefile, 'r') as infile: - formatter = DoxygenFormatter(sys.stdout) - for line in infile: - formatter.ProcessLine(line) + sourcefile = argv[1] + with open(sourcefile, "r") as infile: + formatter = DoxygenFormatter(sys.stdout) + for line in infile: + formatter.ProcessLine(line) -if __name__ == '__main__': - main(sys.argv) +if __name__ == "__main__": + main(sys.argv) diff --git a/tools/doc/gen_ref_doc.py b/tools/doc/gen_ref_doc.py index 303c43ab21..691b5eed5f 100755 --- a/tools/doc/gen_ref_doc.py +++ b/tools/doc/gen_ref_doc.py @@ -18,249 +18,234 @@ import re def main(version): - """For each doc section, edit the doxy and header files, and generate the doc.""" - sections = create_section_data() - doxy_tmp = 'tools/doc/tmp.doxy' - header_tmp = 'tools/doc/header.tmp.html' - footer_tmp = 'tools/doc/footer.tmp.html' - style_sheet_tmp = 'tools/doc/styleSheet.tmp.css' + """For each doc section, edit the doxy and header files, and generate the doc.""" + sections = create_section_data() + doxy_tmp = "tools/doc/tmp.doxy" + header_tmp = "tools/doc/header.tmp.html" + footer_tmp = "tools/doc/footer.tmp.html" + style_sheet_tmp = "tools/doc/styleSheet.tmp.css" - for section in sections: - output_dir = section['output_dir'] - project_name = section['project name'] - title = section['title'] - doxyfile = 'tools/doc/' + section['doxyfile'] - headerfile = 'tools/doc/' + section['headerfile'] - footerfile = 'tools/doc/' + section['footerfile'] - stylesheetfile = 'tools/doc/' + section['styleSheetfile'] - input_files = section['input_files'] - # Edit doxyfile. - project_name_string = 'PROJECT_NAME = ' + project_name - project_number_string = 'PROJECT_NUMBER = ' + version - html_output_string = 'HTML_OUTPUT = ' + output_dir - input_string = 'INPUT = ' + input_files - f = open(doxyfile, 'r') - g = open(doxy_tmp, 'w') - filedata = f.read() - filedata = re.sub('PROJECT_NAME', project_name_string, filedata) - filedata = re.sub('PROJECT_NUMBER', project_number_string, filedata) - filedata = re.sub('HTML_OUTPUT', html_output_string, filedata) - if input_files: - filedata = re.sub(r'INPUT.*=.*', input_string, filedata) - # Write filedata. - g.write(filedata) - f.close() - g.close() + for section in sections: + output_dir = section["output_dir"] + project_name = section["project name"] + title = section["title"] + doxyfile = "tools/doc/" + section["doxyfile"] + headerfile = "tools/doc/" + section["headerfile"] + footerfile = "tools/doc/" + section["footerfile"] + stylesheetfile = "tools/doc/" + section["styleSheetfile"] + input_files = section["input_files"] + # Edit doxyfile. + project_name_string = "PROJECT_NAME = " + project_name + project_number_string = "PROJECT_NUMBER = " + version + html_output_string = "HTML_OUTPUT = " + output_dir + input_string = "INPUT = " + input_files + f = open(doxyfile, "r") + g = open(doxy_tmp, "w") + filedata = f.read() + filedata = re.sub("PROJECT_NAME", project_name_string, filedata) + filedata = re.sub("PROJECT_NUMBER", project_number_string, filedata) + filedata = re.sub("HTML_OUTPUT", html_output_string, filedata) + if input_files: + filedata = re.sub(r"INPUT.*=.*", input_string, filedata) + # Write filedata. + g.write(filedata) + f.close() + g.close() - # Edit header file. - f = open(headerfile, 'r') - g = open(header_tmp, 'w') - filedata = f.read() - filedata = re.sub('Banner Text', 'Google OR-Tools ' + version, - filedata) - filedata = re.sub('Page Title', title, filedata) - # Write filedata. - g.write(filedata) - f.close() - g.close() + # Edit header file. + f = open(headerfile, "r") + g = open(header_tmp, "w") + filedata = f.read() + filedata = re.sub("Banner Text", "Google OR-Tools " + version, filedata) + filedata = re.sub("Page Title", title, filedata) + # Write filedata. + g.write(filedata) + f.close() + g.close() - # Edit footer file. - f = open(footerfile, 'r') - g = open(footer_tmp, 'w') - filedata = f.read() - # Write filedata. - g.write(filedata) - f.close() - g.close() + # Edit footer file. + f = open(footerfile, "r") + g = open(footer_tmp, "w") + filedata = f.read() + # Write filedata. + g.write(filedata) + f.close() + g.close() - # Edit style sheet file. - f = open(stylesheetfile, 'r') - g = open(style_sheet_tmp, 'w') - filedata = f.read() - # Write filedata. - g.write(filedata) - f.close() - g.close() + # Edit style sheet file. + f = open(stylesheetfile, "r") + g = open(style_sheet_tmp, "w") + filedata = f.read() + # Write filedata. + g.write(filedata) + f.close() + g.close() - # Clean previous doc. - os.system('rm -rf docs/' + output_dir) - # Generate the doc. - os.system(f'doxygen {doxy_tmp}') - # Remove temp files. - os.system(f'rm {doxy_tmp}') - os.system(f'rm {header_tmp}') - os.system(f'rm {footer_tmp}') - os.system(f'rm {style_sheet_tmp}') + # Clean previous doc. + os.system("rm -rf docs/" + output_dir) + # Generate the doc. + os.system(f"doxygen {doxy_tmp}") + # Remove temp files. + os.system(f"rm {doxy_tmp}") + os.system(f"rm {header_tmp}") + os.system(f"rm {footer_tmp}") + os.system(f"rm {style_sheet_tmp}") def create_section_data(): - """Generate each section configuration.""" - sections = [{ - 'output_dir': - 'cpp_algorithms', - 'project name': - 'Algorithms', - 'title': - 'C++ Reference: Algorithms', - 'doxyfile': - 'cpp.doxy.in', - 'headerfile': - 'cpp.header.html.in', - 'footerfile': - 'all.footer.html.in', - 'styleSheetfile': - 'all.styleSheet.css.in', - 'input_files': - 'ortools/algorithms/dense_doubly_linked_list.h ' + - 'ortools/algorithms/dynamic_partition.h ' + - 'ortools/algorithms/dynamic_permutation.h ' + - 'ortools/algorithms/find_graph_symmetries.h ' + - 'ortools/algorithms/hungarian.h ' + - 'ortools/algorithms/knapsack_solver.h ' + - 'ortools/algorithms/sparse_permutation.h' - }, { - 'output_dir': - 'cpp_sat', - 'project name': - 'CP-SAT', - 'title': - 'C++ Reference: CP-SAT', - 'doxyfile': - 'cpp.doxy.in', - 'headerfile': - 'cpp.header.html.in', - 'footerfile': - 'all.footer.html.in', - 'styleSheetfile': - 'all.styleSheet.css.in', - 'input_files': - 'ortools/sat/cp_model.h ' + 'ortools/sat/cp_model_solver.h ' + - 'ortools/sat/model.h ' + 'ortools/util/sorted_interval_list.h ' + - 'ortools/util/time_limit.h ' + - 'ortools/gen/ortools/sat/boolean_problem.pb.h ' + - 'ortools/gen/ortools/sat/cp_model.pb.h ' + - 'ortools/gen/ortools/sat/sat_parameters.pb.h' - }, { - 'output_dir': - 'cpp_graph', - 'project name': - 'Graph', - 'title': - 'C++ Reference: Graph', - 'doxyfile': - 'cpp.doxy.in', - 'headerfile': - 'cpp.header.html.in', - 'footerfile': - 'all.footer.html.in', - 'styleSheetfile': - 'all.styleSheet.css.in', - 'input_files': - 'ortools/graph/christofides.h ' + 'ortools/graph/cliques.h ' + - 'ortools/graph/connected_components.h ' + - 'ortools/graph/connectivity.h ' + - 'ortools/graph/eulerian_path.h ' + 'ortools/graph/graph.h ' + - 'ortools/graph/graphs.h ' + 'ortools/graph/hamiltonian_path.h ' + - 'ortools/graph/graph_io.h ' + 'ortools/graph/iterators.h ' + - 'ortools/graph/linear_assignment.h ' + 'ortools/graph/max_flow.h ' + - 'ortools/graph/min_cost_flow.h ' + - 'ortools/graph/minimum_spanning_tree.h ' + - 'ortools/graph/one_tree_lower_bound.h ' + - 'ortools/graph/shortestpaths.h ' + - 'ortools/graph/strongly_connected_components.h ' + - 'ortools/graph/util.h ' + - 'ortools/gen/ortools/graph/flow_problem.pb.h ' - }, { - 'output_dir': - 'cpp_linear', - 'project name': - 'Linear solver', - 'title': - 'C++ Reference: Linear solver', - 'doxyfile': - 'cpp.doxy.in', - 'headerfile': - 'cpp.header.html.in', - 'footerfile': - 'all.footer.html.in', - 'styleSheetfile': - 'all.styleSheet.css.in', - 'input_files': - 'ortools/linear_solver/linear_expr.h ' + - 'ortools/linear_solver/linear_solver.h ' + - 'ortools/linear_solver/model_exporter.h ' + - 'ortools/linear_solver/model_exporter_swig_helper.h ' + - 'ortools/linear_solver/model_validator.h ' + - 'ortools/gen/ortools/linear_solver/linear_solver.pb.h ' - }, { - 'output_dir': - 'cpp_routing', - 'project name': - 'Routing', - 'title': - 'C++ Reference: Routing', - 'doxyfile': - 'cpp.doxy.in', - 'headerfile': - 'cpp.header.html.in', - 'footerfile': - 'all.footer.html.in', - 'styleSheetfile': - 'all.styleSheet.css.in', - 'input_files': - 'ortools/constraint_solver/constraint_solver.h ' + - 'ortools/constraint_solver/constraint_solveri.h ' + - 'ortools/constraint_solver/routing.h ' + - 'ortools/constraint_solver/routing_index_manager.h ' + - 'ortools/constraint_solver/routing_lp_scheduling.h ' + - 'ortools/constraint_solver/routing_neighborhoods.h ' + - 'ortools/constraint_solver/routing_parameters.h ' + - 'ortools/constraint_solver/routing_types.h ' + - 'ortools/gen/ortools/constraint_solver/assignment.pb.h ' + - 'ortools/gen/ortools/constraint_solver/demon_profiler.pb.h ' + - 'ortools/gen/ortools/constraint_solver/routing_enums.pb.h ' + - 'ortools/gen/ortools/constraint_solver/routing_parameters.pb.h ' + - 'ortools/gen/ortools/constraint_solver/search_limit.pb.h ' + - 'ortools/gen/ortools/constraint_solver/solver_parameters.pb.h ' - }, { - 'output_dir': 'cpp', - 'project name': 'OR-Tools', - 'title': 'C++ Reference', - 'doxyfile': 'cpp.doxy.in', - 'headerfile': 'default.header.html.in', - 'footerfile': 'default.footer.html.in', - 'styleSheetfile': 'default.styleSheet.css.in', - 'input_files': 'ortools ' + 'tools/doc' - }, { - 'output_dir': 'dotnet', - 'project name': 'OR-Tools', - 'title': '.Net Reference', - 'doxyfile': 'dotnet.doxy.in', - 'headerfile': 'dotnet.header.html.in', - 'footerfile': 'all.footer.html.in', - 'styleSheetfile': 'all.styleSheet.css.in', - 'input_files': 'ortools ' + 'tools/doc' - }, { - 'output_dir': 'java', - 'project name': 'OR-Tools', - 'title': 'Java Reference', - 'doxyfile': 'java.doxy.in', - 'headerfile': 'java.header.html.in', - 'footerfile': 'all.footer.html.in', - 'styleSheetfile': 'all.styleSheet.css.in', - 'input_files': 'ortools ' + 'tools/doc' - }] - return sections + """Generate each section configuration.""" + sections = [ + { + "output_dir": "cpp_algorithms", + "project name": "Algorithms", + "title": "C++ Reference: Algorithms", + "doxyfile": "cpp.doxy.in", + "headerfile": "cpp.header.html.in", + "footerfile": "all.footer.html.in", + "styleSheetfile": "all.styleSheet.css.in", + "input_files": ( + "ortools/algorithms/dense_doubly_linked_list.h " + + "ortools/algorithms/dynamic_partition.h " + + "ortools/algorithms/dynamic_permutation.h " + + "ortools/algorithms/find_graph_symmetries.h " + + "ortools/algorithms/hungarian.h " + + "ortools/algorithms/knapsack_solver.h " + + "ortools/algorithms/sparse_permutation.h" + ), + }, + { + "output_dir": "cpp_sat", + "project name": "CP-SAT", + "title": "C++ Reference: CP-SAT", + "doxyfile": "cpp.doxy.in", + "headerfile": "cpp.header.html.in", + "footerfile": "all.footer.html.in", + "styleSheetfile": "all.styleSheet.css.in", + "input_files": ( + "ortools/sat/cp_model.h " + + "ortools/sat/cp_model_solver.h " + + "ortools/sat/model.h " + + "ortools/util/sorted_interval_list.h " + + "ortools/util/time_limit.h " + + "ortools/gen/ortools/sat/boolean_problem.pb.h " + + "ortools/gen/ortools/sat/cp_model.pb.h " + + "ortools/gen/ortools/sat/sat_parameters.pb.h" + ), + }, + { + "output_dir": "cpp_graph", + "project name": "Graph", + "title": "C++ Reference: Graph", + "doxyfile": "cpp.doxy.in", + "headerfile": "cpp.header.html.in", + "footerfile": "all.footer.html.in", + "styleSheetfile": "all.styleSheet.css.in", + "input_files": ( + "ortools/graph/christofides.h " + + "ortools/graph/cliques.h " + + "ortools/graph/connected_components.h " + + "ortools/graph/connectivity.h " + + "ortools/graph/eulerian_path.h " + + "ortools/graph/graph.h " + + "ortools/graph/graphs.h " + + "ortools/graph/hamiltonian_path.h " + + "ortools/graph/graph_io.h " + + "ortools/graph/iterators.h " + + "ortools/graph/linear_assignment.h " + + "ortools/graph/max_flow.h " + + "ortools/graph/min_cost_flow.h " + + "ortools/graph/minimum_spanning_tree.h " + + "ortools/graph/one_tree_lower_bound.h " + + "ortools/graph/shortestpaths.h " + + "ortools/graph/strongly_connected_components.h " + + "ortools/graph/util.h " + + "ortools/gen/ortools/graph/flow_problem.pb.h " + ), + }, + { + "output_dir": "cpp_linear", + "project name": "Linear solver", + "title": "C++ Reference: Linear solver", + "doxyfile": "cpp.doxy.in", + "headerfile": "cpp.header.html.in", + "footerfile": "all.footer.html.in", + "styleSheetfile": "all.styleSheet.css.in", + "input_files": ( + "ortools/linear_solver/linear_expr.h " + + "ortools/linear_solver/linear_solver.h " + + "ortools/linear_solver/model_exporter.h " + + "ortools/linear_solver/model_exporter_swig_helper.h " + + "ortools/linear_solver/model_validator.h " + + "ortools/gen/ortools/linear_solver/linear_solver.pb.h " + ), + }, + { + "output_dir": "cpp_routing", + "project name": "Routing", + "title": "C++ Reference: Routing", + "doxyfile": "cpp.doxy.in", + "headerfile": "cpp.header.html.in", + "footerfile": "all.footer.html.in", + "styleSheetfile": "all.styleSheet.css.in", + "input_files": ( + "ortools/constraint_solver/constraint_solver.h " + + "ortools/constraint_solver/constraint_solveri.h " + + "ortools/constraint_solver/routing.h " + + "ortools/constraint_solver/routing_index_manager.h " + + "ortools/constraint_solver/routing_lp_scheduling.h " + + "ortools/constraint_solver/routing_neighborhoods.h " + + "ortools/constraint_solver/routing_parameters.h " + + "ortools/constraint_solver/routing_types.h " + + "ortools/gen/ortools/constraint_solver/assignment.pb.h " + + "ortools/gen/ortools/constraint_solver/demon_profiler.pb.h " + + "ortools/gen/ortools/constraint_solver/routing_enums.pb.h " + + "ortools/gen/ortools/constraint_solver/routing_parameters.pb.h " + + "ortools/gen/ortools/constraint_solver/search_limit.pb.h " + + "ortools/gen/ortools/constraint_solver/solver_parameters.pb.h " + ), + }, + { + "output_dir": "cpp", + "project name": "OR-Tools", + "title": "C++ Reference", + "doxyfile": "cpp.doxy.in", + "headerfile": "default.header.html.in", + "footerfile": "default.footer.html.in", + "styleSheetfile": "default.styleSheet.css.in", + "input_files": "ortools " + "tools/doc", + }, + { + "output_dir": "dotnet", + "project name": "OR-Tools", + "title": ".Net Reference", + "doxyfile": "dotnet.doxy.in", + "headerfile": "dotnet.header.html.in", + "footerfile": "all.footer.html.in", + "styleSheetfile": "all.styleSheet.css.in", + "input_files": "ortools " + "tools/doc", + }, + { + "output_dir": "java", + "project name": "OR-Tools", + "title": "Java Reference", + "doxyfile": "java.doxy.in", + "headerfile": "java.header.html.in", + "footerfile": "all.footer.html.in", + "styleSheetfile": "all.styleSheet.css.in", + "input_files": "ortools " + "tools/doc", + }, + ] + return sections -if __name__ == '__main__': - version_file = open('Version.txt', 'r') - version_file_data = version_file.read() - version_file.close() - major_pattern = re.compile(r'OR_TOOLS_MAJOR=(\d)') - minor_pattern = re.compile(r'OR_TOOLS_MINOR=(\d)') - major = major_pattern.findall(version_file_data)[0] - minor = minor_pattern.findall(version_file_data)[0] +if __name__ == "__main__": + version_file = open("Version.txt", "r") + version_file_data = version_file.read() + version_file.close() + major_pattern = re.compile(r"OR_TOOLS_MAJOR=(\d)") + minor_pattern = re.compile(r"OR_TOOLS_MINOR=(\d)") + major = major_pattern.findall(version_file_data)[0] + minor = minor_pattern.findall(version_file_data)[0] - version_number = f'{major}.{minor}' - main(version_number) + version_number = f"{major}.{minor}" + main(version_number)