# Path: test/utils.py
# class ProjectTestMixin:
#     def setUp(self):
#         self.workdir = tempfile.TemporaryDirectory()
#         self.taskrc = os.path.join(self.workdir.name, ".taskrc")
#         with open(self.taskrc, "wt") as fd:
#             print("data.location={}".format(os.path.join(self.workdir.name, "tasks")), file=fd)
# 
#     def tearDown(self):
#         self.workdir.cleanup()
# 
# Path: egtlib/state.py
# class State:
#     """
#     Cached information about known projects.
#     """
# 
#     def __init__(self):
#         # Map project names to ProjectInfo objects
#         self.projects = {}
# 
#     def load(self, statedir: str = None) -> None:
#         if statedir is None:
#             statedir = self.get_state_dir()
# 
#         statefile = os.path.join(statedir, "state.json")
#         if os.path.exists(statefile):
#             # Load state from JSON file
#             with open(statefile, "rt") as fd:
#                 state = json.load(fd)
#             self.projects = state["projects"]
#             return
# 
#         # TODO: remove support for legacy format
#         statefile = os.path.join(statedir, "state")
#         if os.path.exists(statefile):
#             # Load state from legacy .ini file
#             from configparser import RawConfigParser
#             cp = RawConfigParser()
#             cp.read([statefile])
#             for secname in cp.sections():
#                 if secname.startswith("proj "):
#                     name = secname.split(None, 1)[1]
#                     fname = cp.get(secname, "fname")
#                     self.projects[name] = {"fname": fname}
#             return
# 
#     @classmethod
#     def rescan(cls, dirs: List[str], statedir: str = None) -> None:
#         """
#         Rebuild the state looking for files in the given directories.
# 
#         If statedir is None, the state is saved in the default state
#         directory. If it is not None, it is the directory in which state is to
#         be saved.
#         """
#         if statedir is None:
#             statedir = cls.get_state_dir()
# 
#         # Read and detect duplicates
#         projects: Dict[str, dict] = {}
#         for dirname in dirs:
#             for fname in scan(dirname):
#                 try:
#                     p = Project.from_file(fname)
#                 except Exception as e:
#                     log.exception("%s: failed to parse: %s", fname, str(e))
#                     continue
#                 if p.name in projects:
#                     log.warn("%s: project %s already exists in %s: skipping", fname, p.name, projects[p.name]["fname"])
#                 else:
#                     projects[p.name] = {"fname": p.abspath}
# 
#         # Log the difference with the old info
#         # old_projects = set(self.projects.keys())
#         # for name, p in new_projects.items():
#         #     old_projects.discard(name)
#         #     op = self.projects.get(name, None)
#         #     if op is None:
#         #         log.info("add %s: %s", name, p["fname"])
#         #     elif op["fname"] != p["fname"]:
#         #         log.info("mv %s: %s -> %s", name, p["fname"], p["fname"])
#         #     else:
#         #         log.info("hit %s: %s", name, p["fname"])
#         # for name in old_projects:
#         #     log.info("rm %s", name)
# 
#         # Commit the new project set
#         statefile = os.path.join(statedir, "state.json")
#         with atomic_writer(statefile, "wt") as fd:
#             json.dump({
#                 "projects": projects
#             }, fd, indent=1)
# 
#         # Clean up old version of state file
#         old_statefile = os.path.join(statedir, "state")
#         if os.path.exists(old_statefile):
#             log.warn("%s: legacy state file removed", old_statefile)
#             os.unlink(old_statefile)
# 
#         # TODO: scan statedir removing project-$NAME.json files for all
#         # projects that disappeared.
# 
#         log.debug("%s: new state written", statefile)
# 
#     @classmethod
#     def get_state_dir(cls) -> str:
#         return BaseDirectory.save_data_path('egt')
# 
# Path: egtlib/commands.py
# class Completion(Command):
#     """
#     Tab completion support
#     """
#     def main(self):
#         if not self.args.subcommand:
#             raise CommandError("Usage: egt completion {commands|projects|tags}")
#         if self.args.subcommand == "commands":
#             for c in Command.COMMANDS:
#                 print(c.get_name())
#         elif self.args.subcommand == "projects":
#             e = self.make_egt()
#             names = e.project_names
#             for n in names:
#                 print(n)
#         elif self.args.subcommand == "tags":
#             e = self.make_egt()
#             res = set()
#             for p in e.projects:
#                 res |= p.tags
#             for n in sorted(res):
#                 print(n)
#         else:
#             raise CommandError("Usage: egt completion {commands|projects|tags}")
# 
#     @classmethod
#     def add_args(cls, subparser):
#         super().add_args(subparser)
#         subparser.add_argument("subcommand", nargs="?", default=None, help="command for which to provide completion")


import unittest
import os
import egtlib
        import tarfile
from unittest.mock import Mock, patch
from io import StringIO
from .utils import ProjectTestMixin
from configparser import ConfigParser
from egtlib.state import State
from egtlib.commands import Completion
# coding: utf8

body_p = """Name: test

2016
15 march: 9:00-9:30
 - wrote unit tests


# Path: test/utils.py
# class ProjectTestMixin:
#     def setUp(self):
#         self.workdir = tempfile.TemporaryDirectory()
#         self.taskrc = os.path.join(self.workdir.name, ".taskrc")
#         with open(self.taskrc, "wt") as fd:
#             print("data.location={}".format(os.path.join(self.workdir.name, "tasks")), file=fd)
# 
#     def tearDown(self):
#         self.workdir.cleanup()
# 
# Path: egtlib/state.py
# class State:
#     """
#     Cached information about known projects.
#     """
# 
#     def __init__(self):
#         # Map project names to ProjectInfo objects
#         self.projects = {}
# 
#     def load(self, statedir: str = None) -> None:
#         if statedir is None:
#             statedir = self.get_state_dir()
# 
#         statefile = os.path.join(statedir, "state.json")
#         if os.path.exists(statefile):
#             # Load state from JSON file
#             with open(statefile, "rt") as fd:
#                 state = json.load(fd)
#             self.projects = state["projects"]
#             return
# 
#         # TODO: remove support for legacy format
#         statefile = os.path.join(statedir, "state")
#         if os.path.exists(statefile):
#             # Load state from legacy .ini file
#             from configparser import RawConfigParser
#             cp = RawConfigParser()
#             cp.read([statefile])
#             for secname in cp.sections():
#                 if secname.startswith("proj "):
#                     name = secname.split(None, 1)[1]
#                     fname = cp.get(secname, "fname")
#                     self.projects[name] = {"fname": fname}
#             return
# 
#     @classmethod
#     def rescan(cls, dirs: List[str], statedir: str = None) -> None:
#         """
#         Rebuild the state looking for files in the given directories.
# 
#         If statedir is None, the state is saved in the default state
#         directory. If it is not None, it is the directory in which state is to
#         be saved.
#         """
#         if statedir is None:
#             statedir = cls.get_state_dir()
# 
#         # Read and detect duplicates
#         projects: Dict[str, dict] = {}
#         for dirname in dirs:
#             for fname in scan(dirname):
#                 try:
#                     p = Project.from_file(fname)
#                 except Exception as e:
#                     log.exception("%s: failed to parse: %s", fname, str(e))
#                     continue
#                 if p.name in projects:
#                     log.warn("%s: project %s already exists in %s: skipping", fname, p.name, projects[p.name]["fname"])
#                 else:
#                     projects[p.name] = {"fname": p.abspath}
# 
#         # Log the difference with the old info
#         # old_projects = set(self.projects.keys())
#         # for name, p in new_projects.items():
#         #     old_projects.discard(name)
#         #     op = self.projects.get(name, None)
#         #     if op is None:
#         #         log.info("add %s: %s", name, p["fname"])
#         #     elif op["fname"] != p["fname"]:
#         #         log.info("mv %s: %s -> %s", name, p["fname"], p["fname"])
#         #     else:
#         #         log.info("hit %s: %s", name, p["fname"])
#         # for name in old_projects:
#         #     log.info("rm %s", name)
# 
#         # Commit the new project set
#         statefile = os.path.join(statedir, "state.json")
#         with atomic_writer(statefile, "wt") as fd:
#             json.dump({
#                 "projects": projects
#             }, fd, indent=1)
# 
#         # Clean up old version of state file
#         old_statefile = os.path.join(statedir, "state")
#         if os.path.exists(old_statefile):
#             log.warn("%s: legacy state file removed", old_statefile)
#             os.unlink(old_statefile)
# 
#         # TODO: scan statedir removing project-$NAME.json files for all
#         # projects that disappeared.
# 
#         log.debug("%s: new state written", statefile)
# 
#     @classmethod
#     def get_state_dir(cls) -> str:
#         return BaseDirectory.save_data_path('egt')
# 
# Path: egtlib/commands.py
# class Completion(Command):
#     """
#     Tab completion support
#     """
#     def main(self):
#         if not self.args.subcommand:
#             raise CommandError("Usage: egt completion {commands|projects|tags}")
#         if self.args.subcommand == "commands":
#             for c in Command.COMMANDS:
#                 print(c.get_name())
#         elif self.args.subcommand == "projects":
#             e = self.make_egt()
#             names = e.project_names
#             for n in names:
#                 print(n)
#         elif self.args.subcommand == "tags":
#             e = self.make_egt()
#             res = set()
#             for p in e.projects:
#                 res |= p.tags
#             for n in sorted(res):
#                 print(n)
#         else:
#             raise CommandError("Usage: egt completion {commands|projects|tags}")
# 
#     @classmethod
#     def add_args(cls, subparser):
#         super().add_args(subparser)
#         subparser.add_argument("subcommand", nargs="?", default=None, help="command for which to provide completion")


# Path: test/test_commands.py
import unittest
import os
import egtlib
        import tarfile
from unittest.mock import Mock, patch
from io import StringIO
from .utils import ProjectTestMixin
from configparser import ConfigParser
from egtlib.state import State
from egtlib.commands import Completion

# coding: utf8

body_p = """Name: test

2016
15 march: 9:00-9:30
 - wrote unit tests


Write more unit tests