Repository: NarekA/git-notion
Branch: master
Commit: 144f4f957d05
Files: 15
Total size: 12.2 KB
Directory structure:
gitextract_btxgpe73/
├── .github/
│ ├── ISSUE_TEMPLATE.md
│ └── workflows/
│ └── sync-md2notion-pr-merge.yml
├── .gitignore
├── LICENSE
├── README.md
├── docs/
│ ├── NestedTest/
│ │ └── nested_example.md
│ └── example.md
├── git_notion/
│ ├── __init__.py
│ ├── cli.py
│ └── git_notion.py
├── requirements.in
├── setup.cfg
├── setup.py
└── tests/
├── __init__.py
└── test_git_notion.py
================================================
FILE CONTENTS
================================================
================================================
FILE: .github/ISSUE_TEMPLATE.md
================================================
* git-notion version:
* Python version:
* Operating System:
### Description
Describe what you were trying to get done.
Tell us what happened, what went wrong, and what you expected to happen.
### What I Did
```
Paste the command(s) you ran and the output.
If there was a crash, please include the traceback here.
```
================================================
FILE: .github/workflows/sync-md2notion-pr-merge.yml
================================================
name: Sync md files to notion when PR merged
on:
pull_request:
types: [closed]
jobs:
sync:
timeout-minutes: 10
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Setup Python
uses: actions/setup-python@v2
with:
python-version: '3.x'
- name: Cache pip
uses: actions/cache@v2
with:
# This path is specific to Ubuntu
path: ~/.cache/pip
# Look to see if there is a cache hit for the corresponding requirements file
key: ${{ runner.os }}-pip-${{ hashFiles('requirements.txt') }}
restore-keys: |
${{ runner.os }}-pip-
${{ runner.os }}-
- name: Install dependencies
run: |
python -m pip install --upgrade pip git-notion
- name: Sync md doc
run: |
git-notion
env:
NOTION_IGNORE_REGEX: ${{ secrets.NOTION_IGNORE_REGEX }}
NOTION_ROOT_PAGE: ${{ secrets.NOTION_ROOT_PAGE }}
NOTION_TOKEN_V2: ${{ secrets.NOTION_TOKEN_V2 }}
================================================
FILE: .gitignore
================================================
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
env/
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
*.egg-info/
.installed.cfg
*.egg
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
.hypothesis/
.pytest_cache/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
target/
# Jupyter Notebook
.ipynb_checkpoints
# pyenv
.python-version
# celery beat schedule file
celerybeat-schedule
# SageMath parsed files
*.sage.py
# dotenv
.env
# virtualenv
.venv
venv/
ENV/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
# IDE settings
.vscode/
================================================
FILE: LICENSE
================================================
MIT License
Copyright (c) 2020, NarekA
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: README.md
================================================
Git Notion
==========
Syncs Github markdown files in your repository to Notion.
This utility is described in the following [blog post](https://www.swiftlane.com/blog/syncing-docs-from-code-repositories-to-notion/).
See example [Notion page](https://www.notion.so/git_notion-195c08d3d14140eb9a35ac00f9a0f078).
## Installation
```
pip install git-notion
```
or for local installation:
```bash
git clone https://github.com/NarekA/git-notion.git
cd git-notion
pip install -e .
```
## Configuring
`NOTION_TOKEN_V2` - Can be found in your [browser cookies](https://www.redgregory.com/notion/2020/6/15/9zuzav95gwzwewdu1dspweqbv481s5) for Notion's website.
`NOTION_ROOT_PAGE` - URL for notion page. Repo docs will be a new page under this page.
`NOTION_IGNORE_REGEX` - Regex for paths to ignore.
These environment variables can be set.
```bash
export NOTION_TOKEN_V2=<YOUR_TOKEN>
export NOTION_ROOT_PAGE="https://www.notion.so/..." # Can be in setup.cfg as well
export NOTION_IGNORE_REGEX="models/.*" # Can be in setup.cfg as well
```
These parameters can be set in the `setup.cfg` for the repo.
```
[git-notion]
ignore_regex = models/.*
notion_root_page = https://www.notion.so/...
```
If you want to map specific Github folders to Notion subpages besides the `notion_root_page`, you can add the folder names and subpage URLs as parameters in the `setup.cfg` for the repo:
```
[folders]
# docs = <any_notion_url> # This can be any subpage of the Notion root page
# docs/NestedTest = <any_other_notion_url> # This can be the same subpage as above, or any other subpage of the Notion root page
```
## Usage
```bash
# To upload your current directory
git-notion
# To upload another directory
git-notion --path path/to/your/repo
```
## Pushing to PYPI
```bash
bumpversion patch # Look-up bumpversion
rm -rf dist/
python3 setup.py sdist bdist_wheel
python3 -m twine upload dist/*
```
================================================
FILE: docs/NestedTest/nested_example.md
================================================
### Heading for Test
Here's an example of a markdown file that's in a nested folder within the folder `docs`. We can also add the folder path `docs/NestedDocs` in `setup.cfg` to pick up this file to the specified Notion URL.
================================================
FILE: docs/example.md
================================================
Example
==
This is an example markdown file to sync.
If you add the `docs` folder name to the `[folders]` config settings in `setup.cfg`, this file will sync to the specified Notion subpage URL.
================================================
FILE: git_notion/__init__.py
================================================
"""Top-level package for git-notion."""
__author__ = """NarekA"""
__version__ = '0.2.4'
from git_notion.git_notion import *
================================================
FILE: git_notion/cli.py
================================================
"""Console script for git_notion."""
import sys
import click
import git_notion
@click.command()
@click.option('--path', default=".", help='The path to the repo you want to sync')
def main(path):
"""Console script for git_notion."""
click.echo("running sync")
git_notion.sync_to_notion(path)
return 0
if __name__ == "__main__":
sys.exit(main()) # pragma: no cover
================================================
FILE: git_notion/git_notion.py
================================================
"""Main module."""
import hashlib
import os
import glob
from configparser import ConfigParser
import re
from notion.block import PageBlock
from notion.block import TextBlock
from notion.client import NotionClient
from md2notion.upload import upload
TOKEN = os.getenv("NOTION_TOKEN_V2", "")
_client = None
def get_client():
global _client
if not _client:
_client = NotionClient(token_v2=TOKEN)
return _client
def get_or_create_page(base_page, title):
page = None
for child in base_page.children.filter(PageBlock):
if child.title == title:
page = child
if not page:
page = base_page.children.add_new(PageBlock, title=title)
return page
def upload_file(base_page, filename: str, page_title=None):
page_title = page_title or filename
page = get_or_create_page(base_page, page_title)
hasher = hashlib.md5()
with open(filename, "rb") as mdFile:
buf = mdFile.read()
hasher.update(buf)
if page.children and hasher.hexdigest() in str(page.children[0]):
return page
for child in page.children:
child.remove()
page.children.add_new(TextBlock, title=f"MD5: {hasher.hexdigest()}")
with open(filename, "r", encoding="utf-8") as mdFile:
upload(mdFile, page)
return page
def sync_to_notion(repo_root: str = "."):
os.chdir(repo_root)
config = ConfigParser()
config.read(os.path.join(repo_root, "setup.cfg"))
repo_name = os.path.basename(os.getcwd())
root_page_url = os.getenv("NOTION_ROOT_PAGE") or config.get('git-notion', 'notion_root_page')
ignore_regex = os.getenv("NOTION_IGNORE_REGEX") or config.get('git-notion', 'ignore_regex', fallback=None)
root_page = get_client().get_block(root_page_url)
repo_page = get_or_create_page(root_page, repo_name)
for file in glob.glob("**/*.md", recursive=True):
if ignore_regex is None or not re.match(ignore_regex, file):
# Extract folder from the file path
folder = os.path.dirname(file)
# Use folder-specific URL if available, otherwise use the default repo_page URL
folder_url = config.get('folders', folder, fallback=None)
upload_file(repo_page if folder_url is None else get_client().get_block(folder_url), file)
if folder_url:
print(file, "uploaded to: ", folder_url)
else:
print(file, "uploaded to: default repo page")
# Example call:
# sync_to_notion(repo_root="/path/to/repo", config_file_path="notion_config.ini")
================================================
FILE: requirements.in
================================================
click
md2notion
================================================
FILE: setup.cfg
================================================
[bumpversion]
current_version = 0.2.4
commit = True
tag = True
[bumpversion:file:setup.py]
search = version='{current_version}'
replace = version='{new_version}'
[bumpversion:file:git_notion/__init__.py]
search = __version__ = '{current_version}'
replace = __version__ = '{new_version}'
[bdist_wheel]
universal = 1
[flake8]
exclude = docs
[aliases]
test = pytest
[tool:pytest]
collect_ignore = ['setup.py']
[git-notion]
notion_root_page = https://www.notion.so/Git-Documents-6cf97b2d7ab64a7d964c7a7bcc42f9aa
[folders]
# docs = <any_notion_url> # This can be any subpage of the Notion root page
# docs/NestedTest = <any_other_notion_url> # This can be the same subpage as above, or any other subpage of the Notion root page
================================================
FILE: setup.py
================================================
#!/usr/bin/env python
from setuptools import setup, find_packages
import os
base_dir = os.path.abspath(os.path.dirname(__file__))
with open(os.path.join('requirements.in')) as f:
requirements = [l.strip() for l in f.readlines() if l.strip()]
with open(os.path.join(base_dir, 'README.md'), encoding='utf-8') as f:
long_description = f.read()
setup_requirements = ['pytest-runner', ]
test_requirements = ['pytest>=3', ]
setup(
author="NarekA",
python_requires='>=3.5',
classifiers=[
'Development Status :: 2 - Pre-Alpha',
'Intended Audience :: Developers',
'License :: OSI Approved :: MIT License',
'Natural Language :: English',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.6',
'Programming Language :: Python :: 3.7',
'Programming Language :: Python :: 3.8',
],
description="Syncs Github Mmarkdown files to Notion",
entry_points={
'console_scripts': [
'git-notion=git_notion.cli:main',
],
},
install_requires=requirements,
license="MIT license",
include_package_data=True,
keywords='git_notion',
long_description=long_description,
long_description_content_type='text/markdown',
name='git_notion',
packages=find_packages(include=['git_notion', 'git_notion.*']),
setup_requires=setup_requirements,
test_suite='tests',
tests_require=test_requirements,
url='https://github.com/NarekA/git-notion',
version='0.2.5',
zip_safe=False,
)
================================================
FILE: tests/__init__.py
================================================
"""Unit test package for git_notion."""
================================================
FILE: tests/test_git_notion.py
================================================
#!/usr/bin/env python
"""Tests for `git_notion` package."""
import pytest
from click.testing import CliRunner
from git_notion import git_notion
from git_notion import cli
@pytest.fixture
def response():
"""Sample pytest fixture.
See more at: http://doc.pytest.org/en/latest/fixture.html
"""
# import requests
# return requests.get('https://github.com/audreyr/cookiecutter-pypackage')
def test_content(response):
"""Sample pytest test function with the pytest fixture as an argument."""
# from bs4 import BeautifulSoup
# assert 'GitHub' in BeautifulSoup(response.content).title.string
def test_command_line_interface():
"""Test the CLI."""
runner = CliRunner()
result = runner.invoke(cli.main)
assert result.exit_code == 0
assert 'git_notion.cli.main' in result.output
help_result = runner.invoke(cli.main, ['--help'])
assert help_result.exit_code == 0
assert '--help Show this message and exit.' in help_result.output
gitextract_btxgpe73/
├── .github/
│ ├── ISSUE_TEMPLATE.md
│ └── workflows/
│ └── sync-md2notion-pr-merge.yml
├── .gitignore
├── LICENSE
├── README.md
├── docs/
│ ├── NestedTest/
│ │ └── nested_example.md
│ └── example.md
├── git_notion/
│ ├── __init__.py
│ ├── cli.py
│ └── git_notion.py
├── requirements.in
├── setup.cfg
├── setup.py
└── tests/
├── __init__.py
└── test_git_notion.py
SYMBOL INDEX (8 symbols across 3 files) FILE: git_notion/cli.py function main (line 9) | def main(path): FILE: git_notion/git_notion.py function get_client (line 18) | def get_client(): function get_or_create_page (line 25) | def get_or_create_page(base_page, title): function upload_file (line 36) | def upload_file(base_page, filename: str, page_title=None): function sync_to_notion (line 55) | def sync_to_notion(repo_root: str = "."): FILE: tests/test_git_notion.py function response (line 14) | def response(): function test_content (line 23) | def test_content(response): function test_command_line_interface (line 29) | def test_command_line_interface():
Condensed preview — 15 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (14K chars).
[
{
"path": ".github/ISSUE_TEMPLATE.md",
"chars": 321,
"preview": "* git-notion version:\n* Python version:\n* Operating System:\n\n### Description\n\nDescribe what you were trying to get done."
},
{
"path": ".github/workflows/sync-md2notion-pr-merge.yml",
"chars": 1116,
"preview": "name: Sync md files to notion when PR merged\n\non:\n pull_request:\n types: [closed]\n\njobs:\n sync:\n timeout-minutes"
},
{
"path": ".gitignore",
"chars": 1196,
"preview": "# Byte-compiled / optimized / DLL files\n__pycache__/\n*.py[cod]\n*$py.class\n\n# C extensions\n*.so\n\n# Distribution / packagi"
},
{
"path": "LICENSE",
"chars": 1065,
"preview": "MIT License\n\nCopyright (c) 2020, NarekA\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof"
},
{
"path": "README.md",
"chars": 1906,
"preview": "Git Notion\n==========\n\nSyncs Github markdown files in your repository to Notion.\n\nThis utility is described in the follo"
},
{
"path": "docs/NestedTest/nested_example.md",
"chars": 226,
"preview": "### Heading for Test\nHere's an example of a markdown file that's in a nested folder within the folder `docs`. We can als"
},
{
"path": "docs/example.md",
"chars": 197,
"preview": "Example\n==\n\nThis is an example markdown file to sync.\n\nIf you add the `docs` folder name to the `[folders]` config setti"
},
{
"path": "git_notion/__init__.py",
"chars": 126,
"preview": "\"\"\"Top-level package for git-notion.\"\"\"\n\n__author__ = \"\"\"NarekA\"\"\"\n__version__ = '0.2.4'\n\nfrom git_notion.git_notion imp"
},
{
"path": "git_notion/cli.py",
"chars": 388,
"preview": "\"\"\"Console script for git_notion.\"\"\"\nimport sys\nimport click\nimport git_notion\n\n\n@click.command()\n@click.option('--path'"
},
{
"path": "git_notion/git_notion.py",
"chars": 2571,
"preview": "\"\"\"Main module.\"\"\"\nimport hashlib\nimport os\nimport glob\nfrom configparser import ConfigParser\nimport re\n\nfrom notion.blo"
},
{
"path": "requirements.in",
"chars": 15,
"preview": "click\nmd2notion"
},
{
"path": "setup.cfg",
"chars": 731,
"preview": "[bumpversion]\ncurrent_version = 0.2.4\ncommit = True\ntag = True\n\n[bumpversion:file:setup.py]\nsearch = version='{current_v"
},
{
"path": "setup.py",
"chars": 1599,
"preview": "#!/usr/bin/env python\n\nfrom setuptools import setup, find_packages\nimport os\n\nbase_dir = os.path.abspath(os.path.dirname"
},
{
"path": "tests/__init__.py",
"chars": 40,
"preview": "\"\"\"Unit test package for git_notion.\"\"\"\n"
},
{
"path": "tests/test_git_notion.py",
"chars": 994,
"preview": "#!/usr/bin/env python\n\n\"\"\"Tests for `git_notion` package.\"\"\"\n\nimport pytest\n\nfrom click.testing import CliRunner\n\nfrom g"
}
]
About this extraction
This page contains the full source code of the NarekA/git-notion GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 15 files (12.2 KB), approximately 3.5k tokens, and a symbol index with 8 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.