123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207 |
- # -*- coding: utf-8 -*-
- from __future__ import unicode_literals, absolute_import
- from time import time
- from uuid import uuid5, NAMESPACE_URL
- from six import iteritems
- from six.moves.urllib.parse import urlencode
- def clean(data):
- """Remove all keys where value is None"""
- return dict((k, v) for k, v in iteritems(data) if v is not None)
- DEFAULT_VARS = {
- "string": "",
- "integer": 0,
- "number": 0,
- }
- class Request(object):
- """Wraps a Swagger operation into a Postman Request"""
- def __init__(self, collection, path, params, method, operation):
- self.collection = collection
- self.path = path
- self.params = params
- self.method = method.upper()
- self.operation = operation
- @property
- def id(self):
- seed = str(" ".join((self.method, self.url)))
- return str(uuid5(self.collection.uuid, seed))
- @property
- def url(self):
- return self.collection.api.base_url.rstrip("/") + self.path
- @property
- def headers(self):
- headers = {}
- # Handle content-type
- if self.method != "GET":
- consumes = self.collection.api.__schema__.get("consumes", [])
- consumes = self.operation.get("consumes", consumes)
- if len(consumes):
- headers["Content-Type"] = consumes[-1]
- # Add all parameters headers
- for param in self.operation.get("parameters", []):
- if param["in"] == "header":
- headers[param["name"]] = param.get("default", "")
- # Add security headers if needed (global then local)
- for security in self.collection.api.__schema__.get("security", []):
- for key, header in iteritems(self.collection.apikeys):
- if key in security:
- headers[header] = ""
- for security in self.operation.get("security", []):
- for key, header in iteritems(self.collection.apikeys):
- if key in security:
- headers[header] = ""
- lines = [":".join(line) for line in iteritems(headers)]
- return "\n".join(lines)
- @property
- def folder(self):
- if "tags" not in self.operation or len(self.operation["tags"]) == 0:
- return
- tag = self.operation["tags"][0]
- for folder in self.collection.folders:
- if folder.tag == tag:
- return folder.id
- def as_dict(self, urlvars=False):
- url, variables = self.process_url(urlvars)
- return clean(
- {
- "id": self.id,
- "method": self.method,
- "name": self.operation["operationId"],
- "description": self.operation.get("summary"),
- "url": url,
- "headers": self.headers,
- "collectionId": self.collection.id,
- "folder": self.folder,
- "pathVariables": variables,
- "time": int(time()),
- }
- )
- def process_url(self, urlvars=False):
- url = self.url
- path_vars = {}
- url_vars = {}
- params = dict((p["name"], p) for p in self.params)
- params.update(
- dict((p["name"], p) for p in self.operation.get("parameters", []))
- )
- if not params:
- return url, None
- for name, param in iteritems(params):
- if param["in"] == "path":
- url = url.replace("{%s}" % name, ":%s" % name)
- path_vars[name] = DEFAULT_VARS.get(param["type"], "")
- elif param["in"] == "query" and urlvars:
- default = DEFAULT_VARS.get(param["type"], "")
- url_vars[name] = param.get("default", default)
- if url_vars:
- url = "?".join((url, urlencode(url_vars)))
- return url, path_vars
- class Folder(object):
- def __init__(self, collection, tag):
- self.collection = collection
- self.tag = tag["name"]
- self.description = tag["description"]
- @property
- def id(self):
- return str(uuid5(self.collection.uuid, str(self.tag)))
- @property
- def order(self):
- return [r.id for r in self.collection.requests if r.folder == self.id]
- def as_dict(self):
- return clean(
- {
- "id": self.id,
- "name": self.tag,
- "description": self.description,
- "order": self.order,
- "collectionId": self.collection.id,
- }
- )
- class PostmanCollectionV1(object):
- """Postman Collection (V1 format) serializer"""
- def __init__(self, api, swagger=False):
- self.api = api
- self.swagger = swagger
- @property
- def uuid(self):
- return uuid5(NAMESPACE_URL, self.api.base_url)
- @property
- def id(self):
- return str(self.uuid)
- @property
- def requests(self):
- if self.swagger:
- # First request is Swagger specifications
- yield Request(
- self,
- "/swagger.json",
- {},
- "get",
- {
- "operationId": "Swagger specifications",
- "summary": "The API Swagger specifications as JSON",
- },
- )
- # Then iter over API paths and methods
- for path, operations in iteritems(self.api.__schema__["paths"]):
- path_params = operations.get("parameters", [])
- for method, operation in iteritems(operations):
- if method != "parameters":
- yield Request(self, path, path_params, method, operation)
- @property
- def folders(self):
- for tag in self.api.__schema__["tags"]:
- yield Folder(self, tag)
- @property
- def apikeys(self):
- return dict(
- (name, secdef["name"])
- for name, secdef in iteritems(
- self.api.__schema__.get("securityDefinitions")
- )
- if secdef.get("in") == "header" and secdef.get("type") == "apiKey"
- )
- def as_dict(self, urlvars=False):
- return clean(
- {
- "id": self.id,
- "name": " ".join((self.api.title, self.api.version)),
- "description": self.api.description,
- "order": [r.id for r in self.requests if not r.folder],
- "requests": [r.as_dict(urlvars=urlvars) for r in self.requests],
- "folders": [f.as_dict() for f in self.folders],
- "timestamp": int(time()),
- }
- )
|