input: 
  from typing import Any, Dict, List, Set
  
  class Environment:
      """
      Create an Environment class that can execute and analyze Python code. The environment includes a set of predefined global variables and functions, as well as the ability to add additional global variables. The environment can execute Python code and analyze it for variable usage and imports. The environment also includes a stdout object that can be used to capture and display output from executed code.
  
      >>> env = Environment('/path/to/files')
      >>> env.execute('example.py', 'print("Hello, World!")')
      Executing example.py False
      varsed used: ['print'] set: [] imported: []
      >>> print(env.globals['FILES'].list_dir('.'))
      ['example.py']
      """
      extra_globals: Dict[str, Any] = {}
      active: Set['Environment'] = weakref.WeakSet()
      predefined_names: Set[str] = {"parsed"}
  
      def __init__(self, path: str):
          self.path = path
          self.globals: Dict[str, Any] = {
              "print": jsonify_print,
              "print_expr": jsonify_print_expr,
              "jsonify": jsonify,
              "jsonify_print": jsonify_print,
              "listdir": stdlib.listdir,
              "__builtins__": __builtins__,
              "FILES": stdlib.FilesDict(self.path),
          }
          for name in stdlib.builtin_names:
              self.globals[name] = getattr(stdlib, name)
          self._cached_analysis: Dict[str, Dict[str, Any]] = {}
          self.active.add(self)
  
      def init_commands(self) -> List['FileEdit']:
          """Returns a list of commands that represent the existing state of the filesystem"""
          for path in os.listdir(self.path):
              if path.endswith(".json"):
                  continue
              if not os.path.isfile(os.path.join(self.path, path)):
                  continue
              try:
                  with open(os.path.join(self.path, path), "r") as fp:
                      content = fp.read()
                  yield FileEdit(filename=path, content=content, external_edit=True)
              except UnicodeDecodeError:
                  pass
  
      def fixup_globals(self):
          for name, value in self.extra_globals.items():
              self.globals.setdefault(name, value)
  
      def execute(self, filename: str, content: str, subexpressions: bool = False):
          print("Executing", filename, subexpressions)
          self.fixup_globals()
          stdout = Stdout()
          compiled = None
          try:
              parsed = ast.parse(content, filename, mode='exec')
              RewriteExprToPrint(subexpressions).walk(parsed)
              var_inspect = VariableInspector()
              var_inspect.walk(parsed)
              print("varsed used:", sorted(var_inspect.used), "set:", sorted(var_inspect.set), "imported:", var_inspect.imports)
              compiled = compile(parsed, filename, 'exec')
          except:
              stdout.write(traceback.format_exc())
  
          def displayhook(value):
              stdout.write_repr(value)
  
          orig_displayhook = sys.displayhook
          sys.displayhook = displayhook
          orig_stdout = sys.stdout
          orig_stderr = sys.stderr
          sys.stdout = stdout
          sys.stderr = stdout
          self.globals["parsed"] = parsed
          self.globals["ast"] = ast
          globals_before = self.globals.copy()
          start = time.time()
          try:
              try:
                  if compiled:
                      exec(compiled, self.globals)
              except:
                  traceback.print_exc()
          finally:
              end = time.time()
              sys.displayhook = orig_displayhook
              sys.stdout = orig_stdout
              sys.stderr = orig_stderr
          local_scope = dict(
              (name, value)
              for name, value in self.globals.items()
              if name not in globals_before or globals_before[name] is not value)
          defines = dict(
              (key, {
                  "json": jsonify(local_scope[key]),
                  "type": str(type(local_scope[key])),
              })
              for key in local_scope
              if not isinstance(local_scope[key], types.ModuleType))
          command = Execution(
              filename=filename,
              content=content,
              emitted=stdout.emitted,
              defines=defines,
              start_time=int(start * 1000),
              end_time=int(end * 1000),
              exec_time=int((end - start) * 1000),
              with_subexpressions=subexpressions,
          )
          send(command)
  
      def analyze(self, filename: str, content: str):
          print("Analyzing", filename)
          properties = {}
          try:
              parsed = ast.parse(content, filename, mode='exec')
              var_inspect = VariableInspector()
              var_inspect.walk(parsed)
          except:
              return
              properties["parse_error"] = jsonify(traceback.format_exc())
          else:
              properties = var_inspect.json
          if properties != self._cached_analysis.get(filename):
              self._cached_analysis[filename] = properties
              send(Analysis(filename=filename, content=content, properties=properties))
  
output:     
      def add_global(self, name: str, value: Any):
          self.extra_globals[name] = value
          self.fixup_globals()
  
      def remove_global(self, name: str):
          if name in self.extra_globals:
              del self.extra_globals[name]
          self.fixup_globals()
  
      def list_globals(self) -> List[str]:
          return sorted(self.globals.keys())
  
      def clear_globals(self):
          self.extra_globals.clear()
          self.fixup_globals()
  
      def get_global(self, name: str) -> Any:
          return self.globals.get(name)
  
      def set_global(self, name: str, value: Any):
          self.globals[name] = value
  
      def get_analysis_cache(self, filename: str) -> Dict[str, Any]:
          return self._cached_analysis.get(filename, {})
  
      def clear_analysis_cache(self):
          self._cached_analysis.clear()
  
      def list_analysis_cache(self) -> List[str]:
          return sorted(self._cached_analysis.keys())
  
      def get_stdout(self) -> str:
          return self.globals["stdout"].getvalue()
  
      def clear_stdout(self):
          self.globals["stdout"].clear()
  