浏览代码

Automatische Code-Formatierung

- C11 jetzt mit Shortcuts
gc-server6 1 年之前
父节点
当前提交
d3d1cf90a9
共有 5 个文件被更改,包括 388 次插入207 次删除
  1. 315 179
      cognos11/c11_api.py
  2. 6 0
      cognos11/c11_export.py
  3. 32 0
      cognos11/c11_jobs.py
  4. 8 7
      pdf/pdf_merge.py
  5. 27 21
      pdf/pdf_test.py

+ 315 - 179
cognos11/c11_api.py

@@ -26,16 +26,16 @@ class c11_api:
         self.cfg = cfg
         self.webservice = cfg.cognos11.webservice
 
-        self.templates_dir = cfg.tasks_dir + '/scripts/templates'
+        self.templates_dir = cfg.tasks_dir + "/scripts/templates"
         self._env = jinja2.Environment(
             loader=jinja2.FileSystemLoader(self.templates_dir),
-            autoescape=jinja2.select_autoescape(['html', 'xml'])
+            autoescape=jinja2.select_autoescape(["html", "xml"]),
         )
         self.templates = {
-            'get_report': self._env.get_template('get_report.xml'),
-            'create_report': self._env.get_template('create_report.xml'),
-            'update_report': self._env.get_template('update_report.xml'),
-            'get_package': self._env.get_template('get_package.xml'),
+            "get_report": self._env.get_template("get_report.xml"),
+            "create_report": self._env.get_template("create_report.xml"),
+            "update_report": self._env.get_template("update_report.xml"),
+            "get_package": self._env.get_template("get_package.xml"),
         }
 
     @staticmethod
@@ -53,116 +53,186 @@ class c11_api:
 
         return base64.b64encode(version + chunks[-1]).decode("utf-8")
 
-    def login(self, user='Global1', password='Cognos#11'):
+    def login(self, user="Global1", password="Cognos#11"):
         credentials = {
             "parameters": [
                 {"name": "CAMNamespace", "value": "CognosEx"},
                 {"name": "h_CAM_action", "value": "logonAs"},
                 {"name": "CAMUsername", "value": user},
-                {"name": "CAMPassword", "value": password}
+                {"name": "CAMPassword", "value": password},
             ]
         }
         self.session = requests.Session()
         r = self.session.get(self.webservice)
-        self.headers = {'Content-Type': "application/json; charset=UTF-8", 'X-XSRF-TOKEN': self.session.cookies.get('XSRF-TOKEN')}
+        self.headers = {
+            "Content-Type": "application/json; charset=UTF-8",
+            "X-XSRF-TOKEN": self.session.cookies.get("XSRF-TOKEN"),
+        }
 
-        r = self.session.post(self.webservice + "v1/login", data=json.dumps(credentials), headers=self.headers)
+        r = self.session.post(
+            self.webservice + "v1/login",
+            data=json.dumps(credentials),
+            headers=self.headers,
+        )
 
-        self.caf = r.json()['cafContextId']
+        self.caf = r.json()["cafContextId"]
         self.cam = self.generate_token(r.cookies["usersessionid"])
         return self
 
     def get_folders(self):
         if len(self.folders) == 0:
-            self.folders.append({'id': '_dot_public_folders', 'name': 'Team Content'})
+            self.folders.append({"id": "_dot_public_folders", "name": "Team Content"})
             self.load_folder_list()
             self.save_config()
         return self.folders
 
     def save_config(self):
         os.makedirs(self.cfg.cognos11.config_dir, exist_ok=True)
-        with open(self.cfg.cognos11.folders_file, 'w') as fwh:
+        with open(self.cfg.cognos11.folders_file, "w") as fwh:
             json.dump(self.folders, fwh, indent=2)
-        with open(self.cfg.cognos11.reports_file, 'w') as fwh:
+        with open(self.cfg.cognos11.reports_file, "w") as fwh:
             json.dump(self.reports, fwh, indent=2)
-        with open(self.cfg.cognos11.jobs_file, 'w') as fwh:
+        with open(self.cfg.cognos11.jobs_file, "w") as fwh:
             json.dump(self.jobs, fwh, indent=2)
 
     def load_config_from_files(self):
-        with open(self.cfg.cognos11.folders_file, 'r') as frh:
+        with open(self.cfg.cognos11.folders_file, "r") as frh:
             self.folders = json.load(frh)
-        with open(self.cfg.cognos11.reports_file, 'r') as frh:
+        with open(self.cfg.cognos11.reports_file, "r") as frh:
             self.reports = json.load(frh)
-        with open(self.cfg.cognos11.jobs_file, 'w') as frh:
+        with open(self.cfg.cognos11.jobs_file, "w") as frh:
             self.jobs = json.load(frh)
 
-    def load_folder_list(self, folder_id='_dot_public_folders', prefix='Team Content'):
-        res = self.session.get(f"{self.webservice}v1/objects/{folder_id}/items", headers=self.headers)
-        folder_list = sorted(res.json()['data'], key=lambda x: x['defaultName'])
+    def load_folder_list(self, folder_id="_dot_public_folders", prefix="Team Content"):
+        fields = ",".join(
+            [
+                "id",
+                "defaultName",
+                "defaultDescription",
+                "type",
+                "target.id",
+                "target.searchPath",
+                "target.defaultName",                
+                "base.id",
+                "base.searchPath",
+                "base.defaultName",
+                "parameters"
+            ]
+        )
+        res = self.session.get(
+            f"{self.webservice}v1/objects/{folder_id}/items?fields={fields}", headers=self.headers
+        )
+        folder_list = sorted(res.json()["data"], key=lambda x: x["defaultName"])
         for f in folder_list:
-            if f['type'] == 'folder':
+            if f["type"] == "folder":
                 folder = {
-                    'id': f['id'],
-                    'name': prefix + '/' + f['defaultName'].replace('/', '-')
+                    "id": f["id"],
+                    "name": prefix + "/" + f["defaultName"].replace("/", "-"),
                 }
                 self.folders.append(folder)
-                self.load_folder_list(folder['id'], folder['name'])
-            elif f['type'] == 'report':
+                self.load_folder_list(folder["id"], folder["name"])
+            elif f["type"] in ("report", "reportView", "shortcut"):
                 report = {
-                    'id': f['id'],
-                    'name': f['defaultName'].replace('/', '-'),
-                    'path': prefix
+                    "id": f["id"],
+                    "name": f["defaultName"].replace("/", "-"),
+                    "description": f["defaultDescription"],
+                    "path": prefix,
+                    "type": f["type"],
                 }
+                if f["type"] == "shortcut":
+                    report["target_id"] = f["target"][0]["id"]
+                if f["type"] == "reportView":
+                    report["target_id"] = f["base"][0]["id"]
+                    report["parameters"] = {}
+                    params = [p for p in f["parameters"] if len(p["value"]) > 0]
+                    for p in params:
+                        report["parameters"][p["name"]] = dict([(v["use"], v["display"]) for v in p["value"]])
+                    # report["details"] = self.get_report_details(report["id"])
+                    # print(json.dumps(f, indent=2))
                 self.reports.append(report)
-            elif f['type'] == 'jobDefinition':
-                job = {
-                    'id': f['id'],
-                    'name': f['defaultName'],
-                    'path': prefix
-                }
-                job['details'] = self.get_job_details(job['id'])
+            elif f["type"] == "jobDefinition":
+                job = {"id": f["id"], "name": f["defaultName"], "path": prefix}
+                job["details"] = self.get_job_details(job["id"])
                 self.jobs.append(job)
 
-    def get_job_details(self, job_id):
-        fields = ",".join([
-            'userInterfaces,disabled',
-            'runInAdvancedViewer,modificationTime,canBurst',
-            'defaultPortalAction',
-            'base.defaultName,tags,target.searchPath,target.disabled',
-            'options,base.options'
-        ])
-        res = self.session.get(f"{self.webservice}v1/objects/{job_id}?fields={fields}", headers=self.headers)
-        job = res.json()['data'][0]
-        job.pop('_meta', None)
-        job.pop('id', None)
-        job.pop('type', None)
-        job.pop('defaultName', None)
-
-        fields2 = ",".join([
-            r'id,displaySequence,stepObject{defaultName}',
-            r'stepObject{id},stepObject{parameters}',
-            r'stepObject{canBurst},options,parameters'
-        ])
+    def get_report_details(self, object_id):
+        fields = ",".join(
+            [
+                "defaultDescription",
+                "options",
+                "executionPrompt",
+                "parameters",
+                "module.defaultName",
+                "module.ancestors",
+                "allowNotification",
+                "base.id",
+                "base.searchPath",
+                "base.defaultName",
+                "base.defaultDescription",
+                "base.ancestors",
+                "base.metadataModelPackage",
+                "base.module",
+            ]
+        )
+        res = self.session.get(
+            f"{self.webservice}v1/objects/{object_id}?fields={fields}",
+            headers=self.headers,
+        )
+        res = res.json()["data"][0]
+        res.pop("_meta", None)
+        res.pop("id", None)
+        res.pop("type", None)
+        res.pop("defaultName", None)
+
+        return res
+
+    def get_job_details(self, object_id):
+        fields = ",".join(
+            [
+                "userInterfaces", "disabled",
+                "runInAdvancedViewer", "modificationTime", "canBurst",
+                "defaultPortalAction",
+                "base.defaultName", "tags", "target.searchPath", "target.disabled",
+                "options", "base.options",
+            ]
+        )
+        res = self.session.get(
+            f"{self.webservice}v1/objects/{object_id}?fields={fields}",
+            headers=self.headers,
+        )
+        job = res.json()["data"][0]
+        job.pop("_meta", None)
+        job.pop("id", None)
+        job.pop("type", None)
+        job.pop("defaultName", None)
+
+        fields2 = ",".join(
+            [
+                r"id,displaySequence,stepObject{defaultName}",
+                r"stepObject{id},stepObject{parameters}",
+                r"stepObject{canBurst},options,parameters",
+            ]
+        )
         res = self.session.get(
-            f"{self.webservice}v1/objects/{job_id}/items?types=jobStepDefinition&fields={fields2}",
-            headers=self.headers
+            f"{self.webservice}v1/objects/{object_id}/items?types=jobStepDefinition&fields={fields2}",
+            headers=self.headers,
         )
-        steps = res.json()['data']
+        steps = res.json()["data"]
         for s in steps:
-            s.pop('_meta', None)
-            if s['stepObject'] is not None:
-                s['report_id'] = s['stepObject'][0]['id']
-            s.pop('stepObject', None)
-        job['steps'] = steps
+            s.pop("_meta", None)
+            if s["stepObject"] is not None:
+                s["report_id"] = s["stepObject"][0]["id"]
+            s.pop("stepObject", None)
+        job["steps"] = steps
         return job
 
     def get_report(self, report_id):
         self.get_folders()
-        report = [r for r in self.reports if r['id'] == report_id]
+        report = [r for r in self.reports if r["id"] == report_id]
         if len(report) == 0:
             return None
         report = report[0]
-        if 'meta' not in report:
+        if "meta" not in report:
             report = self.get_report_specs(report)
         return report
 
@@ -170,138 +240,180 @@ class c11_api:
         self.get_folders()
 
         if recursive:
-            res = [r for r in self.reports if r['path'].startswith(folder)]
+            res = [r for r in self.reports if r["path"].startswith(folder)]
         else:
-            res = [r for r in self.reports if r['path'] == folder]
+            res = [r for r in self.reports if r["path"] == folder]
 
         if specs:
             return [self.get_report_specs(r) for r in res]
         return res
 
     def get_report_specs(self, report):
+        report = self.get_report_filename(report)
         headers = {
-            'Content-Type': 'text/xml; charset=UTF-8',
-            'X-XSRF-TOKEN': self.headers['X-XSRF-TOKEN'],
-            'X-RsCMStoreID': report['id'],
-            'X-UseRsConsumerMode': 'true',
-            'SOAPAction': 'http://www.ibm.com/xmlns/prod/cognos/reportService/202004/'
+            "Content-Type": "text/xml; charset=UTF-8",
+            "X-XSRF-TOKEN": self.headers["X-XSRF-TOKEN"],
+            "X-RsCMStoreID": report["id"],
+            "X-UseRsConsumerMode": "true",
+            "SOAPAction": "http://www.ibm.com/xmlns/prod/cognos/reportService/202004/",
         }
-        soap = self.templates['get_report'].render(
-            {"caf": self.caf, "cam": self.cam,
-             "report": report, "format": 'XHTML',
-             "prompt": 'true', "tracking": "", "params": {}}
+        soap = self.templates["get_report"].render(
+            {
+                "caf": self.caf,
+                "cam": self.cam,
+                "report": report,
+                "format": "XHTML",
+                "prompt": "true",
+                "tracking": "",
+                "params": {},
+            }
         )
 
-        r = self.session.post(self.webservice + 'v1/reports', data=soap, headers=headers)
+        r = self.session.post(
+            self.webservice + "v1/reports", data=soap, headers=headers
+        )
         if r.status_code == 500:
-            bs = BeautifulSoup(r.text, 'xml')
-            report['error'] = bs.find_all('messageString')[0].string
-            logging.error(report['error'])
+            bs = BeautifulSoup(r.text, "xml")
+            report["error"] = bs.find_all("messageString")[0].string
+            logging.error(report["error"])
             return report
 
         parts = decoder.MultipartDecoder.from_response(r).parts
 
-        meta = {'required': {}, 'optional': {}}
-        bs = BeautifulSoup(parts[1].content, 'lxml')
-
-        for sv in bs.find_all('selectvalue'):
-            k = sv['parameter']
-            req = 'required' if sv['required'] == 'true' else 'optional'
-            v = dict([(opt['usevalue'], opt['displayvalue']) for opt in sv.find_all('selectoption')])
+        meta = {"required": {}, "optional": {}}
+        bs = BeautifulSoup(parts[1].content, "lxml")
+
+        for sv in bs.find_all("selectvalue"):
+            k = sv["parameter"]
+            req = "required" if sv["required"] == "true" else "optional"
+            v = dict(
+                [
+                    (opt["usevalue"], opt["displayvalue"])
+                    for opt in sv.find_all("selectoption")
+                ]
+            )
             meta[req][k] = v
 
-        for sv in bs.find_all('selectdate'):
-            k = sv['parameter']
-            req = 'required' if sv['required'] == 'true' else 'optional'
-            v = dict([(opt['usevalue'], opt.get('displayvalue', '')) for opt in sv.find_all('selectoption')])
+        for sv in bs.find_all("selectdate"):
+            k = sv["parameter"]
+            req = "required" if sv["required"] == "true" else "optional"
+            v = dict(
+                [
+                    (opt["usevalue"], opt.get("displayvalue", ""))
+                    for opt in sv.find_all("selectoption")
+                ]
+            )
             meta[req][k] = v
-        filename = self.cfg.xml_dir + f"/{report['path']}/{report['name']}.json"
+        filename = self.cfg.cognos11.config_dir + f"/params/{report['path']}/{report['name']}.json"
         os.makedirs(os.path.dirname(filename), exist_ok=True)
-        json.dump(meta, open(filename, 'w'), indent=2)
-        report['meta'] = meta
-        report['spec'] = parts[2].text
-        path = report['path'].replace('Team Content/ReportOutput', '')
-        report['filename'] = f"{self.cfg.cognos11.reportoutput_dir}/{path}/{report['name']}.pdf"
-        report['format'] = 'PDF'
-        if report['name'][-5:].lower() == '.xlsx':
-            report['format'] = 'spreadsheetML'
-            report['filename'] = report['filename'][:-4]
-
-        report['params'] = list(re.findall(r'\[([^\]]+)\]', report['filename']))
-        for i, p in enumerate(report['params']):
-            report['filename'] = report['filename'].replace('[' + p + ']', '{' + str(i) + '}')
+        json.dump(meta, open(filename, "w"), indent=2)
+        report["meta"] = meta
+        report["spec"] = parts[2].text
+        return report
+
+    def get_report_filename(self, report):
+        path = report["path"].replace("Team Content/ReportOutput", "")
+        report[
+            "filename"
+        ] = f"{self.cfg.cognos11.reportoutput_dir}/{path}/{report['name']}.pdf"
+        report["format"] = "PDF"
+        if report["name"][-5:].lower() == ".xlsx":
+            report["format"] = "spreadsheetML"
+            report["filename"] = report["filename"][:-4]
+
+        report["params"] = list(re.findall(r"\[([^\]]+)\]", report["filename"]))
+        for i, p in enumerate(report["params"]):
+            report["filename"] = report["filename"].replace(
+                "[" + p + "]", "{" + str(i) + "}"
+            )
         return report
 
     def request_unstubbed(self, report_id):
         report = self.get_report(report_id)
-        if 'spec' not in report:
-            return ''
-        payload = json.dumps({'reportspec_stubbed': report['spec'], 'storeid': report['id']})
+        if "spec" not in report:
+            return ""
+        payload = json.dumps(
+            {"reportspec_stubbed": report["spec"], "storeid": report["id"]}
+        )
 
         headers = {
-            'Content-Type': 'application/json; charset=UTF-8',
-            'X-XSRF-TOKEN': self.session.cookies.get('XSRF-TOKEN'),
-            'authenticityToken': self.cam,
-            'X-UseRsConsumerMode': 'true',
-            'cafContextId': self.caf
+            "Content-Type": "application/json; charset=UTF-8",
+            "X-XSRF-TOKEN": self.session.cookies.get("XSRF-TOKEN"),
+            "authenticityToken": self.cam,
+            "X-UseRsConsumerMode": "true",
+            "cafContextId": self.caf,
         }
 
-        r = self.session.post(self.webservice + 'v1/reports/unstubreport', data=payload, headers=headers)
-        unstubbed = json.loads(r.text)['reportspec_full']
-        unstubbed = re.sub(r' iid="[^"]*"', '', unstubbed)
+        r = self.session.post(
+            self.webservice + "v1/reports/unstubreport", data=payload, headers=headers
+        )
+        unstubbed = json.loads(r.text)["reportspec_full"]
+        unstubbed = re.sub(r' iid="[^"]*"', "", unstubbed)
 
-        bs = BeautifulSoup(unstubbed, 'xml')
-        for xa in bs.find_all('XMLAttributes'):
+        bs = BeautifulSoup(unstubbed, "xml")
+        for xa in bs.find_all("XMLAttributes"):
             if (
-                xa.find_all('XMLAttribute', {'name': 'RS_dataType'}) or
-                xa.find_all('XMLAttribute', {'name': 'RS_CreateExtendedDataItems'}) or
-                xa.find_all('XMLAttribute', {'name': 'RS_legacyDrillDown'})
+                xa.find_all("XMLAttribute", {"name": "RS_dataType"})
+                or xa.find_all("XMLAttribute", {"name": "RS_CreateExtendedDataItems"})
+                or xa.find_all("XMLAttribute", {"name": "RS_legacyDrillDown"})
             ):
                 continue
-            if xa.find_all('XMLAttribute', {'name': 'supportsDefaultDataFormatting'}):
-                for xa2 in xa.find_all('XMLAttribute'):
-                    if xa2.attrs['name'] != 'supportsDefaultDataFormatting':
+            if xa.find_all("XMLAttribute", {"name": "supportsDefaultDataFormatting"}):
+                for xa2 in xa.find_all("XMLAttribute"):
+                    if xa2.attrs["name"] != "supportsDefaultDataFormatting":
                         xa2.decompose()
                 continue
             xa.decompose()
-        for cti in bs.find_all('crosstabIntersection'):
+        for cti in bs.find_all("crosstabIntersection"):
             if len(list(cti.children)) == 0:
                 cti.decompose()
         unstubbed_report = str(bs)
-        unstubbed_report = prettify_xml(unstubbed_report).replace("'", '"')
+        unstubbed_report = prettify_xml(unstubbed_report).replace("'", """)
         return unstubbed_report
 
     def get_report_headers(self, report_id=None):
         res = {
-            'Content-Type': 'text/xml; charset=UTF-8',
-            'X-XSRF-TOKEN': self.headers['X-XSRF-TOKEN'],
-            'X-UseRsConsumerMode': 'true',
-            'SOAPAction': 'http://www.ibm.com/xmlns/prod/cognos/reportService/202004/'
+            "Content-Type": "text/xml; charset=UTF-8",
+            "X-XSRF-TOKEN": self.headers["X-XSRF-TOKEN"],
+            "X-UseRsConsumerMode": "true",
+            "SOAPAction": "http://www.ibm.com/xmlns/prod/cognos/reportService/202004/",
         }
         if report_id is not None:
-            res['X-RsCMStoreID'] = report_id
+            res["X-RsCMStoreID"] = report_id
         return res
 
-    def request_file(self, report_id, params, format='PDF'):
+    def request_file(self, report_id, params, format="PDF"):
         report = self.get_report(report_id)
         headers = self.get_report_headers(report_id)
 
-        soap = self.templates['get_report'].render(
-            {"caf": self.caf, "cam": self.cam,
-             "report": report, "format": format,
-             "prompt": 'false', "tracking": "", "params": params}
-        ).encode("utf-8")
-        r = self.session.post(self.webservice + 'v1/reports', data=soap, headers=headers)
+        soap = (
+            self.templates["get_report"]
+            .render(
+                {
+                    "caf": self.caf,
+                    "cam": self.cam,
+                    "report": report,
+                    "format": format,
+                    "prompt": "false",
+                    "tracking": "",
+                    "params": params,
+                }
+            )
+            .encode("utf-8")
+        )
+        r = self.session.post(
+            self.webservice + "v1/reports", data=soap, headers=headers
+        )
 
-        bs = BeautifulSoup(r.text, 'xml')
+        bs = BeautifulSoup(r.text, "xml")
         if r.status_code == 200:
             try:
                 parts = decoder.MultipartDecoder.from_response(r).parts
             except decoder.NonMultipartContentTypeException:
-                return 500, 'Timeout'
+                return 500, "Timeout"
             return 200, parts[1].content
 
-        error = bs.find_all('messageString')[0].string
+        error = bs.find_all("messageString")[0].string
         logging.debug(error)
         return r.status_code, error
 
@@ -311,41 +423,63 @@ class c11_api:
         # self.session.get(self.webservice + 'v1/reports/startupconfig?keys=supportedContentLocales,supportedCurrencies,
         # supportedFonts,metadataInformationURI,glossaryURI&locale=de')
         headers = self.get_report_headers()
-        soap = self.templates['get_package'].render(
-            {"caf": self.caf, "cam": self.cam}
-        ).encode("utf-8")
-        r = self.session.post(self.webservice + 'v1/reports', data=soap, headers=headers)
-        open('package.xml', 'wb').write(r.content)
+        soap = (
+            self.templates["get_package"]
+            .render({"caf": self.caf, "cam": self.cam})
+            .encode("utf-8")
+        )
+        r = self.session.post(
+            self.webservice + "v1/reports", data=soap, headers=headers
+        )
+        open("package.xml", "wb").write(r.content)
 
         search_path = self.request_search_path(folder_id)
         report_name = os.path.basename(fullpath)
-        unstubbed = open(fullpath, 'rb').read()
-        headers['SOAPAction'] = 'http://www.ibm.com/xmlns/prod/cognos/reportService/202004/.session'
-        headers['Referer'] = 'http://localhost:9300/bi/pat/rsapp.htm'
+        unstubbed = open(fullpath, "rb").read()
+        headers[
+            "SOAPAction"
+        ] = "http://www.ibm.com/xmlns/prod/cognos/reportService/202004/.session"
+        headers["Referer"] = "http://localhost:9300/bi/pat/rsapp.htm"
         # headers['caf'] = self.caf
 
-        soap = self.templates['create_report'].render(
-            {"caf": self.caf, "cam": self.cam,
-             "search_path": search_path,
-             "report_name": report_name, "unstubbed": unstubbed}
-        ).encode("utf-8")
-        r = self.session.post(self.webservice + 'v1/reports', data=soap, headers=headers)
-        open('request_create.xml', 'wb').write(r.request.body)
+        soap = (
+            self.templates["create_report"]
+            .render(
+                {
+                    "caf": self.caf,
+                    "cam": self.cam,
+                    "search_path": search_path,
+                    "report_name": report_name,
+                    "unstubbed": unstubbed,
+                }
+            )
+            .encode("utf-8")
+        )
+        r = self.session.post(
+            self.webservice + "v1/reports", data=soap, headers=headers
+        )
+        open("request_create.xml", "wb").write(r.request.body)
         print(r.status_code)
         print(r.text)
 
     def update_report(self, report, fullpath):
-        search_path = self.request_search_path(report['id'])
-        unstubbed = open(fullpath, 'r').read()
-        headers = self.get_report_headers(report['id'])
+        search_path = self.request_search_path(report["id"])
+        unstubbed = open(fullpath, "r").read()
+        headers = self.get_report_headers(report["id"])
         # headers['Referer'] = 'http://localhost:9300/bi/pat/rsapp.htm'
-        headers['caf'] = self.caf
-
-        soap = self.templates['update_report'].render(
-            {"caf": self.caf, "cam": self.cam,
-             "search_path": search_path, "unstubbed": unstubbed}
+        headers["caf"] = self.caf
+
+        soap = self.templates["update_report"].render(
+            {
+                "caf": self.caf,
+                "cam": self.cam,
+                "search_path": search_path,
+                "unstubbed": unstubbed,
+            }
         )  # .encode("utf-8")
-        r = self.session.post(self.webservice + 'v1/reports', data=soap, headers=headers)
+        r = self.session.post(
+            self.webservice + "v1/reports", data=soap, headers=headers
+        )
         # open('request_update.xml', 'wb').write(r.request.body)
         print(r.status_code)
         print(r.text)
@@ -355,27 +489,29 @@ class c11_api:
         res = self.session.post(
             f"{self.webservice}v1/objects/{parent_id}/items",
             headers=self.headers,
-            data=data
+            data=data,
         )
 
         if res.status_code == 201:
-            loc = res.headers.get('Location')
-            folder_id = loc.split('/')[-1]
-            self.folders.append({'id': folder_id, 'name': folder_name})
+            loc = res.headers.get("Location")
+            folder_id = loc.split("/")[-1]
+            self.folders.append({"id": folder_id, "name": folder_name})
             return folder_id
 
     def request_search_path(self, id):
-        res = self.session.get(f"{self.webservice}v1/objects/{id}?fields=searchPath", headers=self.headers)
-        return res.json()['data'][0]['searchPath']
+        res = self.session.get(
+            f"{self.webservice}v1/objects/{id}?fields=searchPath", headers=self.headers
+        )
+        return res.json()["data"][0]["searchPath"]
 
 
-if __name__ == '__main__':
+if __name__ == "__main__":
     api = c11_api()
     api.login()
     folders = api.get_folders()
-    filename = 'C:/GlobalCube/Tasks/gctools/logs/config/folders.json'
-    json.dump(folders, open(filename, 'w'), indent=2)
-    filename = 'C:/GlobalCube/Tasks/gctools/logs/config/reports.json'
-    json.dump(api.reports, open(filename, 'w'), indent=2)
-    filename = 'C:/GlobalCube/Tasks/gctools/logs/config/jobs.json'
-    json.dump(api.jobs, open(filename, 'w'), indent=2)
+    # filename = "C:/GlobalCube/Tasks/gctools/logs/config/folders.json"
+    # json.dump(folders, open(filename, "w"), indent=2)
+    # filename = "C:/GlobalCube/Tasks/gctools/logs/config/reports.json"
+    # json.dump(api.reports, open(filename, "w"), indent=2)
+    # filename = "C:/GlobalCube/Tasks/gctools/logs/config/jobs.json"
+    # json.dump(api.jobs, open(filename, "w"), indent=2)

+ 6 - 0
cognos11/c11_export.py

@@ -60,6 +60,12 @@ class c11_export:
 
     def export_pdf(self, report_id, folder=None):
         report = self.api.get_report(report_id)
+        if report["type"] == "shortcut":
+            report_link = report
+            report = self.api.get_report(report["target_id"]).copy()
+            for k in ("name", "description", "path", "type", "filename"):
+                report[k] = report_link[k]
+            json.dump(report, open("dump.json", "w"), indent=2)
         if "meta" not in report:
             logging.warning(report["name"] + " is not accessible!")
             return False

+ 32 - 0
cognos11/c11_jobs.py

@@ -0,0 +1,32 @@
+import json
+
+
+with open("data/reports.json", "r") as frh:
+    reports = json.load(frh)
+
+report_id_to_name = dict([(r["id"], r["name"]) for r in reports])
+
+with open("data/jobs.json", "r") as frh:
+    data = json.load(frh)
+
+for job in data:
+    print(job["name"])
+
+    for step in job["details"]["steps"]:
+        to_address = [
+            opt["value"] for opt in step["options"] if opt["name"] == "toAddress"
+        ]
+        parameters = {}
+        if step["parameters"]:
+            parameters = dict(
+                [
+                    (opt["name"], opt["value"])
+                    for opt in step["parameters"]
+                    if len(opt["value"]) > 0
+                ]
+            )
+
+        report_name = report_id_to_name[step["report_id"]]
+        print("  " + report_name)
+        print("    " + ",\n    ".join(to_address[0]))
+        # print("    ", parameters)

+ 8 - 7
pdf/pdf_merge.py

@@ -6,11 +6,11 @@ import json
 
 
 def pdf_merge(base_dir: str, report_name):
-    report_prefix = re.sub(r'\[([^\]]+)\]', '', report_name)
+    report_prefix = re.sub(r"\[([^\]]+)\]", "", report_name)
     target = f"{base_dir}/{report_prefix}_0.pdf"
     if Path(target).exists():
         Path(target).unlink()
-    pdfs = [f for f in Path(base_dir).glob(report_prefix + '*.pdf')]
+    pdfs = [f for f in Path(base_dir).glob(report_prefix + "*.pdf")]
     if len(pdfs) > 0:
         with PdfMerger() as merger:
             for pdf in sorted(pdfs, key=lambda f: f.stat().st_mtime):
@@ -19,17 +19,18 @@ def pdf_merge(base_dir: str, report_name):
 
 
 def get_reports(reports_file, folder):
-    with open(reports_file, 'r') as frh:
+    with open(reports_file, "r") as frh:
         reports = json.load(frh)
-    return [r['name'] for r in reports if r['path'].startswith(folder)]
+    return [r["name"] for r in reports if r["path"].startswith(folder)]
 
 
-def merge_reports_in_folder(cfg: config.Config, folder='Team Content/ReportOutput'):
+def merge_reports_in_folder(cfg: config.Config, folder="Team Content/ReportOutput"):
     reports = get_reports(cfg.cognos11.reports_file, folder)
+    print(folder)
     for r in reports:
         print(r)
-        pdf_merge(cfg.portal_dir + '/ReportOutput', r)
+        pdf_merge(cfg.cognos11.reportoutput_dir, r)
 
 
-if __name__ == '__main__':
+if __name__ == "__main__":
     merge_reports_in_folder(config.Config())

+ 27 - 21
pdf/pdf_test.py

@@ -9,50 +9,56 @@ from datetime import datetime, timedelta
 def current_date_test(base_dir: str):
     today = datetime.now()
     yesterday = today - timedelta(days=1)
-    current_date = [today.strftime('%d.%m.%Y'), today.strftime('%d/%m/%Y'), yesterday.strftime('%d.%m.%Y'), yesterday.strftime('%d/%m/%Y')]
-    errors = {
-        'empty': [],
-        'outdated': []
-    }
+    current_date = [
+        today.strftime("%d.%m.%Y"),
+        today.strftime("%d/%m/%Y"),
+        yesterday.strftime("%d.%m.%Y"),
+        yesterday.strftime("%d/%m/%Y"),
+    ]
+    errors = {"empty": [], "outdated": []}
 
-    files = [f for f in Path(base_dir).glob('*.pdf')]
+    files = [f for f in Path(base_dir).glob("*.pdf")]
     files_count = len(files)
 
     for i, f in enumerate(files):
-        print(f'({i}/{files_count}) {f.name}                 ', end='\r')
+        print(f"({i}/{files_count}) {f.name}                 ", end="\r")
         with pdfplumber.open(str(f)) as pdf:
             text = pdf.pages[0].extract_text()
-            if re.search(r'\d+ von \d+$', text):
-                errors['empty'].append(f.name)
-            report_date = re.search(r'\d{2}[\./]\d{2}[\./]\d{4}', text.split('\n')[0])
+            if re.search(r"\d+ von \d+$", text):
+                errors["empty"].append(f.name)
+            report_date = re.search(r"\d{2}[\./]\d{2}[\./]\d{4}", text.split("\n")[0])
             if report_date is not None and report_date.group() not in current_date:
-                errors['outdated'].append([f.name, report_date.group()])
+                errors["outdated"].append([f.name, report_date.group()])
 
     print()
     print(json.dumps(errors, indent=2))
 
 
 def missing_data(base_dir: str):
-    os.makedirs(base_dir + '/leer', exist_ok=True)
+    os.makedirs(base_dir + "/leer", exist_ok=True)
 
     errors = []
-    for f in Path(base_dir).glob('*.pdf'):
+    for f in Path(base_dir).glob("*.pdf"):
         with pdfplumber.open(str(f)) as pdf:
             pages = len(pdf.pages)
             text = pdf.pages[0].extract_text()
 
         # print(text)
-        if pages < 2 and any([
-            re.search(r'Daten nicht verf', text),
-            text.endswith('unprod.abw.'),
-            (len(text) < 650 and text.count('\n') < 8)
-        ]):
+        if pages < 2 and any(
+            [
+                re.search(r"Daten nicht verf", text),
+                text.endswith("unprod.abw."),
+                (len(text) < 650 and text.count("\n") < 8),
+            ]
+        ):
             errors.append(f.name)
-            f.rename(base_dir + '/leer/' + f.name)
+            target = Path(base_dir + "/leer/" + f.name)
+            target.unlink(missing_ok=True)
+            f.rename(target)
 
     return errors
 
 
-if __name__ == '__main__':
+if __name__ == "__main__":
     # current_date_test('C:\\GAPS_BMW\\Portal\\Publish\\daten\\GAPS_BMW_neu')
-    missing_data('C:\\GlobalCube\\ReportOutput\\raw')
+    missing_data("C:\\GlobalCube\\ReportOutput\\raw")