# Path: distance/_level.py
# class Level(Fragment):
# 
#     class_tag = 'Level'
#     default_container = Section(Magic[9])
# 
#     layers = ()
#     name = None
#     version = 3
# 
#     def _read_section_data(self, dbytes, sec):
#         if sec.magic != Magic[9]:
#             raise ValueError(f"Unexpected section: {sec.magic}")
#         self.name = sec.name
#         self.version = sec.version
# 
#         num_layers = sec.count
# 
#         self.content = self.classes.level_content.lazy_n_maybe(
#             dbytes, num_layers + 1)
#         if num_layers:
#             self.layers = LazySequence(
#                 (obj for obj in self.content if obj.class_tag == 'Layer'),
#                 num_layers)
# 
#     def _get_write_section(self, sec):
#         return Section(Magic[9], self.name, len(self.layers), self.version)
# 
#     def _visit_write_section_data(self, dbytes, sec):
#         if sec.magic != Magic[9]:
#             raise ValueError(f"Unexpected section: {sec.magic}")
#         for obj in self.content:
#             yield obj.visit_write(dbytes)
# 
#     @property
#     def settings(self):
#         try:
#             return self._settings
#         except AttributeError:
#             for obj in self.content:
#                 if obj.class_tag != 'Layer':
#                     s = obj
#                     break
#             else:
#                 s = None
#             self._settings = s
#             return s
# 
#     @settings.setter
#     def settings(self, s):
#         self._settings = s
# 
#     def _repr_detail(self):
#         supstr = super()._repr_detail()
#         if self.name:
#             return f" {self.name!r}{supstr}"
#         return supstr
# 
#     def visit_print(self, p):
#         with need_counters(p) as counters:
#             yield super().visit_print(p)
#             if counters:
#                 counters.print(p)
# 
#     def _print_type(self, p):
#         p(f"Level: {self.name!r} version {self.version}")
# 
#     def _visit_print_data(self, p):
#         yield super()._visit_print_data(p)
#         p(f"Level name: {self.name!r}")
# 
#     def _visit_print_children(self, p):
#         if self.settings is not None:
#             with p.tree_children(1):
#                 yield self.settings.visit_print(p)
#         for layer in self.layers:
#             yield layer.visit_print(p)
# 
# Path: distance/filter/remove.py
# class RemoveFilter(ObjectFilter):
# 
#     @classmethod
#     def add_args(cls, parser):
#         super().add_args(parser)
#         parser.add_argument(":type", action='append', default=[],
#                             help="Match object type (regex).")
#         parser.add_argument(":section", action='append', default=[],
#                             help="Match sections.")
#         parser.add_argument(":print", action='store_true', dest='print_',
#                             help="Print matching candidates and abort filter.")
#         parser.add_argument(":all", action='store_true',
#                             help="This is now the default and has been removed.")
#         parser.add_argument(":number", dest='numbers', action='append',
#                             type=int, default=[],
#                             help="Select by candidate number.")
#         parser.add_argument(":invert", action='store_true',
#                             help="Remove unmatched objects.")
# 
#     def __init__(self, args):
#         super().__init__(args)
#         self.print_ = args.print_
#         self.numbers = args.numbers
#         self.type_patterns = [re.compile(r) for r in args.type]
#         self.sections = {parse_section(arg).to_key() for arg in args.section}
#         self.invert = args.invert
#         self.num_matches = 0
#         self.matches = []
#         self.removed = []
# 
#     def _match_sections(self, obj):
#         for sec in obj.sections:
#             if sec.to_key() in self.sections:
#                 return True
#         for child in obj.children:
#             if self._match_sections(child):
#                 return True
#         return False
# 
#     def match_props(self, obj):
#         if not self.type_patterns and not self.sections:
#             return True
#         if self.type_patterns:
#             typename = obj.type
#             if any(r.search(typename) for r in self.type_patterns):
#                 return True
#         if self.sections:
#             if not obj.is_object_group and self._match_sections(obj):
#                 return True
#         return False
# 
#     def match(self, obj):
#         if self.match_props(obj):
#             num = self.num_matches
#             self.num_matches = num + 1
#             self.matches.append(obj)
#             if not self.numbers or num in self.numbers:
#                 return True
#         return False
# 
#     def filter_any_object(self, obj, levels):
#         remove = self.match(obj)
#         if self.invert:
#             remove = not remove
#         res = super().filter_any_object(obj, levels)
#         if remove:
#             self.removed.append(obj)
#             return ()
#         return res
# 
#     def post_filter(self, content):
#         if self.print_:
#             print_candidates(self.matches)
#             return False
#         return True
# 
#     def print_summary(self, p):
#         p(f"Removed matches: {len(self.removed)}")
#         num_objs, num_groups = count_objects(self.removed)
#         if num_objs != len(self.removed):
#             p(f"Removed objects: {num_objs}")
#             p(f"Removed groups: {num_groups}")


from argparse import Namespace
from distance import Level
from distance.filter import RemoveFilter
import unittest



def mkargs(maxrecurse=-1, type=[], numbers=[], section=[],
           print_=False, invert=False):
    return Namespace(**locals())


class RemoveTest(unittest.TestCase):

    def test_by_type(self):

# Path: distance/_level.py
# class Level(Fragment):
# 
#     class_tag = 'Level'
#     default_container = Section(Magic[9])
# 
#     layers = ()
#     name = None
#     version = 3
# 
#     def _read_section_data(self, dbytes, sec):
#         if sec.magic != Magic[9]:
#             raise ValueError(f"Unexpected section: {sec.magic}")
#         self.name = sec.name
#         self.version = sec.version
# 
#         num_layers = sec.count
# 
#         self.content = self.classes.level_content.lazy_n_maybe(
#             dbytes, num_layers + 1)
#         if num_layers:
#             self.layers = LazySequence(
#                 (obj for obj in self.content if obj.class_tag == 'Layer'),
#                 num_layers)
# 
#     def _get_write_section(self, sec):
#         return Section(Magic[9], self.name, len(self.layers), self.version)
# 
#     def _visit_write_section_data(self, dbytes, sec):
#         if sec.magic != Magic[9]:
#             raise ValueError(f"Unexpected section: {sec.magic}")
#         for obj in self.content:
#             yield obj.visit_write(dbytes)
# 
#     @property
#     def settings(self):
#         try:
#             return self._settings
#         except AttributeError:
#             for obj in self.content:
#                 if obj.class_tag != 'Layer':
#                     s = obj
#                     break
#             else:
#                 s = None
#             self._settings = s
#             return s
# 
#     @settings.setter
#     def settings(self, s):
#         self._settings = s
# 
#     def _repr_detail(self):
#         supstr = super()._repr_detail()
#         if self.name:
#             return f" {self.name!r}{supstr}"
#         return supstr
# 
#     def visit_print(self, p):
#         with need_counters(p) as counters:
#             yield super().visit_print(p)
#             if counters:
#                 counters.print(p)
# 
#     def _print_type(self, p):
#         p(f"Level: {self.name!r} version {self.version}")
# 
#     def _visit_print_data(self, p):
#         yield super()._visit_print_data(p)
#         p(f"Level name: {self.name!r}")
# 
#     def _visit_print_children(self, p):
#         if self.settings is not None:
#             with p.tree_children(1):
#                 yield self.settings.visit_print(p)
#         for layer in self.layers:
#             yield layer.visit_print(p)
# 
# Path: distance/filter/remove.py
# class RemoveFilter(ObjectFilter):
# 
#     @classmethod
#     def add_args(cls, parser):
#         super().add_args(parser)
#         parser.add_argument(":type", action='append', default=[],
#                             help="Match object type (regex).")
#         parser.add_argument(":section", action='append', default=[],
#                             help="Match sections.")
#         parser.add_argument(":print", action='store_true', dest='print_',
#                             help="Print matching candidates and abort filter.")
#         parser.add_argument(":all", action='store_true',
#                             help="This is now the default and has been removed.")
#         parser.add_argument(":number", dest='numbers', action='append',
#                             type=int, default=[],
#                             help="Select by candidate number.")
#         parser.add_argument(":invert", action='store_true',
#                             help="Remove unmatched objects.")
# 
#     def __init__(self, args):
#         super().__init__(args)
#         self.print_ = args.print_
#         self.numbers = args.numbers
#         self.type_patterns = [re.compile(r) for r in args.type]
#         self.sections = {parse_section(arg).to_key() for arg in args.section}
#         self.invert = args.invert
#         self.num_matches = 0
#         self.matches = []
#         self.removed = []
# 
#     def _match_sections(self, obj):
#         for sec in obj.sections:
#             if sec.to_key() in self.sections:
#                 return True
#         for child in obj.children:
#             if self._match_sections(child):
#                 return True
#         return False
# 
#     def match_props(self, obj):
#         if not self.type_patterns and not self.sections:
#             return True
#         if self.type_patterns:
#             typename = obj.type
#             if any(r.search(typename) for r in self.type_patterns):
#                 return True
#         if self.sections:
#             if not obj.is_object_group and self._match_sections(obj):
#                 return True
#         return False
# 
#     def match(self, obj):
#         if self.match_props(obj):
#             num = self.num_matches
#             self.num_matches = num + 1
#             self.matches.append(obj)
#             if not self.numbers or num in self.numbers:
#                 return True
#         return False
# 
#     def filter_any_object(self, obj, levels):
#         remove = self.match(obj)
#         if self.invert:
#             remove = not remove
#         res = super().filter_any_object(obj, levels)
#         if remove:
#             self.removed.append(obj)
#             return ()
#         return res
# 
#     def post_filter(self, content):
#         if self.print_:
#             print_candidates(self.matches)
#             return False
#         return True
# 
#     def print_summary(self, p):
#         p(f"Removed matches: {len(self.removed)}")
#         num_objs, num_groups = count_objects(self.removed)
#         if num_objs != len(self.removed):
#             p(f"Removed objects: {num_objs}")
#             p(f"Removed groups: {num_groups}")


# Path: tests/filter/test_remove.py
from argparse import Namespace
from distance import Level
from distance.filter import RemoveFilter
import unittest




def mkargs(maxrecurse=-1, type=[], numbers=[], section=[],
           print_=False, invert=False):
    return Namespace(**locals())


class RemoveTest(unittest.TestCase):

    def test_by_type(self):

        l = Level("tests/in/level/test-straightroad.bytes")