paperpush 0.1.0__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 (108) hide show
  1. paperpush-0.1.0/LICENSE +24 -0
  2. paperpush-0.1.0/PKG-INFO +113 -0
  3. paperpush-0.1.0/README.md +82 -0
  4. paperpush-0.1.0/paperpush/__init__.py +47 -0
  5. paperpush-0.1.0/paperpush/_logging.py +84 -0
  6. paperpush-0.1.0/paperpush/autofill.py +533 -0
  7. paperpush-0.1.0/paperpush/cli.py +1031 -0
  8. paperpush-0.1.0/paperpush/credentials.py +312 -0
  9. paperpush-0.1.0/paperpush/database.py +566 -0
  10. paperpush-0.1.0/paperpush/manuscript.py +408 -0
  11. paperpush-0.1.0/paperpush/orcid.py +442 -0
  12. paperpush-0.1.0/paperpush/schema_models.py +206 -0
  13. paperpush-0.1.0/paperpush/sensitive.py +785 -0
  14. paperpush-0.1.0/paperpush/subfile.py +312 -0
  15. paperpush-0.1.0/paperpush/subfile_templates/arxiv.sub +80 -0
  16. paperpush-0.1.0/paperpush/subfile_templates/bioinformatics.sub +211 -0
  17. paperpush-0.1.0/paperpush/subfile_templates/biorxiv.sub +100 -0
  18. paperpush-0.1.0/paperpush/subfile_templates/bmc_bioinformatics.sub +75 -0
  19. paperpush-0.1.0/paperpush/subfile_templates/cell.sub +89 -0
  20. paperpush-0.1.0/paperpush/subfile_templates/cell_genomics.sub +84 -0
  21. paperpush-0.1.0/paperpush/subfile_templates/cell_systems.sub +89 -0
  22. paperpush-0.1.0/paperpush/subfile_templates/discrete_mathematics.sub +92 -0
  23. paperpush-0.1.0/paperpush/subfile_templates/genome_biology.sub +75 -0
  24. paperpush-0.1.0/paperpush/subfile_templates/medrxiv.sub +115 -0
  25. paperpush-0.1.0/paperpush/subfile_templates/nature.sub +114 -0
  26. paperpush-0.1.0/paperpush/subfile_templates/nature_biotech.sub +114 -0
  27. paperpush-0.1.0/paperpush/subfile_templates/nature_methods.sub +108 -0
  28. paperpush-0.1.0/paperpush/subfile_templates/nucleic_acids_research.sub +146 -0
  29. paperpush-0.1.0/paperpush/subfile_templates/plos_compbio.sub +137 -0
  30. paperpush-0.1.0/paperpush/subfile_templates/science.sub +92 -0
  31. paperpush-0.1.0/paperpush/subfile_templates/science_advances.sub +92 -0
  32. paperpush-0.1.0/paperpush/subfile_templates/science_immunology.sub +92 -0
  33. paperpush-0.1.0/paperpush/subfile_templates/science_robotics.sub +92 -0
  34. paperpush-0.1.0/paperpush/subfile_templates/science_signaling.sub +92 -0
  35. paperpush-0.1.0/paperpush/subfile_templates/science_translational_medicine.sub +92 -0
  36. paperpush-0.1.0/paperpush/validate.py +971 -0
  37. paperpush-0.1.0/paperpush/venues/__init__.py +233 -0
  38. paperpush-0.1.0/paperpush/venues/_assets/aaai_2027_countries.txt +196 -0
  39. paperpush-0.1.0/paperpush/venues/_assets/aaai_2027_topics.txt +203 -0
  40. paperpush-0.1.0/paperpush/venues/_assets/arxiv_categories.txt +155 -0
  41. paperpush-0.1.0/paperpush/venues/_assets/bioinformatics_keywords.txt +192 -0
  42. paperpush-0.1.0/paperpush/venues/_assets/genome_biology_institution_countries.txt +249 -0
  43. paperpush-0.1.0/paperpush/venues/_assets/nature_biotech_categories.json +18659 -0
  44. paperpush-0.1.0/paperpush/venues/_assets/nature_categories.json +22740 -0
  45. paperpush-0.1.0/paperpush/venues/_assets/nature_methods_categories.json +22740 -0
  46. paperpush-0.1.0/paperpush/venues/_assets/plos_compbio_classifications.txt +257 -0
  47. paperpush-0.1.0/paperpush/venues/_assets/plos_compbio_funding_countries.txt +197 -0
  48. paperpush-0.1.0/paperpush/venues/_assets/science_advances_subjects.txt +82 -0
  49. paperpush-0.1.0/paperpush/venues/_assets/science_immunology_subjects.txt +51 -0
  50. paperpush-0.1.0/paperpush/venues/_assets/science_robotics_subjects.txt +50 -0
  51. paperpush-0.1.0/paperpush/venues/_assets/science_signaling_subjects.txt +116 -0
  52. paperpush-0.1.0/paperpush/venues/_assets/science_subjects.txt +58 -0
  53. paperpush-0.1.0/paperpush/venues/_assets/science_translational_medicine_subjects.txt +62 -0
  54. paperpush-0.1.0/paperpush/venues/arxiv/__init__.py +0 -0
  55. paperpush-0.1.0/paperpush/venues/arxiv/arxiv.py +166 -0
  56. paperpush-0.1.0/paperpush/venues/base.py +273 -0
  57. paperpush-0.1.0/paperpush/venues/common.py +249 -0
  58. paperpush-0.1.0/paperpush/venues/discrete_mathematics/__init__.py +0 -0
  59. paperpush-0.1.0/paperpush/venues/discrete_mathematics/discrete_mathematics.py +438 -0
  60. paperpush-0.1.0/paperpush/venues/editorialmanager/__init__.py +0 -0
  61. paperpush-0.1.0/paperpush/venues/editorialmanager/cell.py +22 -0
  62. paperpush-0.1.0/paperpush/venues/editorialmanager/cell_genomics.py +22 -0
  63. paperpush-0.1.0/paperpush/venues/editorialmanager/cell_systems.py +22 -0
  64. paperpush-0.1.0/paperpush/venues/editorialmanager/main.py +1119 -0
  65. paperpush-0.1.0/paperpush/venues/editorialmanager/plos_compbio.py +22 -0
  66. paperpush-0.1.0/paperpush/venues/login.py +202 -0
  67. paperpush-0.1.0/paperpush/venues/nature/__init__.py +0 -0
  68. paperpush-0.1.0/paperpush/venues/nature/main.py +1413 -0
  69. paperpush-0.1.0/paperpush/venues/nature/nature.py +39 -0
  70. paperpush-0.1.0/paperpush/venues/nature/nature_biotech.py +39 -0
  71. paperpush-0.1.0/paperpush/venues/nature/nature_methods.py +40 -0
  72. paperpush-0.1.0/paperpush/venues/openreview/__init__.py +6 -0
  73. paperpush-0.1.0/paperpush/venues/openreview/aaai_2027.py +417 -0
  74. paperpush-0.1.0/paperpush/venues/openrxiv/__init__.py +0 -0
  75. paperpush-0.1.0/paperpush/venues/openrxiv/biorxiv.py +28 -0
  76. paperpush-0.1.0/paperpush/venues/openrxiv/main.py +891 -0
  77. paperpush-0.1.0/paperpush/venues/openrxiv/medrxiv.py +32 -0
  78. paperpush-0.1.0/paperpush/venues/scholarone/__init__.py +0 -0
  79. paperpush-0.1.0/paperpush/venues/scholarone/bioinformatics.py +357 -0
  80. paperpush-0.1.0/paperpush/venues/scholarone/main.py +372 -0
  81. paperpush-0.1.0/paperpush/venues/scholarone/nucleic_acids_research.py +515 -0
  82. paperpush-0.1.0/paperpush/venues/science/__init__.py +0 -0
  83. paperpush-0.1.0/paperpush/venues/science/science.py +794 -0
  84. paperpush-0.1.0/paperpush/venues/snapp/__init__.py +0 -0
  85. paperpush-0.1.0/paperpush/venues/snapp/bmc_bioinformatics.py +29 -0
  86. paperpush-0.1.0/paperpush/venues/snapp/genome_biology.py +29 -0
  87. paperpush-0.1.0/paperpush/venues/snapp/main.py +683 -0
  88. paperpush-0.1.0/paperpush/venues/template/template.py +73 -0
  89. paperpush-0.1.0/paperpush/venues.json +3082 -0
  90. paperpush-0.1.0/paperpush/venues.schema.json +856 -0
  91. paperpush-0.1.0/paperpush.egg-info/PKG-INFO +113 -0
  92. paperpush-0.1.0/paperpush.egg-info/SOURCES.txt +106 -0
  93. paperpush-0.1.0/paperpush.egg-info/dependency_links.txt +1 -0
  94. paperpush-0.1.0/paperpush.egg-info/entry_points.txt +2 -0
  95. paperpush-0.1.0/paperpush.egg-info/requires.txt +17 -0
  96. paperpush-0.1.0/paperpush.egg-info/top_level.txt +1 -0
  97. paperpush-0.1.0/pyproject.toml +61 -0
  98. paperpush-0.1.0/setup.cfg +4 -0
  99. paperpush-0.1.0/tests/test_autofill.py +740 -0
  100. paperpush-0.1.0/tests/test_internals.py +422 -0
  101. paperpush-0.1.0/tests/test_logging.py +150 -0
  102. paperpush-0.1.0/tests/test_login.py +288 -0
  103. paperpush-0.1.0/tests/test_portal_drift.py +459 -0
  104. paperpush-0.1.0/tests/test_sensitive.py +285 -0
  105. paperpush-0.1.0/tests/test_subfile.py +300 -0
  106. paperpush-0.1.0/tests/test_submit.py +399 -0
  107. paperpush-0.1.0/tests/test_validate.py +1235 -0
  108. paperpush-0.1.0/tests/test_venue_interface.py +114 -0
@@ -0,0 +1,24 @@
1
+ BSD 2-Clause License
2
+
3
+ Copyright (c) 2024, Pachter Lab
4
+
5
+ Redistribution and use in source and binary forms, with or without
6
+ modification, are permitted provided that the following conditions are met:
7
+
8
+ 1. Redistributions of source code must retain the above copyright notice, this
9
+ list of conditions and the following disclaimer.
10
+
11
+ 2. Redistributions in binary form must reproduce the above copyright notice,
12
+ this list of conditions and the following disclaimer in the documentation
13
+ and/or other materials provided with the distribution.
14
+
15
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
19
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,113 @@
1
+ Metadata-Version: 2.4
2
+ Name: paperpush
3
+ Version: 0.1.0
4
+ Summary: A Python library for automating the submission of manuscripts to academic venues.
5
+ Author-email: Joseph Rich <josephrich98@gmail.com>
6
+ Maintainer-email: Joseph Rich <josephrich98@gmail.com>
7
+ License: MIT
8
+ Project-URL: Homepage, https://github.com/pachterlab/paperpush
9
+ Project-URL: Repository, https://github.com/pachterlab/paperpush
10
+ Project-URL: Documentation, https://github.com/pachterlab/paperpush#readme
11
+ Project-URL: Issues, https://github.com/pachterlab/paperpush/issues
12
+ Requires-Python: >=3.10
13
+ Description-Content-Type: text/markdown
14
+ License-File: LICENSE
15
+ Requires-Dist: playwright>=1.40
16
+ Requires-Dist: keyring>=24.0
17
+ Requires-Dist: pydantic>=2.0
18
+ Requires-Dist: pypdf>=6.0.0
19
+ Requires-Dist: pillow>=10.0
20
+ Provides-Extra: autofill
21
+ Requires-Dist: anthropic>=0.40; extra == "autofill"
22
+ Provides-Extra: dev
23
+ Requires-Dist: pytest>=7.0; extra == "dev"
24
+ Requires-Dist: bandit; extra == "dev"
25
+ Requires-Dist: black; extra == "dev"
26
+ Requires-Dist: chromium; extra == "dev"
27
+ Requires-Dist: jsonschema>=4.18; extra == "dev"
28
+ Requires-Dist: sphinx; extra == "dev"
29
+ Requires-Dist: isort; extra == "dev"
30
+ Dynamic: license-file
31
+
32
+ # PaperPush: Automated manuscript submission to journals, conferences, and preprint servers
33
+
34
+ <!-- [![Documentation Status](https://readthedocs.org/projects/paperpush/badge/?version=latest)](https://paperpush.readthedocs.io/en/latest/?badge=latest) -->
35
+
36
+ Prepare manuscripts for submission to preprint servers, venues, and conferences with just a few commands. No need to spend hours filling out forms manually. Just provide a manuscript directory and submission venue of interest, and `paperpush` will fill out the submission portal for you.
37
+
38
+ ## Install
39
+
40
+ ```bash
41
+ pip install paperpush
42
+ ```
43
+
44
+ To install the playwright dependency and the required browsers, run:
45
+
46
+ ```bash
47
+ playwright install
48
+ ```
49
+
50
+ ## Use with AI
51
+ ```LLM
52
+ Prepare my manuscript in /PATH/TO/MANUSCRIPT/DIRECTORY for submission to VENUE with PaperPush.
53
+ ```
54
+
55
+ The Claude skill `/paperpush-prepare-submission` helps with this.
56
+
57
+ See [`docs/example-session.md`](docs/example-session.md) for a full worked example of this flow.
58
+
59
+ ## Quickstart
60
+ 1. `paperpush subfile VENUE`: creates a file VENUE.sub that is a template for the VENUE submission.
61
+ 2. **fill out VENUE.sub - 3 options:**
62
+ - **a.** *fill out manually*
63
+ - **b.** *Ask an LLM*: Use Claude skill `/paperpush-autofill`, or any AI agent following [`AGENTS.md`](AGENTS.md).
64
+ - **c.** `paperpush autofill -d /PATH/TO/MANUSCRIPT/DIRECTORY --engine api VENUE.sub`: Use an LLM API. Requires an API key.
65
+ 3. `paperpush validate VENUE.sub`: run the pre-submission checks on the filled `VENUE.sub`.
66
+ 4. `paperpush login VENUE`: log in to the VENUE submission portal
67
+ 5. `paperpush submit VENUE.sub`: Fill out the VENUE submission portal. Will not actually submit the manuscript. We highly recommend reviewing the submission form in the venue portal before clicking submit.
68
+
69
+ ## Run the whole pipeline at once
70
+
71
+ `scripts/paperpush_pipeline.py` sequentially runs the commands above — `subfile`, `autofill`, `validate`, `login`, `submit`. This allows going from a manuscript directory to a filled submission portal in just one command.
72
+
73
+ ```bash
74
+ python scripts/paperpush_pipeline.py -d /PATH/TO/MANUSCRIPT/DIRECTORY --engine api VENUE
75
+ ```
76
+
77
+ See `python scripts/paperpush_pipeline.py --help` for the full list of options, grouped by step.
78
+
79
+ ## Supported venues
80
+
81
+ <!-- BEGIN SUPPORTED VENUES -->
82
+ **Preprint servers:** [arXiv](https://arxiv.org), [bioRxiv](https://www.biorxiv.org), [medRxiv](https://www.medrxiv.org)
83
+
84
+ **Journals:** [Bioinformatics](https://academic.oup.com/bioinformatics), [BMC Bioinformatics](https://link.springer.com/journal/12859), [Cell](https://www.cell.com/cell/home), [Cell Genomics](https://www.cell.com/cell-genomics/home), [Cell Systems](https://www.cell.com/cell-systems/home), [Discrete Mathematics](https://www.sciencedirect.com/journal/discrete-mathematics), [Genome Biology](https://genomebiology.biomedcentral.com), [Nature](https://www.nature.com), [Nature Biotechnology](https://www.nature.com/nbt), [Nature Methods](https://www.nature.com/nmeth), [Nucleic Acids Research](https://academic.oup.com/nar), [PLOS Computational Biology](https://journal.plos.org/ploscompbiol/), [Science](https://www.science.org/journal/science), [Science Advances](https://www.science.org/journal/sciadv), [Science Immunology](https://www.science.org/journal/sciimmunol), [Science Robotics](https://www.science.org/journal/scirobotics), [Science Signaling](https://www.science.org/journal/signaling), [Science Translational Medicine](https://www.science.org/journal/stm)
85
+
86
+ **Conferences:** _none yet_
87
+ <!-- END SUPPORTED VENUES -->
88
+
89
+ View the list on the command line with `paperpush --venues`.
90
+
91
+ For more details, see [`venues.md`](venues.md)
92
+
93
+ ## Documentation
94
+
95
+ [paperpush.readthedocs.io](https://paperpush.readthedocs.io)
96
+
97
+ ## Adding new venues
98
+
99
+ See [`CONTRIBUTING.md`](CONTRIBUTING.md) for instructions on adding new venues. See [`DEVELOPMENT.md`](DEVELOPMENT.md) for tips on adding new venues and running unit tests.
100
+
101
+ ## For AI agents
102
+
103
+ If you are an AI agent asked to submit a manuscript on the user's behalf, read
104
+ [`AGENTS.md`](AGENTS.md). It describes how to run the full pipeline while doing
105
+ your **own** field extraction (reading the manuscript and writing a
106
+ `values.json` for the default `--engine manual`) rather than relying on the
107
+ API-backed engine. Claude Code should prefer the `/paperpush-prepare-submission`
108
+ and `/paperpush-autofill` skills, which encode the same contract.
109
+
110
+ ## License
111
+ This project is licensed under the BSD-2 License - see the [LICENSE](LICENSE) file for details.
112
+
113
+ Developed by Joe Rich
@@ -0,0 +1,82 @@
1
+ # PaperPush: Automated manuscript submission to journals, conferences, and preprint servers
2
+
3
+ <!-- [![Documentation Status](https://readthedocs.org/projects/paperpush/badge/?version=latest)](https://paperpush.readthedocs.io/en/latest/?badge=latest) -->
4
+
5
+ Prepare manuscripts for submission to preprint servers, venues, and conferences with just a few commands. No need to spend hours filling out forms manually. Just provide a manuscript directory and submission venue of interest, and `paperpush` will fill out the submission portal for you.
6
+
7
+ ## Install
8
+
9
+ ```bash
10
+ pip install paperpush
11
+ ```
12
+
13
+ To install the playwright dependency and the required browsers, run:
14
+
15
+ ```bash
16
+ playwright install
17
+ ```
18
+
19
+ ## Use with AI
20
+ ```LLM
21
+ Prepare my manuscript in /PATH/TO/MANUSCRIPT/DIRECTORY for submission to VENUE with PaperPush.
22
+ ```
23
+
24
+ The Claude skill `/paperpush-prepare-submission` helps with this.
25
+
26
+ See [`docs/example-session.md`](docs/example-session.md) for a full worked example of this flow.
27
+
28
+ ## Quickstart
29
+ 1. `paperpush subfile VENUE`: creates a file VENUE.sub that is a template for the VENUE submission.
30
+ 2. **fill out VENUE.sub - 3 options:**
31
+ - **a.** *fill out manually*
32
+ - **b.** *Ask an LLM*: Use Claude skill `/paperpush-autofill`, or any AI agent following [`AGENTS.md`](AGENTS.md).
33
+ - **c.** `paperpush autofill -d /PATH/TO/MANUSCRIPT/DIRECTORY --engine api VENUE.sub`: Use an LLM API. Requires an API key.
34
+ 3. `paperpush validate VENUE.sub`: run the pre-submission checks on the filled `VENUE.sub`.
35
+ 4. `paperpush login VENUE`: log in to the VENUE submission portal
36
+ 5. `paperpush submit VENUE.sub`: Fill out the VENUE submission portal. Will not actually submit the manuscript. We highly recommend reviewing the submission form in the venue portal before clicking submit.
37
+
38
+ ## Run the whole pipeline at once
39
+
40
+ `scripts/paperpush_pipeline.py` sequentially runs the commands above — `subfile`, `autofill`, `validate`, `login`, `submit`. This allows going from a manuscript directory to a filled submission portal in just one command.
41
+
42
+ ```bash
43
+ python scripts/paperpush_pipeline.py -d /PATH/TO/MANUSCRIPT/DIRECTORY --engine api VENUE
44
+ ```
45
+
46
+ See `python scripts/paperpush_pipeline.py --help` for the full list of options, grouped by step.
47
+
48
+ ## Supported venues
49
+
50
+ <!-- BEGIN SUPPORTED VENUES -->
51
+ **Preprint servers:** [arXiv](https://arxiv.org), [bioRxiv](https://www.biorxiv.org), [medRxiv](https://www.medrxiv.org)
52
+
53
+ **Journals:** [Bioinformatics](https://academic.oup.com/bioinformatics), [BMC Bioinformatics](https://link.springer.com/journal/12859), [Cell](https://www.cell.com/cell/home), [Cell Genomics](https://www.cell.com/cell-genomics/home), [Cell Systems](https://www.cell.com/cell-systems/home), [Discrete Mathematics](https://www.sciencedirect.com/journal/discrete-mathematics), [Genome Biology](https://genomebiology.biomedcentral.com), [Nature](https://www.nature.com), [Nature Biotechnology](https://www.nature.com/nbt), [Nature Methods](https://www.nature.com/nmeth), [Nucleic Acids Research](https://academic.oup.com/nar), [PLOS Computational Biology](https://journal.plos.org/ploscompbiol/), [Science](https://www.science.org/journal/science), [Science Advances](https://www.science.org/journal/sciadv), [Science Immunology](https://www.science.org/journal/sciimmunol), [Science Robotics](https://www.science.org/journal/scirobotics), [Science Signaling](https://www.science.org/journal/signaling), [Science Translational Medicine](https://www.science.org/journal/stm)
54
+
55
+ **Conferences:** _none yet_
56
+ <!-- END SUPPORTED VENUES -->
57
+
58
+ View the list on the command line with `paperpush --venues`.
59
+
60
+ For more details, see [`venues.md`](venues.md)
61
+
62
+ ## Documentation
63
+
64
+ [paperpush.readthedocs.io](https://paperpush.readthedocs.io)
65
+
66
+ ## Adding new venues
67
+
68
+ See [`CONTRIBUTING.md`](CONTRIBUTING.md) for instructions on adding new venues. See [`DEVELOPMENT.md`](DEVELOPMENT.md) for tips on adding new venues and running unit tests.
69
+
70
+ ## For AI agents
71
+
72
+ If you are an AI agent asked to submit a manuscript on the user's behalf, read
73
+ [`AGENTS.md`](AGENTS.md). It describes how to run the full pipeline while doing
74
+ your **own** field extraction (reading the manuscript and writing a
75
+ `values.json` for the default `--engine manual`) rather than relying on the
76
+ API-backed engine. Claude Code should prefer the `/paperpush-prepare-submission`
77
+ and `/paperpush-autofill` skills, which encode the same contract.
78
+
79
+ ## License
80
+ This project is licensed under the BSD-2 License - see the [LICENSE](LICENSE) file for details.
81
+
82
+ Developed by Joe Rich
@@ -0,0 +1,47 @@
1
+ """paperpush: one-click manuscript submission to academic venues."""
2
+
3
+ import logging
4
+
5
+ __version__ = "0.1.0"
6
+ __url__ = "https://github.com/pachterlab/paperpush"
7
+
8
+ # Standard-library convention: a library should not configure logging output.
9
+ # The NullHandler keeps importing paperpush silent until the embedding
10
+ # application (or our own CLI, via paperpush._logging.configure_logging)
11
+ # installs a real handler.
12
+ #
13
+ # Import stdlib logging under its own name -- NOT ``as _logging`` -- so it does
14
+ # not shadow the ``paperpush._logging`` submodule as a package attribute, which
15
+ # would make ``from paperpush import _logging`` hand back the stdlib module.
16
+ logging.getLogger(__name__).addHandler(logging.NullHandler())
17
+
18
+ # Public API. Kept deliberately small: the two data models (with their
19
+ # accessors), the subfile toolkit, and the two workflow operations that have a
20
+ # library-level entry point. The login and submit steps are exposed only as CLI
21
+ # commands (`paperpush login` / `paperpush submit`), not as importable
22
+ # functions. Lower-level helpers (autofill extraction internals, credential
23
+ # storage, logging setup) remain importable from their submodules
24
+ # (e.g. `from paperpush import credentials`) but are not part of the public API.
25
+ from .database import Field, Venue, get_venue, list_venues
26
+ from .subfile import SubFile, load, parse, render_template, write_template
27
+ from .autofill import autofill
28
+ from .validate import validate
29
+
30
+ __all__ = [
31
+ "__version__",
32
+ "__url__",
33
+ # Data models
34
+ "Field",
35
+ "Venue",
36
+ "get_venue",
37
+ "list_venues",
38
+ # Submission files
39
+ "SubFile",
40
+ "load",
41
+ "parse",
42
+ "render_template",
43
+ "write_template",
44
+ # Workflow operations
45
+ "autofill",
46
+ "validate",
47
+ ]
@@ -0,0 +1,84 @@
1
+ """Logging configuration for the paperpush command-line interface.
2
+
3
+ Library modules obtain a logger with ``logging.getLogger(__name__)`` and never
4
+ install handlers themselves. Following the standard-library convention, the
5
+ package's top-level logger carries a :class:`logging.NullHandler` (attached in
6
+ :mod:`paperpush.__init__`), so importing paperpush as a library stays
7
+ silent unless the embedding application configures logging.
8
+
9
+ The command-line entry point calls :func:`configure_logging` once to attach a
10
+ single stderr handler whose level reflects the ``-v``/``-q`` flags, or the
11
+ ``PAPERPUSH_LOG_LEVEL`` environment variable when set. Diagnostics go to
12
+ stderr so they never mix with command output on stdout.
13
+ """
14
+
15
+ from __future__ import annotations
16
+
17
+ import logging
18
+ import os
19
+ import sys
20
+
21
+ PACKAGE_LOGGER = "paperpush"
22
+
23
+ # Each additional ``-v`` raises the verbosity one step from the WARNING default:
24
+ # -v -> INFO, -vv -> DEBUG.
25
+ _VERBOSITY_LEVELS = [logging.WARNING, logging.INFO, logging.DEBUG]
26
+
27
+ _LOG_FORMAT = "%(asctime)s %(levelname)s %(name)s: %(message)s"
28
+ _DATE_FORMAT = "%H:%M:%S"
29
+
30
+ # Marks the handler this module installs so a later call can replace it rather
31
+ # than stack a second one.
32
+ _HANDLER_FLAG = "_paperpush_cli_handler"
33
+
34
+
35
+ def _level_from_env() -> int | None:
36
+ """Return the level named by ``PAPERPUSH_LOG_LEVEL``, or None if unset/bad."""
37
+ name = os.environ.get("PAPERPUSH_LOG_LEVEL")
38
+ if not name:
39
+ return None
40
+ resolved = logging.getLevelName(name.strip().upper())
41
+ # getLevelName returns the int for a known name, or a "Level X" string for
42
+ # an unknown one; only accept a real level.
43
+ return resolved if isinstance(resolved, int) else None
44
+
45
+
46
+ def resolve_level(verbosity: int = 0, quiet: bool = False) -> int:
47
+ """Pick a logging level from the CLI flags and the environment.
48
+
49
+ ``PAPERPUSH_LOG_LEVEL`` (e.g. ``DEBUG``) wins when set to a valid level;
50
+ otherwise ``quiet`` forces ``ERROR`` and each ``-v`` raises the verbosity one
51
+ step from the ``WARNING`` default.
52
+ """
53
+ env_level = _level_from_env()
54
+ if env_level is not None:
55
+ return env_level
56
+ if quiet:
57
+ return logging.ERROR
58
+ index = min(max(verbosity, 0), len(_VERBOSITY_LEVELS) - 1)
59
+ return _VERBOSITY_LEVELS[index]
60
+
61
+
62
+ def configure_logging(verbosity: int = 0, quiet: bool = False) -> logging.Logger:
63
+ """Attach a single stderr handler to the package logger and set its level.
64
+
65
+ Safe to call more than once: a handler installed by an earlier call is
66
+ replaced rather than stacked, so repeated CLI invocations within one process
67
+ (notably the test suite) do not emit duplicate lines.
68
+ """
69
+ level = resolve_level(verbosity, quiet)
70
+ logger = logging.getLogger(PACKAGE_LOGGER)
71
+
72
+ for handler in list(logger.handlers):
73
+ if getattr(handler, _HANDLER_FLAG, False):
74
+ logger.removeHandler(handler)
75
+
76
+ handler = logging.StreamHandler(sys.stderr)
77
+ handler.setFormatter(logging.Formatter(_LOG_FORMAT, _DATE_FORMAT))
78
+ setattr(handler, _HANDLER_FLAG, True)
79
+ logger.addHandler(handler)
80
+ logger.setLevel(level)
81
+ # Diagnostics flow only through our handler, not whatever the root logger has.
82
+ logger.propagate = False
83
+ logger.debug("Logging configured at level %s", logging.getLevelName(level))
84
+ return logger