pyformatjson 0.2.5__tar.gz → 0.2.6__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (26) hide show
  1. pyformatjson-0.2.6/.github/workflows/docs.yml +73 -0
  2. pyformatjson-0.2.6/.github/workflows/publish.yml +24 -0
  3. pyformatjson-0.2.6/.github/workflows/release.yml +46 -0
  4. pyformatjson-0.2.6/.gitignore +180 -0
  5. pyformatjson-0.2.6/CODE_OF_CONDUCT.md +83 -0
  6. {pyformatjson-0.2.5 → pyformatjson-0.2.6}/PKG-INFO +22 -13
  7. pyformatjson-0.2.6/docs/api-manual/index.md +1 -0
  8. pyformatjson-0.2.6/docs/index.md +1 -0
  9. pyformatjson-0.2.6/docs/requirements.txt +7 -0
  10. pyformatjson-0.2.6/docs/users-guide/bug-report.md +1 -0
  11. pyformatjson-0.2.6/docs/users-guide/installation.md +13 -0
  12. pyformatjson-0.2.6/docs/users-guide/pull-request.md +1 -0
  13. pyformatjson-0.2.6/mkdocs.yml +148 -0
  14. {pyformatjson-0.2.5 → pyformatjson-0.2.6}/pyformatjson/core/_base.py +3 -3
  15. pyformatjson-0.2.6/pyformatjson/tools/__init__.py +0 -0
  16. {pyformatjson-0.2.5 → pyformatjson-0.2.6}/pyformatjson/tools/generate_dict.py +83 -40
  17. {pyformatjson-0.2.5 → pyformatjson-0.2.6}/pyformatjson/tools/write_dict.py +1 -1
  18. pyformatjson-0.2.6/pyformatjson.sublime-project +24 -0
  19. {pyformatjson-0.2.5 → pyformatjson-0.2.6}/pyproject.toml +56 -18
  20. pyformatjson-0.2.6/scripts/generate_docs.py +134 -0
  21. {pyformatjson-0.2.5 → pyformatjson-0.2.6}/LICENSE +0 -0
  22. {pyformatjson-0.2.5 → pyformatjson-0.2.6}/README.md +0 -0
  23. {pyformatjson-0.2.5 → pyformatjson-0.2.6}/pyformatjson/__init__.py +0 -0
  24. {pyformatjson-0.2.5 → pyformatjson-0.2.6}/pyformatjson/core/__init__.py +0 -0
  25. {pyformatjson-0.2.5 → pyformatjson-0.2.6}/pyformatjson/core/update_json.py +0 -0
  26. {pyformatjson-0.2.5 → pyformatjson-0.2.6}/pyformatjson/main.py +0 -0
@@ -0,0 +1,73 @@
1
+ name: Deploy Documentation
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ branches: [main]
8
+
9
+ jobs:
10
+ test:
11
+ runs-on: ubuntu-latest
12
+ steps:
13
+ - uses: actions/checkout@v5
14
+
15
+ - name: Set up Python
16
+ uses: actions/setup-python@v6
17
+ with:
18
+ python-version: "3.12"
19
+
20
+ - name: Cache pip
21
+ uses: actions/cache@v4
22
+ with:
23
+ path: ~/.cache/pip
24
+ key: ${{ runner.os }}-pip-${{ hashFiles('docs/requirements.txt') }}
25
+ restore-keys: |
26
+ ${{ runner.os }}-pip-
27
+
28
+ - name: Install dependencies
29
+ run: |
30
+ pip install -r docs/requirements.txt
31
+
32
+ - name: Generate API docs
33
+ run: python scripts/generate_docs.py
34
+
35
+ - name: Build documentation (strict)
36
+ run: mkdocs build --strict
37
+
38
+ deploy:
39
+ if: github.event_name == 'push' && github.ref == 'refs/heads/main'
40
+ runs-on: ubuntu-latest
41
+ needs: test
42
+ steps:
43
+ - uses: actions/checkout@v5
44
+ with:
45
+ token: ${{ secrets.PAT_TOKEN }}
46
+
47
+ - name: Set up Python
48
+ uses: actions/setup-python@v6
49
+ with:
50
+ python-version: "3.12"
51
+
52
+ - name: Cache pip
53
+ uses: actions/cache@v4
54
+ with:
55
+ path: ~/.cache/pip
56
+ key: ${{ runner.os }}-pip-${{ hashFiles('docs/requirements.txt') }}
57
+ restore-keys: |
58
+ ${{ runner.os }}-pip-
59
+
60
+ - name: Install dependencies
61
+ run: |
62
+ pip install -r docs/requirements.txt
63
+
64
+ - name: Generate API docs
65
+ run: python scripts/generate_docs.py
66
+
67
+ - name: Configure Git
68
+ run: |
69
+ git config user.name "GitHub Actions"
70
+ git config user.email "actions@github.com"
71
+
72
+ - name: Deploy to GitHub Pages
73
+ run: mkdocs gh-deploy --force --remote-branch gh-pages
@@ -0,0 +1,24 @@
1
+ name: Publish to PyPI
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - "v*"
7
+
8
+ jobs:
9
+ publish:
10
+ runs-on: ubuntu-latest
11
+ steps:
12
+ - name: Checkout
13
+ uses: actions/checkout@v5
14
+
15
+ - name: Install uv
16
+ uses: astral-sh/setup-uv@v6
17
+
18
+ - name: Build package
19
+ run: uv build
20
+
21
+ - name: Publish to PyPI
22
+ env:
23
+ UV_PUBLISH_TOKEN: ${{ secrets.PYPI_API_TOKEN }}
24
+ run: uv publish
@@ -0,0 +1,46 @@
1
+ name: Release
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - "v*"
7
+
8
+ jobs:
9
+ release:
10
+ runs-on: ubuntu-latest
11
+ permissions:
12
+ contents: write
13
+ steps:
14
+ - uses: actions/checkout@v5
15
+ with:
16
+ fetch-depth: 0
17
+ token: ${{ secrets.PAT_TOKEN }}
18
+ ref: main
19
+
20
+ - name: Setup Node.js
21
+ uses: actions/setup-node@v6
22
+ with:
23
+ node-version: "24"
24
+
25
+ - name: Install dependencies
26
+ run: npm install -g conventional-changelog conventional-changelog-angular
27
+
28
+ - name: Generate changelog
29
+ # run: conventional-changelog -p angular -i CHANGELOG.md -s -r 0
30
+ run: conventional-changelog -p angular -i CHANGELOG.md -s -r 2
31
+
32
+ # - name: Commit changelog
33
+ # run: |
34
+ # git config --local user.email "github-actions[bot]@users.noreply.github.com"
35
+ # git config --local user.name "github-actions[bot]"
36
+ # git add CHANGELOG.md
37
+ # git commit -m "docs: update changelog for ${{ github.ref_name }}" || exit 0
38
+ # git push
39
+
40
+ - name: Create GitHub Release
41
+ uses: softprops/action-gh-release@v2
42
+ with:
43
+ body_path: CHANGELOG.md
44
+ # generate_release_notes: true
45
+ env:
46
+ GITHUB_TOKEN: ${{ secrets.PAT_TOKEN }}
@@ -0,0 +1,180 @@
1
+ # Common ignored files and folders
2
+ # Ignored files
3
+ .DS_Store
4
+ poetry.lock
5
+ uv.lock
6
+
7
+ *.sublime-workspace
8
+ *.code-workspace
9
+
10
+ # Ignored folders
11
+ node_modules/
12
+ .virtual_documents/
13
+ .ruff_cache
14
+ .idea/
15
+ .vscode/
16
+ tests_temp/
17
+
18
+ # Special for this project
19
+
20
+ # From https://github.com/github/gitignore/blob/main/Python.gitignore
21
+ # Byte-compiled / optimized / DLL files
22
+ __pycache__/
23
+ *.py[cod]
24
+ *$py.class
25
+
26
+ # C extensions
27
+ *.so
28
+
29
+ # Distribution / packaging
30
+ .Python
31
+ build/
32
+ develop-eggs/
33
+ dist/
34
+ downloads/
35
+ eggs/
36
+ .eggs/
37
+ lib/
38
+ lib64/
39
+ parts/
40
+ sdist/
41
+ var/
42
+ wheels/
43
+ share/python-wheels/
44
+ *.egg-info/
45
+ .installed.cfg
46
+ *.egg
47
+ MANIFEST
48
+
49
+ # PyInstaller
50
+ # Usually these files are written by a python script from a template
51
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
52
+ *.manifest
53
+ *.spec
54
+
55
+ # Installer logs
56
+ pip-log.txt
57
+ pip-delete-this-directory.txt
58
+
59
+ # Unit test / coverage reports
60
+ htmlcov/
61
+ .tox/
62
+ .nox/
63
+ .coverage
64
+ .coverage.*
65
+ .cache
66
+ nosetests.xml
67
+ coverage.xml
68
+ *.cover
69
+ *.py,cover
70
+ .hypothesis/
71
+ .pytest_cache/
72
+ cover/
73
+
74
+ # Translations
75
+ *.mo
76
+ *.pot
77
+
78
+ # Django stuff:
79
+ *.log
80
+ local_settings.py
81
+ db.sqlite3
82
+ db.sqlite3-journal
83
+
84
+ # Flask stuff:
85
+ instance/
86
+ .webassets-cache
87
+
88
+ # Scrapy stuff:
89
+ .scrapy
90
+
91
+ # Sphinx documentation
92
+ docs/_build/
93
+
94
+ # PyBuilder
95
+ .pybuilder/
96
+ target/
97
+
98
+ # Jupyter Notebook
99
+ .ipynb_checkpoints
100
+
101
+ # IPython
102
+ profile_default/
103
+ ipython_config.py
104
+
105
+ # pyenv
106
+ # For a library or package, you might want to ignore these files since the code is
107
+ # intended to run in multiple environments; otherwise, check them in:
108
+ # .python-version
109
+
110
+ # pipenv
111
+ # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
112
+ # However, in case of collaboration, if having platform-specific dependencies or dependencies
113
+ # having no cross-platform support, pipenv may install dependencies that don't work, or not
114
+ # install all needed dependencies.
115
+ #Pipfile.lock
116
+
117
+ # poetry
118
+ # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
119
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
120
+ # commonly ignored for libraries.
121
+ # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
122
+ #poetry.lock
123
+
124
+ # pdm
125
+ # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
126
+ #pdm.lock
127
+ # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
128
+ # in version control.
129
+ # https://pdm.fming.dev/#use-with-ide
130
+ .pdm.toml
131
+
132
+ # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
133
+ __pypackages__/
134
+
135
+ # Celery stuff
136
+ celerybeat-schedule
137
+ celerybeat.pid
138
+
139
+ # SageMath parsed files
140
+ *.sage.py
141
+
142
+ # Environments
143
+ .env
144
+ .venv
145
+ env/
146
+ venv/
147
+ ENV/
148
+ env.bak/
149
+ venv.bak/
150
+
151
+ # Spyder project settings
152
+ .spyderproject
153
+ .spyproject
154
+
155
+ # Rope project settings
156
+ .ropeproject
157
+
158
+ # mkdocs documentation
159
+ /site
160
+
161
+ # mypy
162
+ .mypy_cache/
163
+ .dmypy.json
164
+ dmypy.json
165
+
166
+ # Pyre type checker
167
+ .pyre/
168
+
169
+ # pytype static type analyzer
170
+ .pytype/
171
+
172
+ # Cython debug symbols
173
+ cython_debug/
174
+
175
+ # PyCharm
176
+ # JetBrains specific template is maintained in a separate JetBrains.gitignore that can
177
+ # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
178
+ # and can be added to the global gitignore or merged into this file. For a more nuclear
179
+ # option (not recommended) you can uncomment the following to ignore the entire idea folder.
180
+ #.idea/
@@ -0,0 +1,83 @@
1
+ # Contributor Covenant Code of Conduct
2
+
3
+ ## Our Pledge
4
+
5
+ We as members, contributors, and leaders pledge to make participation in our community a harassment-free experience for everyone, regardless of age, body size, visible or invisible disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion, or sexual identity and orientation.
6
+
7
+ We pledge to act and interact in ways that contribute to an open, welcoming, diverse, inclusive, and healthy community.
8
+
9
+ ## Our Standards
10
+
11
+ Examples of behavior that contributes to a positive environment for our community include:
12
+
13
+ * Demonstrating empathy and kindness toward other people
14
+ * Being respectful of differing opinions, viewpoints, and experiences
15
+ * Giving and gracefully accepting constructive feedback
16
+ * Accepting responsibility and apologizing to those affected by our mistakes, and learning from the experience
17
+ * Focusing on what is best not just for us as individuals, but for the overall community
18
+
19
+ Examples of unacceptable behavior include:
20
+
21
+ * The use of sexualized language or imagery, and sexual attention or advances of any kind
22
+ * Trolling, insulting or derogatory comments, and personal or political attacks
23
+ * Public or private harassment
24
+ * Publishing others' private information, such as a physical or email address, without their explicit permission
25
+ * Other conduct which could reasonably be considered inappropriate in a professional setting
26
+
27
+ ## Enforcement Responsibilities
28
+
29
+ Community leaders are responsible for clarifying and enforcing our standards of acceptable behavior and will take appropriate and fair corrective action in response to any behavior that they deem inappropriate, threatening, offensive, or harmful.
30
+
31
+ Community leaders have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, and will communicate reasons for moderation decisions when appropriate.
32
+
33
+ ## Scope
34
+
35
+ This Code of Conduct applies within all community spaces, and also applies when an individual is officially representing the community in public spaces. Examples of representing our community include using an official e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event.
36
+
37
+ ## Enforcement
38
+
39
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be reported to the community leaders responsible for enforcement at [INSERT CONTACT METHOD]. All complaints will be reviewed and investigated promptly and fairly.
40
+
41
+ All community leaders are obligated to respect the privacy and security of the reporter of any incident.
42
+
43
+ ## Enforcement Guidelines
44
+
45
+ Community leaders will follow these Community Impact Guidelines in determining the consequences for any action they deem in violation of this Code of Conduct:
46
+
47
+ ### 1. Correction
48
+
49
+ **Community Impact**: Use of inappropriate language or other behavior deemed unprofessional or unwelcome in the community.
50
+
51
+ **Consequence**: A private, written warning from community leaders, providing clarity around the nature of the violation and an explanation of why the behavior was inappropriate. A public apology may be requested.
52
+
53
+ ### 2. Warning
54
+
55
+ **Community Impact**: A violation through a single incident or series of actions.
56
+
57
+ **Consequence**: A warning with consequences for continued behavior. No interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, for a specified period of time. This includes avoiding interactions in community spaces as well as external channels like social media. Violating these terms may lead to a temporary or permanent ban.
58
+
59
+ ### 3. Temporary Ban
60
+
61
+ **Community Impact**: A serious violation of community standards, including sustained inappropriate behavior.
62
+
63
+ **Consequence**: A temporary ban from any sort of interaction or public communication with the community for a specified period of time. No public or private interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, is allowed during this period. Violating these terms may lead to a permanent ban.
64
+
65
+ ### 4. Permanent Ban
66
+
67
+ **Community Impact**: Demonstrating a pattern of violation of community standards, including sustained inappropriate behavior, harassment of an individual, or aggression toward or disparagement of classes of individuals.
68
+
69
+ **Consequence**: A permanent ban from any sort of public interaction within the community.
70
+
71
+ ## Attribution
72
+
73
+ This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 2.0, available at [https://www.contributor-covenant.org/version/2/0/code_of_conduct.html][v2.0].
74
+
75
+ Community Impact Guidelines were inspired by [Mozilla's code of conduct enforcement ladder][Mozilla CoC].
76
+
77
+ For answers to common questions about this code of conduct, see the FAQ at [https://www.contributor-covenant.org/faq][FAQ]. Translations are available at [https://www.contributor-covenant.org/translations][translations].
78
+
79
+ [homepage]: https://www.contributor-covenant.org
80
+ [v2.0]: https://www.contributor-covenant.org/version/2/0/code_of_conduct.html
81
+ [Mozilla CoC]: https://github.com/mozilla/diversity
82
+ [FAQ]: https://www.contributor-covenant.org/faq
83
+ [translations]: https://www.contributor-covenant.org/translations
@@ -1,24 +1,34 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pyformatjson
3
- Version: 0.2.5
3
+ Version: 0.2.6
4
4
  Summary: pyformatjson
5
- License: GPL-3.0-or-later
5
+ Project-URL: Homepage, https://github.com/Easy-PhD/pyformatjson
6
+ Project-URL: Repository, https://github.com/Easy-PhD/pyformatjson
7
+ Project-URL: Documentation, https://Easy-PhD.github.io/pyformatjson
8
+ Project-URL: Source, https://github.com/Easy-PhD/pyformatjson
9
+ Project-URL: Issues, https://github.com/Easy-PhD/pyformatjson/issues
10
+ Project-URL: Changelog, https://github.com/Easy-PhD/pyformatjson/releases
11
+ Author-email: NextAI <nextartifintell@gmail.com>
12
+ Maintainer-email: NextAI <nextartifintell@gmail.com>
13
+ License-Expression: GPL-3.0-or-later
6
14
  License-File: LICENSE
7
- Keywords: Python,Json
8
- Author: NextAI
9
- Author-email: nextartifintell@gmail.com
10
- Maintainer: NextAI
11
- Maintainer-email: nextartifintell@gmail.com
12
- Requires-Python: >=3.12
13
- Classifier: License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)
15
+ Keywords: JSON,Python
16
+ Classifier: Operating System :: OS Independent
17
+ Classifier: Programming Language :: Python
14
18
  Classifier: Programming Language :: Python :: 3
15
19
  Classifier: Programming Language :: Python :: 3.12
16
20
  Classifier: Programming Language :: Python :: 3.13
17
21
  Classifier: Programming Language :: Python :: 3.14
18
22
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
19
- Project-URL: Documentation, https://github.com/Easy-PhD/pyformatjson
20
- Project-URL: Homepage, https://github.com/Easy-PhD/pyformatjson
21
- Project-URL: Repository, https://github.com/Easy-PhD/pyformatjson
23
+ Requires-Python: >=3.12
24
+ Requires-Dist: beautifulsoup4>=4.14.2
25
+ Requires-Dist: func-timeout>=4.3.5
26
+ Requires-Dist: lxml>=6.0.2
27
+ Requires-Dist: playwright>=1.55.0
28
+ Requires-Dist: psutil>=7.1.2
29
+ Requires-Dist: pyadvtools>=0.3.8
30
+ Requires-Dist: requests>=2.32.5
31
+ Requires-Dist: selenium>=4.38.0
22
32
  Description-Content-Type: text/markdown
23
33
 
24
34
  # PyFormatJson
@@ -28,4 +38,3 @@ Description-Content-Type: text/markdown
28
38
  ![PyPI - Python Version](https://img.shields.io/pypi/pyversions/pyformatjson)
29
39
  [![PyPI](https://img.shields.io/pypi/v/pyformatjson)](https://pypi.org/project/pyformatjson/)
30
40
  [![Commitizen friendly](https://img.shields.io/badge/commitizen-friendly-brightgreen.svg)](http://commitizen.github.io/cz-cli/)
31
-
@@ -0,0 +1 @@
1
+ # API Reference
@@ -0,0 +1 @@
1
+ # pyformatjson
@@ -0,0 +1,7 @@
1
+ mkdocs>=1.6.1
2
+ mkdocs-autorefs>=1.4.3
3
+ mkdocs-material>=9.6.21
4
+ mkdocs-material-extensions>=1.3.1
5
+ mkdocs-minify-plugin>=0.8.0
6
+ mkdocs-redirects>=1.2.2
7
+ mkdocstrings[python]>=0.30.1
@@ -0,0 +1 @@
1
+ # Bug Report
@@ -0,0 +1,13 @@
1
+ # Installation
2
+
3
+ - uv
4
+
5
+ ```bash
6
+ uv add pyformatjson
7
+ ```
8
+
9
+ - pip
10
+
11
+ ```bash
12
+ pip install pyformatjson
13
+ ```
@@ -0,0 +1 @@
1
+ # Pull Request
@@ -0,0 +1,148 @@
1
+ # Project information
2
+ site_name: pyformatjson Documentation
3
+ site_url: https://Easy-PhD.github.com/pyformatjson
4
+ site_author: NextAI
5
+ site_description: >-
6
+ pyformatjson
7
+
8
+ # Repository
9
+ repo_url: https://github.com/Easy-PhD/pyformatjson
10
+ repo_name: Easy-PhD/pyformatjson
11
+
12
+ # Copyright
13
+ copyright: Copyright &copy; 2025 - 2025 NextAI
14
+
15
+ # Configuration
16
+ theme:
17
+ name: material
18
+ features:
19
+ - announce.dismiss
20
+ # - content.action.edit
21
+ # - content.action.view
22
+ - content.code.annotate
23
+ - content.code.copy
24
+ # - content.code.select
25
+ # - content.footnote.tooltips
26
+ # - content.tabs.link
27
+ - content.tooltips
28
+ # - header.autohide
29
+ # - navigation.expand
30
+ - navigation.footer
31
+ - navigation.indexes
32
+ # - navigation.instant
33
+ # - navigation.instant.prefetch
34
+ # - navigation.instant.progress
35
+ # - navigation.prune
36
+ - navigation.sections
37
+ - navigation.tabs
38
+ # - navigation.tabs.sticky
39
+ - navigation.top
40
+ - navigation.tracking
41
+ - search.highlight
42
+ - search.share
43
+ - search.suggest
44
+ - toc.follow
45
+ # - toc.integrate
46
+ palette:
47
+ - scheme: default
48
+ primary: teal
49
+ accent: purple
50
+ toggle:
51
+ icon: material/brightness-7
52
+ name: Switch to dark mode
53
+ - scheme: slate
54
+ primary: teal
55
+ accent: purple
56
+ toggle:
57
+ icon: material/brightness-4
58
+ name: Switch to light mode
59
+
60
+ plugins:
61
+ - search:
62
+ lang: en
63
+ separator: '[\s\u200b\-_,:!=\[\]()"`/]+|\.(?!\d)|&[lg]t;|(?!\b)(?=[A-Z][a-z])'
64
+ - autorefs
65
+ - mkdocstrings:
66
+ default_handler: python
67
+ handlers:
68
+ python:
69
+ paths: [.]
70
+ options:
71
+ docstring_style: google
72
+ show_root_heading: true
73
+ show_source: true
74
+ show_category_heading: true
75
+ separate_signature: true
76
+ merge_init_into_class: true
77
+ - minify:
78
+ minify_html: true
79
+
80
+ # Extensions
81
+ markdown_extensions:
82
+ - abbr
83
+ - admonition
84
+ - attr_list
85
+ - def_list
86
+ - footnotes
87
+ - md_in_html
88
+ - toc:
89
+ permalink: true
90
+ - pymdownx.arithmatex:
91
+ generic: true
92
+ - pymdownx.betterem:
93
+ smart_enable: all
94
+ - pymdownx.caret
95
+ - pymdownx.details
96
+ - pymdownx.emoji:
97
+ emoji_generator: !!python/name:material.extensions.emoji.to_svg
98
+ emoji_index: !!python/name:material.extensions.emoji.twemoji
99
+ - pymdownx.highlight:
100
+ anchor_linenums: true
101
+ line_spans: __span
102
+ pygments_lang_class: true
103
+ - pymdownx.inlinehilite
104
+ - pymdownx.keys
105
+ - pymdownx.magiclink:
106
+ normalize_issue_symbols: true
107
+ repo_url_shorthand: true
108
+ user: squidfunk
109
+ repo: mkdocs-material
110
+ - pymdownx.mark
111
+ - pymdownx.smartsymbols
112
+ - pymdownx.snippets:
113
+ auto_append:
114
+ - includes/mkdocs.md
115
+ - pymdownx.superfences:
116
+ custom_fences:
117
+ - name: mermaid
118
+ class: mermaid
119
+ format: !!python/name:pymdownx.superfences.fence_code_format
120
+ - pymdownx.tabbed:
121
+ alternate_style: true
122
+ combine_header_slug: true
123
+ slugify: !!python/object/apply:pymdownx.slugs.slugify
124
+ kwds:
125
+ case: lower
126
+ - pymdownx.tasklist:
127
+ custom_checkbox: true
128
+ - pymdownx.tilde
129
+
130
+ extra_javascript:
131
+ - https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js
132
+
133
+ nav:
134
+ - Home: index.md
135
+
136
+ - Getting Started:
137
+ - Installation: users-guide/installation.md
138
+
139
+ - Auto API:
140
+ - Auto API: api-auto.md
141
+
142
+ - Manual API:
143
+ - Manual API: api-manual/index.md
144
+
145
+ - Community:
146
+ - Contributing:
147
+ - Reporting a bug: users-guide/bug-report.md
148
+ - Making a pull request: users-guide/pull-request.md
@@ -172,7 +172,7 @@ class IterateSortDict:
172
172
  """
173
173
  self.reverse = reverse
174
174
 
175
- def dict_update(self, old):
175
+ def dict_update(self, old: dict) -> dict:
176
176
  """Update and sort a dictionary recursively.
177
177
 
178
178
  This method sorts the dictionary keys and recursively processes
@@ -188,7 +188,7 @@ class IterateSortDict:
188
188
  old = self.dict_sort(old)
189
189
  return old
190
190
 
191
- def dict_sort_iteration(self, old: dict):
191
+ def dict_sort_iteration(self, old: dict) -> dict:
192
192
  """Recursively sort nested dictionaries.
193
193
 
194
194
  This method iterates through the dictionary and recursively sorts
@@ -205,7 +205,7 @@ class IterateSortDict:
205
205
  old[key] = self.dict_update(old[key])
206
206
  return old
207
207
 
208
- def dict_sort(self, old: dict):
208
+ def dict_sort(self, old: dict) -> dict:
209
209
  """Sort dictionary keys using natural sorting.
210
210
 
211
211
  This method sorts the top-level keys of the dictionary using
File without changes
@@ -1,9 +1,10 @@
1
1
  import os
2
2
  import re
3
3
  from datetime import datetime
4
+ from typing import Any
4
5
 
5
6
 
6
- def conference_journal_header():
7
+ def conference_journal_header() -> tuple[list[str], list[str]]:
7
8
  """Generate markdown table headers for conferences and journals.
8
9
 
9
10
  This function creates the appropriate markdown table headers for displaying
@@ -82,7 +83,7 @@ class GenerateDataDict:
82
83
  self.path_spidered_cj = path_spidered_conferences_or_journals
83
84
  self.for_vue = for_vue
84
85
 
85
- def generate(self):
86
+ def generate(self) -> tuple[dict, dict, dict]:
86
87
  """Generate publisher metadata and keyword-based publication information.
87
88
 
88
89
  This method processes the JSON data to create three main dictionaries:
@@ -161,7 +162,7 @@ class GenerateDataDict:
161
162
 
162
163
  return publisher_meta_dict, publisher_abbr_meta_dict, keyword_abbr_meta_dict
163
164
 
164
- def conference_or_journal(self, publisher_url: str, abbr: str, abbr_dict: dict):
165
+ def conference_or_journal(self, publisher_url: str, abbr: str, abbr_dict: dict) -> tuple[dict[str, Any], list[str]]:
165
166
  """Process conference or journal data and generate formatted information.
166
167
 
167
168
  This method processes individual conference or journal data, validates
@@ -214,7 +215,7 @@ class GenerateDataDict:
214
215
 
215
216
  return {"txt_abouts": abouts, "txt_remarks": remarks, "row_inf": row_inf}, keywords
216
217
 
217
- def _validate_name_lengths(self, abbr_dict: dict):
218
+ def _validate_name_lengths(self, abbr_dict: dict) -> None:
218
219
  """Validate that full and abbreviated names arrays have equal length.
219
220
 
220
221
  This method ensures that the full names and abbreviated names arrays
@@ -231,7 +232,9 @@ class GenerateDataDict:
231
232
  if len(full_names) != len(abbr_names):
232
233
  raise ValueError(f"Length mismatch: {len(full_names)} {full_names} vs {len(abbr_names)} abbreviated names")
233
234
 
234
- def _extract_full_abbr_names(self, abbr_dict: dict):
235
+ return None
236
+
237
+ def _extract_full_abbr_names(self, abbr_dict: dict) -> tuple[str, str]:
235
238
  """Extract full and abbreviated names from dictionary.
236
239
 
237
240
  This method extracts the appropriate full and abbreviated names based on
@@ -248,11 +251,11 @@ class GenerateDataDict:
248
251
  abbr_name = abbr_dict.get("names_abbr", [""])[0]
249
252
  return full_name, abbr_name
250
253
 
251
- def _extract_homepage_url(self, abbr_dict: dict):
254
+ def _extract_homepage_url(self, abbr_dict: dict[str, Any]) -> str:
252
255
  """Extract and clean homepage URL.
253
256
 
254
257
  Args:
255
- abbr_dict (dict): Dictionary containing publication data.
258
+ abbr_dict (dict[str, Any]): Dictionary containing publication data.
256
259
 
257
260
  Returns:
258
261
  str: The first valid homepage URL, or empty string if none found.
@@ -260,11 +263,11 @@ class GenerateDataDict:
260
263
  urls = [u.strip() for u in abbr_dict.get("urls_homepage", []) if u.strip()]
261
264
  return urls[0] if urls else ""
262
265
 
263
- def _format_period_with_dblp(self, abbr_dict: dict):
266
+ def _format_period_with_dblp(self, abbr_dict: dict[str, Any]) -> str:
264
267
  """Format publication period with DBLP link if available.
265
268
 
266
269
  Args:
267
- abbr_dict (dict): Dictionary containing publication data.
270
+ abbr_dict (dict[str, Any]): Dictionary containing publication data.
268
271
 
269
272
  Returns:
270
273
  str: Formatted period string with optional DBLP link.
@@ -283,11 +286,11 @@ class GenerateDataDict:
283
286
 
284
287
  return period
285
288
 
286
- def _extract_text_content(self, abbr_dict: dict, key: str):
289
+ def _extract_text_content(self, abbr_dict: dict[str, Any], key: str):
287
290
  """Extract and clean text content from dictionary.
288
291
 
289
292
  Args:
290
- abbr_dict (dict): Dictionary containing publication data.
293
+ abbr_dict (dict[str, Any]): Dictionary containing publication data.
291
294
  key (str): Key to extract text content from.
292
295
 
293
296
  Returns:
@@ -295,11 +298,11 @@ class GenerateDataDict:
295
298
  """
296
299
  return [text for text in abbr_dict.get(key, []) if text.strip()]
297
300
 
298
- def _extract_first_url(self, abbr_dict: dict, key: str):
301
+ def _extract_first_url(self, abbr_dict: dict[str, Any], key: str):
299
302
  """Extract first URL from a list in dictionary.
300
303
 
301
304
  Args:
302
- abbr_dict (dict): Dictionary containing publication data.
305
+ abbr_dict (dict[str, Any]): Dictionary containing publication data.
303
306
  key (str): Key to extract URLs from.
304
307
 
305
308
  Returns:
@@ -308,11 +311,11 @@ class GenerateDataDict:
308
311
  urls = [url.strip() for url in abbr_dict.get(key, []) if url.strip()]
309
312
  return urls[0].split(",")[0] if urls else ""
310
313
 
311
- def _process_keywords(self, abbr_dict: dict):
314
+ def _process_keywords(self, abbr_dict: dict[str, Any]):
312
315
  """Process keywords and convert to Google search URLs.
313
316
 
314
317
  Args:
315
- abbr_dict (dict): Dictionary containing publication data.
318
+ abbr_dict (dict[str, Any]): Dictionary containing publication data.
316
319
 
317
320
  Returns:
318
321
  tuple: A tuple containing (keywords, keywords_url) where keywords
@@ -350,11 +353,11 @@ class GenerateDataDict:
350
353
 
351
354
  return all_keywords, keywords_url
352
355
 
353
- def _format_top_score(self, abbr_dict: dict):
356
+ def _format_top_score(self, abbr_dict: dict[str, Any]):
354
357
  """Format top score with optional early access link.
355
358
 
356
359
  Args:
357
- abbr_dict (dict): Dictionary containing publication data.
360
+ abbr_dict (dict[str, Any]): Dictionary containing publication data.
358
361
 
359
362
  Returns:
360
363
  str: Formatted top score with optional early access link.
@@ -376,7 +379,17 @@ class GenerateDataDict:
376
379
  return f"[{text}]({url})" if url else text
377
380
 
378
381
  def _generate_table_row(
379
- self, publisher_url, full_name, abbr_name, url_home, url_about, period, top, keywords, abbr, abbr_dict
382
+ self,
383
+ publisher_url: str,
384
+ full_name: str,
385
+ abbr_name: str,
386
+ url_home: str,
387
+ url_about: str,
388
+ period: str,
389
+ top: str,
390
+ keywords: list[str],
391
+ abbr: str,
392
+ abbr_dict: dict[str, Any],
380
393
  ):
381
394
  """Generate appropriate table row based on publication type."""
382
395
  if self.cj == "conferences":
@@ -390,7 +403,17 @@ class GenerateDataDict:
390
403
 
391
404
  # Conferences
392
405
  def _generate_for_conference(
393
- self, publisher_url, full_name, abbr_name, url_home, url_about, period, top, keywords, abbr, abbr_dict
406
+ self,
407
+ publisher_url: str,
408
+ full_name: str,
409
+ abbr_name: str,
410
+ url_home: str,
411
+ url_about: str,
412
+ period: str,
413
+ top: str,
414
+ keywords: list[str],
415
+ abbr: str,
416
+ abbr_dict: dict[str, Any],
394
417
  ):
395
418
  """Generate a markdown table row for conference information.
396
419
 
@@ -441,7 +464,7 @@ class GenerateDataDict:
441
464
  keywords,
442
465
  )
443
466
 
444
- def _process_conference_dates(self, abbr_dict):
467
+ def _process_conference_dates(self, abbr_dict: dict[str, Any]):
445
468
  """Parse and return conference dates."""
446
469
  # Parse abstract due date
447
470
  abstract_due = None
@@ -458,7 +481,7 @@ class GenerateDataDict:
458
481
 
459
482
  return abstract_due, start_date, today
460
483
 
461
- def _format_date_indicators(self, abstract_due, start_date, today):
484
+ def _format_date_indicators(self, abstract_due, start_date, today) -> tuple[str, str]:
462
485
  """Format date indicators for display."""
463
486
  abstract_indicator, start_indicator = "", ""
464
487
 
@@ -479,22 +502,22 @@ class GenerateDataDict:
479
502
 
480
503
  def _build_conference_row(
481
504
  self,
482
- publisher_url,
483
- full_name,
484
- abbr_name,
485
- url_home,
486
- url_about,
487
- archive_display,
488
- period,
489
- top,
490
- abbr_dict,
505
+ publisher_url: str,
506
+ full_name: str,
507
+ abbr_name: str,
508
+ url_home: str,
509
+ url_about: str,
510
+ archive_display: str,
511
+ period: str,
512
+ top: str,
513
+ abbr_dict: dict[str, Any],
491
514
  abstract_due,
492
- abstract_indicator,
515
+ abstract_indicator: str,
493
516
  start_date,
494
- start_indicator,
495
- year_url,
496
- keywords,
497
- ):
517
+ start_indicator: str,
518
+ year_url: str,
519
+ keywords: list[str],
520
+ ) -> str:
498
521
  """Construct conference table row string."""
499
522
  # Format date strings
500
523
  abstract_date_str = abstract_due.strftime("%d/%m/%Y") if abstract_due else ""
@@ -522,8 +545,18 @@ class GenerateDataDict:
522
545
 
523
546
  # Journals
524
547
  def _generate_for_journal(
525
- self, publisher_url, full_name, abbr_name, url_home, url_about, period, top, keywords, abbr, abbr_dict
526
- ):
548
+ self,
549
+ publisher_url: str,
550
+ full_name: str,
551
+ abbr_name: str,
552
+ url_home: str,
553
+ url_about: str,
554
+ period: str,
555
+ top: str,
556
+ keywords: list[str],
557
+ abbr: str,
558
+ abbr_dict: dict[str, Any],
559
+ ) -> str:
527
560
  r"""Generate a markdown table row for journal information.
528
561
 
529
562
  Args:
@@ -551,8 +584,18 @@ class GenerateDataDict:
551
584
  )
552
585
 
553
586
  def _build_journal_row(
554
- self, publisher_url, full_name, abbr_name, url_home, url_about, issues_display, period, top, abbr_dict, keywords
555
- ):
587
+ self,
588
+ publisher_url: str,
589
+ full_name: str,
590
+ abbr_name: str,
591
+ url_home: str,
592
+ url_about: str,
593
+ issues_display: str,
594
+ period: str,
595
+ top: str,
596
+ abbr_dict: dict[str, Any],
597
+ keywords: list[str],
598
+ ) -> str:
556
599
  """Construct journal table row string."""
557
600
  return (
558
601
  f"|{publisher_url}|"
@@ -569,7 +612,7 @@ class GenerateDataDict:
569
612
  )
570
613
 
571
614
  # Mermaid data
572
- def generate_mermaid_data(self, publisher: str, abbr: str, inproceedings_or_article: str):
615
+ def generate_mermaid_data(self, publisher: str, abbr: str, inproceedings_or_article: str) -> list[str]:
573
616
  """Generate Mermaid diagram data from spidered README files.
574
617
 
575
618
  This method reads spidered data from README files and generates
@@ -15,7 +15,7 @@ def create_safe_filename(text: str) -> str:
15
15
  return safe_text if safe_text else "unnamed"
16
16
 
17
17
 
18
- def conference_journal_informations():
18
+ def conference_journal_informations() -> tuple[list[str], list[str]]:
19
19
  """Generate informational content for conferences and journals.
20
20
 
21
21
  This function provides additional informational content that can be
@@ -0,0 +1,24 @@
1
+ {
2
+ "build_systems": [
3
+ {
4
+ "file_patterns": ["*.py"],
5
+ "selector": "source.python",
6
+ "working_dir": "${project_path}",
7
+ "name": "Python3 Virtual Env",
8
+ "target": "terminus_exec",
9
+ "cancel": "terminus_cancel_build",
10
+ "shell_cmd": "\".venv/bin/python3\" -u \"$file\"",
11
+ "env": {
12
+ "PYTHONIOENCODING": "utf-8",
13
+ "PYTHONPATH": ".",
14
+ },
15
+ "file_regex": "^[ ]*File \"(...*?)\", line ([0-9]*)",
16
+ },
17
+ ],
18
+ "settings": {},
19
+ "folders": [
20
+ {
21
+ "path": ".",
22
+ },
23
+ ],
24
+ }
@@ -1,24 +1,62 @@
1
- [tool.poetry]
1
+ [project]
2
2
  name = "pyformatjson"
3
- version = "0.2.5"
3
+ version = "0.2.6"
4
4
  description = "pyformatjson"
5
5
  license = "GPL-3.0-or-later"
6
- authors = ["NextAI <nextartifintell@gmail.com>"]
7
- maintainers = ["NextAI <nextartifintell@gmail.com>"]
8
- readme = ["README.md"]
9
- homepage = "https://github.com/Easy-PhD/pyformatjson"
10
- repository = "https://github.com/Easy-PhD/pyformatjson"
11
- documentation = "https://github.com/Easy-PhD/pyformatjson"
12
- keywords = ["Python", "Json"]
13
- classifiers = ["Topic :: Software Development :: Libraries :: Python Modules"]
6
+ license-files = ["LICENSE"]
7
+ authors = [
8
+ {name = "NextAI", email = "nextartifintell@gmail.com"},
9
+ ]
10
+ maintainers = [
11
+ {name = "NextAI", email = "nextartifintell@gmail.com"},
12
+ ]
13
+ readme = "README.md"
14
+ keywords = ["Python", "JSON"]
15
+ classifiers = [
16
+ "Operating System :: OS Independent",
17
+ "Programming Language :: Python",
18
+ "Programming Language :: Python :: 3",
19
+ "Programming Language :: Python :: 3.12",
20
+ "Programming Language :: Python :: 3.13",
21
+ "Programming Language :: Python :: 3.14",
22
+ "Topic :: Software Development :: Libraries :: Python Modules"
23
+ ]
24
+ requires-python = ">=3.12"
25
+ dependencies = [
26
+ "beautifulsoup4>=4.14.2",
27
+ "func-timeout>=4.3.5",
28
+ "lxml>=6.0.2",
29
+ "playwright>=1.55.0",
30
+ "psutil>=7.1.2",
31
+ "pyadvtools>=0.3.8",
32
+ "requests>=2.32.5",
33
+ "selenium>=4.38.0",
34
+ ]
14
35
 
15
- [tool.poetry.dependencies]
16
- python = ">=3.12"
36
+ [project.urls]
37
+ Homepage = "https://github.com/Easy-PhD/pyformatjson"
38
+ Repository = "https://github.com/Easy-PhD/pyformatjson"
39
+ Documentation = "https://Easy-PhD.github.io/pyformatjson"
40
+ Source = "https://github.com/Easy-PhD/pyformatjson"
41
+ Issues = "https://github.com/Easy-PhD/pyformatjson/issues"
42
+ Changelog = "https://github.com/Easy-PhD/pyformatjson/releases"
17
43
 
18
- [tool.poetry.group.dev.dependencies]
19
- sphinx = "^8.2.3"
20
- sphinx-rtd-theme = "^3.0.2"
21
- sphinx-copybutton = "^0.5.2"
44
+ [dependency-groups]
45
+ dev = [
46
+ "pytest>=8.4.2",
47
+ "pytest-cov>=7.0.0",
48
+ ]
49
+
50
+ docs = [
51
+ "ruff>=0.14.3",
52
+ "mkdocs>=1.6.1",
53
+ "mkdocs-autorefs>=1.4.3",
54
+ "mkdocs-material>=9.6.21",
55
+ "mkdocs-material-extensions>=1.3.1",
56
+ "mkdocs-minify-plugin>=0.8.0",
57
+ "mkdocs-redirects>=1.2.2",
58
+ "mkdocstrings[python]>=0.30.1",
59
+ ]
22
60
 
23
61
  [tool.pyright]
24
62
  venvPath = "."
@@ -91,5 +129,5 @@ include_trailing_comma = true
91
129
  [tool.pytest]
92
130
 
93
131
  [build-system]
94
- requires = ["poetry-core>=1.0.0"]
95
- build-backend = "poetry.core.masonry.api"
132
+ requires = ["hatchling"]
133
+ build-backend = "hatchling.build"
@@ -0,0 +1,134 @@
1
+ #!/usr/bin/env python3
2
+
3
+ from pathlib import Path
4
+ from typing import Any
5
+
6
+
7
+ class DocGenerator:
8
+ """Documentation generator class."""
9
+
10
+ def __init__(self, package_name: str, source_dir: str, docs_dir: str = "docs"):
11
+ self.package_name = package_name
12
+ self.source_dir = Path(source_dir)
13
+ self.docs_dir = Path(docs_dir)
14
+ self.api_dir = self.docs_dir / "api-auto"
15
+
16
+ # Create necessary directories
17
+ self.api_dir.mkdir(parents=True, exist_ok=True)
18
+
19
+ def discover_modules(self) -> list[Path]:
20
+ modules = []
21
+
22
+ for py_file in self.source_dir.rglob("*.py"):
23
+ # Skip __pycache__ directories and test files
24
+ if "__pycache__" in str(py_file) or "test" in str(py_file).lower():
25
+ continue
26
+
27
+ # Skip empty files and __init__.py files (handled separately)
28
+ if py_file.name == "__init__.py":
29
+ continue
30
+
31
+ modules.append(py_file)
32
+
33
+ return modules
34
+
35
+ def get_module_info(self, module_path: Path) -> dict[str, Any]:
36
+ # Calculate relative import path
37
+ relative_path = module_path.relative_to(self.source_dir)
38
+ module_name = str(relative_path).replace("/", ".").replace("\\", ".").replace(".py", "")
39
+
40
+ return {
41
+ "path": module_path,
42
+ "name": module_name,
43
+ "import_path": f"{self.package_name}.{module_name}",
44
+ "doc_path": self.api_dir / f"{module_name}.md"
45
+ }
46
+
47
+ def generate_module_doc(self, module_info: dict[str, Any]) -> str:
48
+ module_name = module_info["name"]
49
+ import_path = module_info["import_path"]
50
+
51
+ content = [
52
+ f"# {module_name}",
53
+ "",
54
+ f"::: {import_path}",
55
+ " options:",
56
+ " show_root_heading: false",
57
+ " show_submodules: true",
58
+ " heading_level: 2",
59
+ " show_source: true",
60
+ " show_category_heading: true",
61
+ ""
62
+ ]
63
+
64
+ return "\n".join(content)
65
+
66
+ def generate_api_index(self) -> str:
67
+ modules = self.discover_modules()
68
+ module_infos = [self.get_module_info(module) for module in modules]
69
+
70
+ content = [
71
+ "# API Reference",
72
+ "",
73
+ f"This is the complete API reference documentation for the {self.package_name} library.",
74
+ "",
75
+ "## Module List",
76
+ ""
77
+ ]
78
+
79
+ # Group modules by directory
80
+ modules_by_dir = {}
81
+ for info in module_infos:
82
+ dir_path = str(Path(info["name"]).parent)
83
+ if dir_path == ".":
84
+ dir_path = "Root Modules"
85
+ if dir_path not in modules_by_dir:
86
+ modules_by_dir[dir_path] = []
87
+ modules_by_dir[dir_path].append(info)
88
+
89
+ # Generate directory structure
90
+ for dir_name in sorted(modules_by_dir.keys()):
91
+ content.append(f"### {dir_name}")
92
+ content.append("")
93
+
94
+ for info in sorted(modules_by_dir[dir_name], key=lambda x: x["name"]):
95
+ module_name = info["name"]
96
+ doc_file = f"api-auto/{module_name}.md"
97
+ content.append(f"- [{module_name}]({doc_file})")
98
+
99
+ content.append("")
100
+
101
+ return "\n".join(content)
102
+
103
+ def write_file(self, filepath: Path, content: str) -> None:
104
+ # Ensure directory exists
105
+ filepath.parent.mkdir(parents=True, exist_ok=True)
106
+
107
+ with open(filepath, "w", encoding="utf-8") as f:
108
+ f.write(content)
109
+
110
+ print(f"✓ Generated documentation: {filepath}")
111
+
112
+ def generate_all(self) -> None:
113
+ """Generate all documentation."""
114
+ print("Starting API documentation generation...")
115
+
116
+ # Generate documentation for individual modules
117
+ modules = self.discover_modules()
118
+ print(f"Found {len(modules)} modules")
119
+
120
+ for module_path in modules:
121
+ module_info = self.get_module_info(module_path)
122
+ doc_content = self.generate_module_doc(module_info)
123
+ self.write_file(module_info["doc_path"], doc_content)
124
+
125
+ # Generate API index
126
+ api_index_content = self.generate_api_index()
127
+ self.write_file(self.docs_dir / "api-auto.md", api_index_content)
128
+
129
+ print("Documentation generation completed!")
130
+
131
+
132
+ if __name__ == "__main__":
133
+ generator = DocGenerator("pyformatjson", "pyformatjson")
134
+ generator.generate_all()
File without changes
File without changes