text: # built-in
  import json
  from collections import OrderedDict
  from hashlib import sha256
  from pathlib import Path
  from typing import Optional
  
  # external
  import attr
  from dephell_discover import Root as PackageRoot
  from dephell_pythons import Pythons
  from dephell_specifier import RangeSpecifier
  
  # app
  from ..controllers import RepositoriesRegistry
  from ..models import RootDependency
  from ..repositories import WarehouseBaseRepo, WarehouseLocalRepo
  from .pipfile import PIPFileConverter
  
  
  # https://stackoverflow.com/a/23820416
  # https://github.com/pypa/pipfile/blob/master/examples/Pipfile.lock
  # https://github.com/pypa/pipfile/blob/master/pipfile/api.py
  
  
  @attr.s()
  class PIPFileLockConverter(PIPFileConverter):
      lock = attr.ib(type=bool, default=True)
  
      def can_parse(self, path: Path, content: Optional[str] = None) -> bool:
          if isinstance(path, str):
              path = Path(path)
          if content:
              return ('pipfile-spec' in content and 'sha256' in content)
          else:
              return (path.name == 'Pipfile.lock')
  
      def loads(self, content) -> RootDependency:
          doc = json.loads(content, object_pairs_hook=OrderedDict)
          deps = []
          root = RootDependency(
              package=PackageRoot(path=self.project_path or Path()),
          )
  
          repo = RepositoriesRegistry()
          for repo_info in doc.get('_meta', {}).get('sources', []):
              repo.add_repo(name=repo_info['name'], url=repo_info['url'])
          repo.attach_config()
  
          python = doc.get('_meta', {}).get('requires', {}).get('python_version', '')
          if python not in {'', '*'}:
              root.python = RangeSpecifier('==' + python)
  
          for section, is_dev in [('default', False), ('develop', True)]:
              for name, content in doc.get(section, {}).items():
                  subdeps = self._make_deps(root, name, content)
                  # set repo
                  if 'index' in content:
                      dep_repo = repo.make(name=content['index'])
                  else:
                      dep_repo = repo
                  for dep in subdeps:
                      if isinstance(dep.repo, WarehouseBaseRepo):
                          dep.repo = dep_repo
                  # set envs
                  for dep in subdeps:
                      dep.envs = {'dev'} if is_dev else {'main'}
                  deps.extend(subdeps)
          root.attach_dependencies(deps)
          return root
  
      def dumps(self, reqs, project: RootDependency, content=None) -> str:
          packages = {True: OrderedDict(), False: OrderedDict()}
          for req in reqs:
              packages[req.is_dev][req.raw_name] = dict(self._format_req(req=req))
  
          # get repos
          repos = []
          added_repos = set()
          for req in reqs:
              if not isinstance(req.dep.repo, WarehouseBaseRepo):
                  continue
              for repo in req.dep.repo.repos:
                  if repo.from_config:
                      continue
                  if repo.name in added_repos:
                      continue
                  # https://github.com/pypa/pipenv/issues/2231
                  if isinstance(repo, WarehouseLocalRepo):
                      continue
                  added_repos.add(repo.name)
                  repos.append(OrderedDict([
                      ('url', repo.pretty_url),
                      ('verify_ssl', repo.pretty_url.startswith('https://')),
                      ('name', repo.name),
                  ]))
          # pipenv doesn't work without explicit repo
          if not repos:
              repos.append(OrderedDict([
                  ('url', 'https://pypi.org/simple/'),
                  ('verify_ssl', True),
                  ('name', 'pypi'),
              ]))
  
          python = Pythons(abstract=True).get_by_spec(project.python)
          data = OrderedDict([
              ('_meta', OrderedDict([
                  ('sources', repos),
                  ('requires', {'python_version': str(python.version)}),
              ])),
              ('default', packages[False]),
              ('develop', packages[True]),
          ])
          data['_meta']['hash'] = {'sha256': self._get_hash(data)}
          data['_meta']['pipfile-spec'] = 6
          return json.dumps(data, indent=4, separators=(',', ': '))
  
      @staticmethod
      def _get_hash(data: dict) -> str:
          content = json.dumps(data, sort_keys=True, separators=(',', ':'))
          return sha256(content.encode('utf8')).hexdigest()
  
      def _format_req(self, req):
          result = dict()
          for name, value in req:
              if name == 'rev':
                  name = 'ref'
              if name in self.fields:
                  result[name] = value
          if isinstance(req.dep.repo, WarehouseBaseRepo) and req.dep.repo.name != 'pypi':
              result['index'] = req.dep.repo.name
          return result
  