pipfile.py 1.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162
  1. """Simplistic parsing of Pipfile dependency files
  2. This only extracts a small subset of the information present in a Pipfile,
  3. as needed for the purposes of this library.
  4. """
  5. from utils import is_string
  6. import pytoml
  7. class PipfileRequirement(object):
  8. def __init__(self, name):
  9. self.name = name
  10. self.editable = False
  11. self.vcs = None
  12. self.vcs_uri = None
  13. self.version = None
  14. self.markers = None
  15. self.provenance = None # a tuple of (file name, line)
  16. @classmethod
  17. def from_dict(cls, name, requirement_dict, pos_in_toml):
  18. req = cls(name)
  19. req.version = requirement_dict.get('version')
  20. req.editable = requirement_dict.get('editable', False)
  21. for vcs in ['git', 'hg', 'svn', 'bzr']:
  22. if vcs in requirement_dict:
  23. req.vcs = vcs
  24. req.vcs_uri = requirement_dict[vcs]
  25. break
  26. req.markers = requirement_dict.get('markers')
  27. # proper file name to be injected into provenance by the calling code
  28. req.provenance = ('Pipfile', pos_in_toml[0], pos_in_toml[0])
  29. return req
  30. def val_with_pos(kind, text, value, pos):
  31. return (value, pos)
  32. def parse(file_contents):
  33. data = pytoml.loads(file_contents, translate=val_with_pos)
  34. sections = ['packages', 'dev-packages']
  35. res = dict.fromkeys(sections)
  36. for section in sections:
  37. if section not in data:
  38. continue
  39. section_data = data[section]
  40. res[section] = [
  41. PipfileRequirement.from_dict(
  42. name,
  43. value if not is_string(value) else {'version': value},
  44. pos,
  45. )
  46. for name, (value, pos) in sorted(section_data.items())
  47. ]
  48. return res