code: func NewProject(context *Context, runtime RuntimeProject, parseOptions *config.ParseOptions) *Project {
  	p := &Project{
  		context:        context,
  		runtime:        runtime,
  		ParseOptions:   parseOptions,
  		ServiceConfigs: config.NewServiceConfigs(),
  		VolumeConfigs:  make(map[string]*config.VolumeConfig),
  		NetworkConfigs: make(map[string]*config.NetworkConfig),
  	}
  
  	if context.LoggerFactory == nil {
  		context.LoggerFactory = &logger.NullLogger{}
  	}
  
  	if context.ResourceLookup == nil {
  		context.ResourceLookup = &lookup.FileResourceLookup{}
  	}
  
  	if context.EnvironmentLookup == nil {
  		var envPath, absPath, cwd string
  		var err error
  		if len(context.ComposeFiles) > 0 {
  			absPath, err = filepath.Abs(context.ComposeFiles[0])
  			dir, _ := path.Split(absPath)
  			envPath = filepath.Join(dir, ".env")
  		} else {
  			cwd, err = os.Getwd()
  			envPath = filepath.Join(cwd, ".env")
  		}
  
  		if err != nil {
  			log.Errorf("Could not get the rooted path name to the current directory: %v", err)
  			return nil
  		}
  		context.EnvironmentLookup = &lookup.ComposableEnvLookup{
  			Lookups: []config.EnvironmentLookup{
  				&lookup.EnvfileLookup{
  					Path: envPath,
  				},
  				&lookup.OsEnvLookup{},
  			},
  		}
  	}
  
  	context.Project = p
  
  	p.listeners = []chan<- events.Event{NewDefaultListener(p)}
  
  	return p
  }
docs: // NewProject creates a new project with the specified context.