{ "info": { "author": "Hsufeng Lee", "author_email": "thittalee@gmail.com", "bugtrack_url": null, "classifiers": [ "Operating System :: OS Independent", "Programming Language :: Python :: 3" ], "description": "This Python package helps developers parse `Metapost` file.\n\nMetapost allows meta data to be appended to markdown files, such as `title` for a post; or `on_index` which denotes whether the post should be placed on the index page -- in a most human `readable` and `manageable` way.\n\n# Use Case\n\nMetapost is meant to help developers efficiently manipulate mock data when building CMS service.\nYou can put a bunch of markdown files (with meta info) in a folder,\nthen use `MetaPostReader` to parse them into a list of dictionaries, \nwhich can easily be imported into database via ORM modules.\n\n# How Metapost Works\n\n- `Metapost` file is a standard `Markdown` file with `.md` extension. \n- Except one thing - `Metapost` is expected to star with a `code block`, which will be parsed as metas of the file.\n- The content of the `code block` should be neither json nor YAML, it's a special but easy to learn format, which is meant to optimize the readability and manageability.\n- This package provides necessary tools for manipulating Metapost files, such as reading and exporting.\n- The markdown parser in this project is based on John Gruber's [Markdown](https://github.com/Python-Markdown/markdown)\n\nMetapost is extremely simple and powerful. The examples below will demonstrate how to implement it.\n\n# Examples\n\n## Quickstart\n\nIn this section, we are going to demonstrate how to parse a Metapost(markdown) file into useful formats that can interact with our application. Be aware that the meta content is neither json nor YAML, it's a key-value pair separated by a colon.\n\nFirst things first, install the package via PyPI\n\n```\npip install metapost\n```\n\nAssuming we have a MetaPost(.md file) article like this. The file starts with a code block containing metas, which is embraced by triple consecutive backtick(\\`\\`\\`).\n\n```\n` ` `\ntitle: Example post\nranking: 999\non_top: true\nkeywords: [\"markdown\", \"meta\", \"microblog\"]\nwork_hours: 35.6\n` ` `\n\n--- \u2191\u2191\u2191 Meta Block \u2191\u2191\u2191 ---\n--- \u2193\u2193\u2193 Markdown Content \u2193\u2193\u2193 ---\n\nBe careful we use ` ` ` here just because we can't escape backtick in the code block of github. \n\nYou should always use ``` in your markdown file.\n```\n\nNow, we are going to parse the file with `MetaPostReader` in our package:\n\n``` python\n# import package\nfrom metapost import MetaPostReader\n\n# set file path\npath = \".\\myMetaPostFilepath.md\"\n\n# instantiate MetaPostReader\nmtpr = MetaPostReader()\nmtpr.set_strict_mode(False)\n\n# read and export to python dict\nresult = mtpr.read_file(path).to_dict()\nprint(result)\n```\n\nThe out put will be:\n\n```\n[{\n \"meta\":{\"title\":\"Example post\",\n \"rank\":\"999\",\n \"on_top\":\"true\",\n \"keywords\":'[\"markdown\", \"meta\", \"microblog\"]',\n \"work_hours\": \"35.6\"}\n \"html\":\"
......
\"\n}]\n```\n\nWell, it's not that impressive, right? All values are parsed as string instead of boolean, integer or other useful datatype.\n\n## Set Meta Configs\n\nSet `meta_configs` on the `MetaPostReader` can help us parse value precisely. We can also set `required` and `df_val` on it to declare whether a meta is required or have default value.\n\nThe five lines of meta in the source markdown file are mapping to five acceptable datatype in the meta, they are string(`str`), boolean(`bool`), integer(`int`), float(`float`) and json(`json`).\n\nLet's set meta configs and parse it again\n\n``` python\nfrom metapost import MetaPostReader\n\npath = \"./ExampleMetaPost.md\"\nmtpr = MetaPostReaser()\n\n# add_meta_config()\n# key: str, datatype: str = \"str\", required: bool = True, df_val: Any = None\nmtpr.add_meta_config(\"title\", \"str\", True )\nmtpr.add_meta_config(\"ranking\", \"int\", False, 0 )\nmtpr.add_meta_config(\"on_top\", \"bool\", False, False)\nmtpr.add_meta_config(\"keywords\", \"json\", False )\nmtpr.add_meta_config(\"work_hours\", \"float\", True )\n\nresult = mtpr.to_dict()\nprint(result)\n```\n\nNow, we can get the content of the file in the format of python `dict`:\n\n```\n[{\n \"meta\":{\"title\":\"Example post\",\n \"rank\":999,\n \"on_top\":true,\n \"keywords\":[\"markdown\", \"meta\", \"microblog\"],\n \"work_hours\":35.6,\n ......}\n \"html\":\"......
\"\n}]\n```\n\nIf the parameter `required` is `True` while your file does not contain that meta key, \nthe reader will report error. \n\nWe can compare these three lines of code which clearly demonstrate how `required` and `df_val` works\n\n```python\nfrom metapost import MetaPostReader\nmtpr = MetaPostReader()\n\n# meta required, default value not necessary\nmtpr.add_meta_config(\"title\", \"str\", True )\n\n# meta not required, it is defaulted to be 999 if not provided\nmtpr.add_meta_config(\"ranking\", \"int\", False, 999 )\n\n# meta not required, no default value\nmtpr.add_meta_config(\"keywords\", \"json\", False )\n```\n\nAnother thing worth mention is that `MetaPostReader` adopt elastic approach to parse `bool` meta. That's to say, values like `False`, `false`, `No`, `n`, `0`, etc., will be parsed to `False` as long as the meta config expects a boolean. The rule is __case insensitive__ and is also applies to `True` parsing.\n\n## Set Strict Mode\n\nWe can set the property `strict_mode` on `MetaPostReader`. The defaulted value is `True`, which means the reader won't parse metas that are not defined in configs. Set it to `False` if you wish to parse as many valid metas as possible.\n\n```python\nfrom metapost import MetaPostReader\nmtpr = MetaPostReader()\n\n# strict mode on \nMetaPostReader().set_strict_mode(True)\n\n# strict mode off\nMetaPostReader().set_strict_mode(False)\n```\n\n## Default Meta\n\nExcept for metas we have defined in config, you can find some default ones. They are `_content_markdown_`,`_filepath_`, `_filename_` and `_last_update_`. These are meant to provide more information about the source file.\n\n## Read Multiple Files & Read from Directory\n\n`MetaPostReader` can also read and stack multiple files, then export them all at once.\nAll the files loaded will be stored in `MetaPostReader.mtp_list`.\n\n```python\nfrom metapost import MetaPostReader\n\n# read three files into MetaPostReader\nmtpr = MetaPostReader()\nmtpr.read_file(\"/mocks/file1.md\")\nmtpr.read_file(\"/mocks/file2.md\")\nmtpr.read_file(\"/mocks/file3.md\")\n\n# now, the length will be 3\nprint(len(mtpr.mtp_list))\n\n# parse all the posts, this returns a list of dictionary\nmy_metas = mtpr.to_dict()\n\n# set reset to True if you wish to reset list before read\nmtpr.read_file(\"/mocks/file4.md\", reset=True)\n\n# now, the length will be 1\nprint(len(mtpr.mtp_list))\n```\n\nYou can also read all files under a specific directory. \n`MetaPostReader.read_dir()` will automatically load all files with `.md` extensions.\nIf you wish to load all `.md` files in the directory tree, just set `walk` to `True`.\n\nThis feature is especially useful when importing mock data via migrations in web development.\n\n```python\nfrom metapost import MetaPostReader\n\n# Read .md from directory\nmy_mock_dirpath = \"./mocks\"\nmtpr = MetaPostReader()\nmtpr.read_file(my_mock_dirpath, walk=True)\n\n# get all parsed data\nposts = mtpr.to_dict()\n```\n\nThat's all! If you have any advice, feel free to contact me via email(thittalee@gmail.com) or github.\nThe following API document provides some short description of all the (expected) public methods. \nHappy coding! \n\n## API Document\n\n### Init\n- `MetaPostReader.__init__(self)`\n\nCreate a MetaPostReader\n\n### Add Meta Configs\n- `.add_meta_cfg(self, key: str, datatype: str = \"str\", required: bool = True, df_val: Any = None)`\n\nAdd meta config. `datatype` can be `str`, `bool`, `int`, `float` and `json`.\n\n### Methods of Read\n- `.read_dir(self, dirpath: str, reset: bool = False, walk: bool = False)`\n\nRead all the `.md` files under `dirpath` into reader. Set `reset` to `True` if you wish to clean the former loading. Set `walk` to `True` if you wish to read all the `.md` files in the directory tree.\n\n- `.read_file(self, filepath: str, reset: bool = False)`\n\nRead one single file from `filepath`. Set `reset` to `True` if you wish to clean the former loading.\n\n- `.read_text(self, source_text: str, reset: bool = False)`\n\nRead from a string. Set `reset` to `True` if you wish to clean the former loading.\n\n### Methods of Output\n\n- `.to_dict(self) -> List[dict]`\n\nExport a list of dict from data read . Use `dict[\"meta\"]` and `dict[\"html\"]` to fetch values.\n\n- `.to_json(self) -> str`\n\nExport a string of json from data read.\n\n- `.to_meta(self) -> List[dict]`\n\nExport a list of dict of meta from data read.s\n\n- `.to_html(self) -> List[str]`\n\nExport a list of string of html from data read.\n\n### Methods of Setter\n\n- `.set_strict_mode(self, strict_mode: bool)`\n\nSet `.strict_mode` to `True` if you wish to parse metas defined in configs only.\n\n- `.set_markdown_extensions(self, extensions: list)`\n\nCustomize your markdown extensions. Visit [Markdown](https://github.com/Python-Markdown/markdown) for more information.\n\n\n", "description_content_type": "text/markdown", "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/thitta/Python-MetaPost", "keywords": "", "license": "MIT License", "maintainer": "", "maintainer_email": "", "name": "metapost", "package_url": "https://pypi.org/project/metapost/", "platform": "", "project_url": "https://pypi.org/project/metapost/", "project_urls": { "Homepage": "https://github.com/thitta/Python-MetaPost" }, "release_url": "https://pypi.org/project/metapost/1.0.3/", "requires_dist": [ "datetime", "markdown", "typing", "tzlocal" ], "requires_python": "", "summary": "Tools for interpreting MetaPost", "version": "1.0.3" }, "last_serial": 5184744, "releases": { "0.0.1": [ { "comment_text": "", "digests": { "md5": "6661a2e952a1b23737c11b46f3fba969", "sha256": "6415fc662810607b0b03c37862fabc8696dffc7b46412d293b7b9969512c2357" }, "downloads": -1, "filename": "metapost-0.0.1-py3-none-any.whl", "has_sig": false, "md5_digest": "6661a2e952a1b23737c11b46f3fba969", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 8823, "upload_time": "2018-11-25T14:27:52", "url": "https://files.pythonhosted.org/packages/01/db/1c6c7b6872aa1ec6267705165caf8fbf7bcf45a91b5416c0f496b4d09936/metapost-0.0.1-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "8b256e4176fc5dabe120015f418c5e5b", "sha256": "43aa6d5c33bd555588393d4f1f268240299dc0e7c3830145f9d406d483455d17" }, "downloads": -1, "filename": "metapost-0.0.1.tar.gz", "has_sig": false, "md5_digest": "8b256e4176fc5dabe120015f418c5e5b", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 8366, "upload_time": "2018-11-25T14:27:54", "url": "https://files.pythonhosted.org/packages/04/65/37e320bab47cfa23c2f1eeffde9eda53237f02a7100b49d78d4d026ad612/metapost-0.0.1.tar.gz" } ], "0.0.2": [ { "comment_text": "", "digests": { "md5": "cc0d3ae149a2b787a6b3d1e23e3e4397", "sha256": "4e6f0bbb876e0d968c21852f39e12877fe710cf48efc507b9504c342fd313722" }, "downloads": -1, "filename": "metapost-0.0.2-py3-none-any.whl", "has_sig": false, "md5_digest": "cc0d3ae149a2b787a6b3d1e23e3e4397", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 8815, "upload_time": "2018-11-25T14:40:42", "url": "https://files.pythonhosted.org/packages/ba/5a/b92d892474d192811b399fdbe24b660d2d353febb9a9b8b136d9d7565887/metapost-0.0.2-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "e338bfad75089615d2f16375a28f4cec", "sha256": "6c0b4b6af50a254ce28164ac61177e383e81403e949881fd88a08193e437afd4" }, "downloads": -1, "filename": "metapost-0.0.2.tar.gz", "has_sig": false, "md5_digest": "e338bfad75089615d2f16375a28f4cec", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 8353, "upload_time": "2018-11-25T14:40:44", "url": "https://files.pythonhosted.org/packages/82/36/2af19eb3b83ffa335acf5aa2fc19c4aaefdc953d0e1d46ac20f9bfdae4c4/metapost-0.0.2.tar.gz" } ], "1.0.3": [ { "comment_text": "", "digests": { "md5": "db32a49fa01ed057111dbcf3fe2a4d89", "sha256": "0e6bfcbcc1786eca3365dd6e6e0c708759ae8dbc69fb7b8e09501634ebac3864" }, "downloads": -1, "filename": "metapost-1.0.3-py3-none-any.whl", "has_sig": false, "md5_digest": "db32a49fa01ed057111dbcf3fe2a4d89", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 8807, "upload_time": "2019-04-24T21:44:20", "url": "https://files.pythonhosted.org/packages/30/d8/20cf57bcad0a6b9265d9aaa71b133a08529b5ec69127b7e5757480a195a7/metapost-1.0.3-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "d8801d3c412cfe52e413851c4b7d05cc", "sha256": "59802bdb0a17709ffb21679761628c0fdc3faacb559c4360295bd80b30bdb8e5" }, "downloads": -1, "filename": "metapost-1.0.3.tar.gz", "has_sig": false, "md5_digest": "d8801d3c412cfe52e413851c4b7d05cc", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 8520, "upload_time": "2019-04-24T21:44:24", "url": "https://files.pythonhosted.org/packages/04/87/1b80960069edf3ae6cf7d27cbee40529989d090c8d7ae0b90db8599f6c88/metapost-1.0.3.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "db32a49fa01ed057111dbcf3fe2a4d89", "sha256": "0e6bfcbcc1786eca3365dd6e6e0c708759ae8dbc69fb7b8e09501634ebac3864" }, "downloads": -1, "filename": "metapost-1.0.3-py3-none-any.whl", "has_sig": false, "md5_digest": "db32a49fa01ed057111dbcf3fe2a4d89", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 8807, "upload_time": "2019-04-24T21:44:20", "url": "https://files.pythonhosted.org/packages/30/d8/20cf57bcad0a6b9265d9aaa71b133a08529b5ec69127b7e5757480a195a7/metapost-1.0.3-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "d8801d3c412cfe52e413851c4b7d05cc", "sha256": "59802bdb0a17709ffb21679761628c0fdc3faacb559c4360295bd80b30bdb8e5" }, "downloads": -1, "filename": "metapost-1.0.3.tar.gz", "has_sig": false, "md5_digest": "d8801d3c412cfe52e413851c4b7d05cc", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 8520, "upload_time": "2019-04-24T21:44:24", "url": "https://files.pythonhosted.org/packages/04/87/1b80960069edf3ae6cf7d27cbee40529989d090c8d7ae0b90db8599f6c88/metapost-1.0.3.tar.gz" } ] }