Esempio n. 1
0
def parse_lookml_file(lookml_file_name: str) -> dict:
    """Parse a LookML file into a dictionary with keys for each of its primary properties and a list of values."""
    logger.info("Parsing data from LookML file {}".format(lookml_file_name))
    with open(lookml_file_name, "r") as lookml_file_stream:
        lookml_data = lkml.load(lookml_file_stream)

    return lookml_data
Esempio n. 2
0
    def _load_viewfile(
            self, path: str,
            reporter: LookMLSourceReport) -> Optional[LookerViewFile]:
        if self.is_view_seen(path):
            return self.viewfile_cache[path]

        try:
            with open(path, "r") as file:
                raw_file_content = file.read()
        except Exception as e:
            self.reporter.report_failure(path,
                                         f"failed to load view file: {e}")
            return None
        try:
            with open(path, "r") as file:
                logger.info(f"Loading file {path}")
                parsed = lkml.load(file)
                looker_viewfile = LookerViewFile.from_looker_dict(
                    absolute_file_path=path,
                    looker_view_file_dict=parsed,
                    base_folder=self._base_folder,
                    raw_file_content=raw_file_content,
                    reporter=reporter,
                )
                logger.debug(f"adding viewfile for path {path} to the cache")
                self.viewfile_cache[path] = looker_viewfile
                return looker_viewfile
        except Exception as e:
            self.reporter.report_failure(path,
                                         f"failed to load view file: {e}")
            return None
def test_parser():
    lookml = {
        "explores": [
            {
                "name": "test_explore",
                "joins": [
                    {
                        "name": "join_a"
                    },
                    {
                        "name": "join_b"
                    },
                ],
                "queries": {
                    "dimensions": ["submission_date", "app_build"],
                    "measures": ["client_count"],
                    "pivots": ["app_build"],
                    "sorts": [{
                        "submission_date": "asc"
                    }],
                    "name": "build_breakdown",
                },
            },
        ],
    }

    print_and_test(lookml, lkml.load(dump(copy.deepcopy(lookml))))
Esempio n. 4
0
 def _load_model(self, path: str) -> LookerModel:
     with open(path, "r") as file:
         parsed = lkml.load(file)
         looker_model = LookerModel.from_looker_dict(
             parsed, self.source_config.base_folder
         )
     return looker_model
Esempio n. 5
0
    def __init__(self, infilepath):
        '''parse the LookML infilepath, convert to JSON, and then read into JSON object

        Args:
            infilepath (str): path to input LookML file

        Returns:
            JSON object of LookML

        '''
        if not os.path.exists(infilepath):
            raise IOError("Filename does not exist: %s" % infilepath)

        self.infilepath = infilepath
        if infilepath.endswith(".model.lkml"):
            self.filetype = 'model'
        elif infilepath.endswith(".view.lkml"):
            self.filetype = 'view'
        elif infilepath.endswith(".explore.lkml"):
            self.filetype = 'explore'
        else:
            raise Exception("Unsupported filename " + infilepath)
        self.base_filename = os.path.basename(infilepath)
        self.base_name = self.base_filename.replace(".model.lkml", "").replace(
            ".explore.lkml", "").replace(".view.lkml", "")

        with open(infilepath, 'r') as file:
            self.json_data = lkml.load(file)
Esempio n. 6
0
def github_lkml(repo_name: str):
    """connect to repo with lookml, iterate through lookml and returns list
    of parsed lookml

    Args:
        repo_name (str): name of repo (not path)

    Returns:
        [list]: list of lookml elements in repo
    """
    g = Github(github_token)

    repo = g.get_repo(repo_name)

    contents = repo.get_contents("", ref='master')
    print(contents)
    lookml = []
    while contents:
        file_content = contents.pop(0)
        if file_content.type == "dir":
            contents.extend(repo.get_contents(file_content.path))
        else:
            x = base64.b64decode(file_content.content).decode('UTF-8')
            try:
                lookml.append(lkml.load(x))
            except SyntaxError:
                print(f'''you have a lookml syntax error in {file_content}
                and your file cannot be parsed
                ''')

    return lookml
Esempio n. 7
0
def test_generate_model(looker_sdk, namespaces, tmp_path):
    sdk = looker_sdk.init31()
    sdk.search_model_sets.side_effect = [
        [Mock(models=["model"], id=1)],
        [Mock(models=["model2"], id=2)],
    ]
    sdk.lookml_model.side_effect = _looker_sdk.error.SDKError
    looker_sdk.error = Mock(SDKError=_looker_sdk.error.SDKError)

    write_model = Mock()
    looker_sdk.models.WriteModelSet.return_value = write_model

    generate_directories(namespaces, tmp_path, True)
    expected = {
        "connection":
        "telemetry",
        "label":
        "Glean App",
        "includes": [
            "//looker-hub/glean-app/explores/*",
            "//looker-hub/glean-app/dashboards/*",
            "views/*",
            "explores/*",
            "dashboards/*",
        ],
    }
    actual = lkml.load(
        (tmp_path / "glean-app" / "glean-app.model.lkml").read_text())
    assert expected == actual

    sdk.update_model_set.assert_any_call(1, write_model)
    sdk.update_model_set.assert_any_call(2, write_model)
Esempio n. 8
0
    def __init__(self, infilepath):
        """parse the LookML infilepath, convert to JSON, and then read into JSON object

        Args:
            infilepath (str): path to input LookML file

        Returns:
            JSON object of LookML

        """
        if not os.path.exists(infilepath):
            raise IOError("Filename does not exist: %s" % infilepath)

        self.infilepath = infilepath
        self.base_filename = os.path.basename(infilepath)

        if self.base_filename.endswith(".model.lkml"):
            self.filetype = "model"
        elif self.base_filename.endswith(".explore.lkml"):
            self.filetype = "explore"
        elif self.base_filename.startswith(
                "explore_") and self.base_filename.endswith(".lkml"):
            self.filetype = "explore"
        elif self.base_filename.endswith(".view.lkml"):
            self.filetype = "view"
        elif self.base_filename.endswith(".lkml"):
            # consider everything else as a view
            self.filetype = "view"
        else:
            raise Exception("Unsupported filename " + infilepath)

        self.base_name = re.sub(r"\.\w+\.lkml$", "", self.base_filename)
        with open(infilepath, "r") as file:
            self.json_data = lkml.load(file)
Esempio n. 9
0
    def getViewInformationFromFile(self,
                                   fileName,
                                   isExtended=False,
                                   logging=None):
        if logging is None:
            logging = Logger().getLogger()
        views = []

        with open(fileName, 'r') as file:
            parsed = lkml.load(file)
            #print(parsed)
            logging.info(parsed)
            includes = []
            if 'includes' in parsed:
                includes = parsed['includes']
            for view in parsed['views']:

                viewObj = View()
                viewObj.setView(view)
                viewObj.includes = includes
                if isExtended:
                    viewObj.viewType = 'EXTENDED'
                views.append(viewObj)

        return views
Esempio n. 10
0
 def parse(self):
     """
     open file and load lkml as json
     """
     with open(self.file_path, "r") as f:
         self.content = lkml.load(f)
     return self.content
Esempio n. 11
0
 def _load_model(self, path: str) -> LookerModel:
     with open(path, "r") as file:
         logger.debug(f"Loading model from file {path}")
         parsed = lkml.load(file)
         looker_model = LookerModel.from_looker_dict(
             parsed, str(self.source_config.base_folder), path,
             self.reporter)
     return looker_model
Esempio n. 12
0
def test_file(path: Path):
    with path.open("r") as file:
        text = file.read()

    try:
        parsed = lkml.load(text)
    except Exception:
        shutil.copy(path, github_path / "load_errors" / path.name)
        logging.exception(f"Error parsing {path}")

    try:
        dumped = lkml.dump(parsed)
        lkml.load(dumped)
    except Exception:
        with open(github_path / "dump_errors" / path.name, "w+") as file:
            file.write(dumped)
        logging.exception(f"Error serializing {path}")
Esempio n. 13
0
def test_round_trip_should_work(lookml):
    # Load the LookML from file, parsing into a tree
    tree = lkml.parse(lookml)

    # Verify it hasn't changed once converted back to string
    assert str(tree) == lookml

    # Convert that parsed tree into a lossy dictionary
    visitor = DictVisitor()
    tree_as_dict = visitor.visit(tree)

    # Parse the dictionary into a new tree
    parser = DictParser()
    new_tree = parser.parse(tree_as_dict)

    # Verify that the string form of the tree parsed from a dictionary can be re-parsed
    lkml.load(str(new_tree))
Esempio n. 14
0
def test_model_with_all_fields():
    path = Path(
        __file__).parent / "resources" / "model_with_all_fields.model.lkml"
    with path.open() as file:
        raw = file.read()

    parsed = lkml.load(raw)
    assert parsed is not None
Esempio n. 15
0
def test_model_with_all_fields():
    path = Path(
        __file__).parent / "resources" / "model_with_all_fields.model.lkml"
    with path.open() as file:
        raw = file.read()

    parsed = lkml.load(raw)
    assert parsed is not None

    lookml = lkml.dump(parsed)
    assert lookml.replace("\n\n", "\n") == raw.replace("\n\n", "\n")
Esempio n. 16
0
    def _load_viewfile(self, path: str) -> typing.Optional["LookerViewFile"]:
        if path in self.viewfile_cache:
            return self.viewfile_cache[path]

        try:
            with open(path, "r") as file:
                parsed = lkml.load(file)
                looker_viewfile = LookerViewFile.from_looker_dict(path, parsed)
                self.viewfile_cache[path] = looker_viewfile
                return looker_viewfile
        except Exception as e:
            print(e)
            print(f"Error processing view file {path}. Skipping it")
Esempio n. 17
0
    def _load_viewfile(self, path: str) -> Optional[LookerViewFile]:
        if self.is_view_seen(path):
            return self.viewfile_cache[path]

        try:
            with open(path, "r") as file:
                parsed = lkml.load(file)
                looker_viewfile = LookerViewFile.from_looker_dict(
                    path, parsed, self._base_folder)
                self.viewfile_cache[path] = looker_viewfile
                return looker_viewfile
        except Exception:
            logger.warning(f"Error processing view file {path}. Skipping it")
            return None
Esempio n. 18
0
def parse(file):
    print('[parsing] {}'.format(f))
    try:
        with open(f, 'r') as file:
            parsed = lkml.load(file)
            if 'explore' in parsed.keys():
                find_joins(parsed['explore'])
            elif 'explores' in parsed.keys():
                for explore in parsed['explores']:
                    find_joins(explore)

    except Exception as e:
        print('[parser error] {}'.format(f))
        print(traceback.format_exc())
Esempio n. 19
0
 def from_lookml_string(
     cls,
     name: str,
     lookml_type: str,
     directory_path: str = "./",
     lookml_string: str = None,
 ):
     """"""
     return cls(
         name,
         lookml_type,
         directory_path=directory_path,
         lookml_data=lkml.load(lookml_string),
     )
Esempio n. 20
0
 def read_data_from_file(self, local_lookml_project_path: str) -> dict:
     """Parse a LookML file into a dictionary with keys for each of its primary properties and a list of values."""
     logger.info(
         "Parsing data from local LookML file {}".format(
             self.lookml_file_name_and_path
         )
     )
     with open(
         utils.assemble_path(
             local_lookml_project_path, self.lookml_file_name_and_path
         ),
         "r",
     ) as lookml_file:
         return lkml.load(lookml_file)
Esempio n. 21
0
    def __attrs_post_init__(self):

        repo_path = Path(self.lookml_repo_path)

        self.models = []
        for model_file in self._model_file_paths():
            with open(repo_path.joinpath(model_file)) as f:
                self.models.append(
                    Model(lkml.load(f), os.path.basename(model_file)))
        self.views = []
        for view_file in self._view_file_paths():
            with open(repo_path.joinpath(view_file)) as f:
                for view_data in lkml.load(f)['views']:
                    self.views.append(
                        View(view_data, os.path.basename(view_file)))

        # match explore views with their source views
        for m in self.models:
            for e in m.explores:
                for ev in e.views:
                    source_view = next(v for v in self.views
                                       if v.name == ev.source_view_name())
                    ev.source_view = source_view
Esempio n. 22
0
def git_auth(user, token, repo, file_name, owner):
    query_url = f"https://api.github.com/repos/{owner}/{repo}"
    params = {
        "state": "open",
    }
    headers = {'Authorization': f'token {token}'}
    r = requests.get(query_url, headers=headers, params=params)
    #grab github repo content(s)
    g = Github(token)
    repo = g.get_repo(owner + "/" + repo)
    #specify lookml file
    content = repo.get_contents(path="/Views/" + file_name)
    raw_data = content.decoded_content.decode("utf-8")
    parsed_lookml = lkml.load(raw_data)
    return parsed_lookml
Esempio n. 23
0
def file_parse_lkml(file_paths: list):
    """Iterate through local file paths
    and return a list of lookml files with an element
    for each lookml file]

    Args:
        file_paths (list): [a list of local path strings]

    Returns:
        [list]: [list of parsed lookml]
    """
    response_list = []
    for path in file_paths:
        with open(path, 'r') as file:
            response_list.append(lkml.load(file))

    return response_list
Esempio n. 24
0
    def from_local_file(cls, looker_project_root: str, file_relative_path: str):
        """"""
        full_project_path = utils.assemble_path(looker_project_root, file_relative_path)
        path_suffixes = Path(full_project_path).suffixes
        lookml_file_type = path_suffixes[0] if len(path_suffixes) > 1 else "generic"
        directory, file_name = (
            Path(full_project_path).parent,
            Path(full_project_path).stem,
        )

        with open(full_project_path, "r") as local_file_stream:
            return cls(
                file_name,
                lookml_file_type,
                directory_path=directory,
                lookml_data=lkml.load(local_file_stream),
            )
Esempio n. 25
0
    def getViewInfomationFromFile(self, fileName):

        views = []

        with open(fileName, 'r') as file:
            parsed = lkml.load(file)
            print(parsed)
            #logging.info(parsed)

            for view in parsed['views']:

                viewObj = View()

                viewObj.setView(view)
                views.append(viewObj)

        return views
Esempio n. 26
0
    def _load_viewfile(
            self, path: str,
            reporter: LookMLSourceReport) -> Optional[LookerViewFile]:
        if self.is_view_seen(path):
            return self.viewfile_cache[path]

        try:
            with open(path, "r") as file:
                parsed = lkml.load(file)
                looker_viewfile = LookerViewFile.from_looker_dict(
                    path, parsed, self._base_folder, reporter)
                logger.debug(f"adding viewfile for path {path} to the cache")
                self.viewfile_cache[path] = looker_viewfile
                return looker_viewfile
        except Exception as e:
            self.reporter.report_failure(path,
                                         f"failed to load view file: {e}")
            return None
Esempio n. 27
0
    def _load_viewfile(
            self, path: str,
            reporter: LookMLSourceReport) -> Optional[LookerViewFile]:
        # always fully resolve paths to simplify de-dup
        path = str(pathlib.Path(path).resolve())
        if not path.endswith(".view.lkml"):
            # not a view file
            logger.debug(
                f"Skipping file {path} because it doesn't appear to be a view file"
            )
            return None

        if self.is_view_seen(str(path)):
            return self.viewfile_cache[path]

        try:
            with open(path, "r") as file:
                raw_file_content = file.read()
        except Exception as e:
            self.reporter.report_failure(path,
                                         f"failed to load view file: {e}")
            return None
        try:
            with open(path, "r") as file:
                logger.debug(f"Loading viewfile {path}")
                parsed = lkml.load(file)
                looker_viewfile = LookerViewFile.from_looker_dict(
                    absolute_file_path=path,
                    looker_view_file_dict=parsed,
                    base_folder=self._base_folder,
                    raw_file_content=raw_file_content,
                    reporter=reporter,
                )
                logger.debug(f"adding viewfile for path {path} to the cache")
                self.viewfile_cache[path] = looker_viewfile
                return looker_viewfile
        except Exception as e:
            self.reporter.report_failure(path,
                                         f"failed to load view file: {e}")
            return None
Esempio n. 28
0
def main():
    kafka_producer = make_kafka_producer(EXTRA_KAFKA_CONF)
    viewfile_loader = LookerViewFileLoader()

    looker_models = []
    all_views = []

    model_files = sorted(f for f in glob.glob(
        f"{LOOKER_DIRECTORY}/**/*.model.lkml", recursive=True))
    for f in model_files:
        try:
            with open(f, 'r') as file:
                parsed = lkml.load(file)
                looker_model = LookerModel.from_looker_dict(parsed)
                looker_models.append(looker_model)
        except Exception as e:
            print(e)
            print(f"Error processing model file {f}. Skipping it")

    for model in looker_models:
        for include in model.resolved_includes:
            looker_viewfile = viewfile_loader.load_viewfile(
                include, model.connection)
            if looker_viewfile is not None:
                for raw_view in looker_viewfile.views:
                    maybe_looker_view = LookerView.from_looker_dict(
                        raw_view, model.connection, looker_viewfile,
                        viewfile_loader)
                    if maybe_looker_view:
                        all_views.append(maybe_looker_view)

    for view in all_views:
        MCE = build_dataset_mce(view)
        print(view)
        print(MCE)
        kafka_producer.produce(topic=KAFKA_TOPIC,
                               key=MCE['proposedSnapshot'][1]['urn'],
                               value=MCE)
        kafka_producer.flush()
Esempio n. 29
0
def test_load_with_bad_argument_raises_type_error():
    with pytest.raises(TypeError):
        lkml.load(stream=100)
def load(filename):
    """Helper method to load a LookML file from tests/resources and parse it."""
    path = Path(__file__).parent / "resources" / filename
    with path.open() as file:
        return lkml.load(file)