├── .bumpversion.cfg ├── .cookiecutterrc ├── .coveragerc ├── .editorconfig ├── .github └── workflows │ └── github-actions.yml ├── .gitignore ├── .pre-commit-config.yaml ├── .readthedocs.yml ├── AUTHORS.rst ├── CHANGELOG.rst ├── CONTRIBUTING.rst ├── LICENSE ├── README.rst ├── ci ├── bootstrap.py ├── requirements.txt └── templates │ └── .github │ └── workflows │ └── github-actions.yml ├── docs ├── authors.rst ├── changelog.rst ├── conf.py ├── contributing.rst ├── index.rst ├── installation.rst ├── readme.rst ├── reference │ ├── index.rst │ └── nameless.rst ├── requirements.txt ├── spelling_wordlist.txt └── usage.rst ├── pyproject.toml ├── pytest.ini ├── setup.py ├── src └── nameless │ ├── __init__.py │ ├── __main__.py │ ├── _core.c │ ├── _core.pyx │ ├── cli.py │ ├── core.py │ └── tests │ ├── __init__.py │ ├── test_cli.py │ └── test_core.py └── tox.ini /.bumpversion.cfg: -------------------------------------------------------------------------------- 1 | [bumpversion] 2 | current_version = 1.0.0 3 | commit = True 4 | tag = True 5 | 6 | [bumpversion:file:setup.py] 7 | search = "fallback_version": "{current_version}" 8 | replace = "fallback_version": "{new_version}" 9 | 10 | [bumpversion:file (badge):README.rst] 11 | search = /v{current_version}.svg 12 | replace = /v{new_version}.svg 13 | 14 | [bumpversion:file (link):README.rst] 15 | search = /v{current_version}...main 16 | replace = /v{new_version}...main 17 | 18 | [bumpversion:file:docs/conf.py] 19 | search = version = release = "{current_version}" 20 | replace = version = release = "{new_version}" 21 | 22 | [bumpversion:file:src/nameless/__init__.py] 23 | search = __version__ = "{current_version}" 24 | replace = __version__ = "{new_version}" 25 | 26 | [bumpversion:file:.cookiecutterrc] 27 | search = version: {current_version} 28 | replace = version: {new_version} 29 | -------------------------------------------------------------------------------- /.cookiecutterrc: -------------------------------------------------------------------------------- 1 | # Generated by cookiepatcher, a small shim around cookiecutter (pip install cookiepatcher) 2 | 3 | default_context: 4 | c_extension_optional: 'yes' 5 | c_extension_support: cython 6 | codacy: 'no' 7 | codacy_projectid: '-' 8 | codeclimate: 'yes' 9 | codecov: 'yes' 10 | command_line_interface: argparse 11 | command_line_interface_bin_name: nameless 12 | coveralls: 'yes' 13 | distribution_name: nameless 14 | email: contact@ionelmc.ro 15 | formatter_quote_style: double 16 | full_name: Ionel Cristian Mărieș 17 | function_name: compute 18 | github_actions: 'yes' 19 | github_actions_osx: 'yes' 20 | github_actions_windows: 'yes' 21 | license: BSD 2-Clause License 22 | module_name: core 23 | package_name: nameless 24 | pre_commit: 'yes' 25 | project_name: Nameless 26 | project_short_description: An example package. Generated with cookiecutter-pylibrary. 27 | pypi_badge: 'yes' 28 | pypi_disable_upload: 'no' 29 | release_date: today 30 | repo_hosting: github.com 31 | repo_hosting_domain: github.com 32 | repo_main_branch: main 33 | repo_name: python-nameless 34 | repo_username: ionelmc 35 | scrutinizer: 'yes' 36 | setup_py_uses_setuptools_scm: 'yes' 37 | sphinx_docs: 'yes' 38 | sphinx_docs_hosting: https://python-nameless.readthedocs.io/ 39 | sphinx_doctest: 'yes' 40 | sphinx_theme: sphinx-rtd-theme 41 | test_matrix_separate_coverage: 'yes' 42 | tests_inside_package: 'yes' 43 | version: 1.0.0 44 | version_manager: bump2version 45 | website: https://blog.ionelmc.ro 46 | year_from: '2019' 47 | year_to: now 48 | -------------------------------------------------------------------------------- /.coveragerc: -------------------------------------------------------------------------------- 1 | [paths] 2 | source = src 3 | 4 | [run] 5 | branch = true 6 | source = 7 | src 8 | tests 9 | parallel = true 10 | 11 | [report] 12 | show_missing = true 13 | precision = 2 14 | omit = *migrations* 15 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # see https://editorconfig.org/ 2 | root = true 3 | 4 | [*] 5 | # Use Unix-style newlines for most files (except Windows files, see below). 6 | end_of_line = lf 7 | trim_trailing_whitespace = true 8 | indent_style = space 9 | insert_final_newline = true 10 | indent_size = 4 11 | charset = utf-8 12 | 13 | [*.{bat,cmd,ps1}] 14 | end_of_line = crlf 15 | 16 | [*.{yml,yaml}] 17 | indent_size = 2 18 | 19 | [*.tsv] 20 | indent_style = tab 21 | -------------------------------------------------------------------------------- /.github/workflows/github-actions.yml: -------------------------------------------------------------------------------- 1 | name: build 2 | on: [push, pull_request] 3 | jobs: 4 | test: 5 | name: ${{ matrix.name }} 6 | runs-on: ${{ matrix.os }} 7 | timeout-minutes: 30 8 | strategy: 9 | fail-fast: false 10 | matrix: 11 | include: 12 | - name: 'check' 13 | python: '3.11' 14 | toxpython: 'python3.11' 15 | tox_env: 'check' 16 | os: 'ubuntu-latest' 17 | - name: 'docs' 18 | python: '3.11' 19 | toxpython: 'python3.11' 20 | tox_env: 'docs' 21 | os: 'ubuntu-latest' 22 | - name: 'py38-cover (ubuntu/x86_64)' 23 | python: '3.8' 24 | toxpython: 'python3.8' 25 | python_arch: 'x64' 26 | tox_env: 'py38-cover' 27 | cover: true 28 | cibw_arch: 'x86_64' 29 | cibw_build: false 30 | os: 'ubuntu-latest' 31 | - name: 'py38-cover (windows/AMD64)' 32 | python: '3.8' 33 | toxpython: 'python3.8' 34 | python_arch: 'x64' 35 | tox_env: 'py38-cover' 36 | cover: true 37 | cibw_arch: 'AMD64' 38 | cibw_build: false 39 | os: 'windows-latest' 40 | - name: 'py38-cover (macos/x86_64)' 41 | python: '3.8' 42 | toxpython: 'python3.8' 43 | python_arch: 'x64' 44 | tox_env: 'py38-cover' 45 | cover: true 46 | cibw_arch: 'x86_64' 47 | cibw_build: false 48 | os: 'macos-latest' 49 | - name: 'py38-nocov (ubuntu/x86_64/manylinux)' 50 | python: '3.8' 51 | toxpython: 'python3.8' 52 | python_arch: 'x64' 53 | tox_env: 'py38-nocov' 54 | cibw_arch: 'x86_64' 55 | cibw_build: 'cp38-*manylinux*' 56 | os: 'ubuntu-latest' 57 | - name: 'py38-nocov (ubuntu/x86_64/musllinux)' 58 | python: '3.8' 59 | toxpython: 'python3.8' 60 | python_arch: 'x64' 61 | tox_env: 'py38-nocov' 62 | cibw_arch: 'x86_64' 63 | cibw_build: 'cp38-*musllinux*' 64 | os: 'ubuntu-latest' 65 | - name: 'py38-nocov (ubuntu/aarch64/manylinux)' 66 | python: '3.8' 67 | toxpython: 'python3.8' 68 | python_arch: 'x64' 69 | tox_env: 'py38-nocov' 70 | cibw_arch: 'aarch64' 71 | cibw_build: 'cp38-*manylinux*' 72 | os: 'ubuntu-latest' 73 | - name: 'py38-nocov (ubuntu/aarch64/musllinux)' 74 | python: '3.8' 75 | toxpython: 'python3.8' 76 | python_arch: 'x64' 77 | tox_env: 'py38-nocov' 78 | cibw_arch: 'aarch64' 79 | cibw_build: 'cp38-*musllinux*' 80 | os: 'ubuntu-latest' 81 | - name: 'py38-nocov (windows/AMD64)' 82 | python: '3.8' 83 | toxpython: 'python3.8' 84 | python_arch: 'x64' 85 | tox_env: 'py38-nocov' 86 | cibw_arch: 'AMD64' 87 | cibw_build: 'cp38-*' 88 | os: 'windows-latest' 89 | - name: 'py38-nocov (windows/x86)' 90 | python: '3.8' 91 | toxpython: 'python3.8' 92 | python_arch: 'x86' 93 | tox_env: 'py38-nocov' 94 | cibw_arch: 'x86' 95 | cibw_build: 'cp38-*' 96 | os: 'windows-latest' 97 | - name: 'py38-nocov (macos/x86_64)' 98 | python: '3.8' 99 | toxpython: 'python3.8' 100 | python_arch: 'x64' 101 | tox_env: 'py38-nocov' 102 | cibw_arch: 'x86_64' 103 | cibw_build: 'cp38-*' 104 | os: 'macos-latest' 105 | - name: 'py39-cover (ubuntu/x86_64)' 106 | python: '3.9' 107 | toxpython: 'python3.9' 108 | python_arch: 'x64' 109 | tox_env: 'py39-cover' 110 | cover: true 111 | cibw_arch: 'x86_64' 112 | cibw_build: false 113 | os: 'ubuntu-latest' 114 | - name: 'py39-cover (windows/AMD64)' 115 | python: '3.9' 116 | toxpython: 'python3.9' 117 | python_arch: 'x64' 118 | tox_env: 'py39-cover' 119 | cover: true 120 | cibw_arch: 'AMD64' 121 | cibw_build: false 122 | os: 'windows-latest' 123 | - name: 'py39-cover (macos/x86_64)' 124 | python: '3.9' 125 | toxpython: 'python3.9' 126 | python_arch: 'x64' 127 | tox_env: 'py39-cover' 128 | cover: true 129 | cibw_arch: 'x86_64' 130 | cibw_build: false 131 | os: 'macos-latest' 132 | - name: 'py39-nocov (ubuntu/x86_64/manylinux)' 133 | python: '3.9' 134 | toxpython: 'python3.9' 135 | python_arch: 'x64' 136 | tox_env: 'py39-nocov' 137 | cibw_arch: 'x86_64' 138 | cibw_build: 'cp39-*manylinux*' 139 | os: 'ubuntu-latest' 140 | - name: 'py39-nocov (ubuntu/x86_64/musllinux)' 141 | python: '3.9' 142 | toxpython: 'python3.9' 143 | python_arch: 'x64' 144 | tox_env: 'py39-nocov' 145 | cibw_arch: 'x86_64' 146 | cibw_build: 'cp39-*musllinux*' 147 | os: 'ubuntu-latest' 148 | - name: 'py39-nocov (ubuntu/aarch64/manylinux)' 149 | python: '3.9' 150 | toxpython: 'python3.9' 151 | python_arch: 'x64' 152 | tox_env: 'py39-nocov' 153 | cibw_arch: 'aarch64' 154 | cibw_build: 'cp39-*manylinux*' 155 | os: 'ubuntu-latest' 156 | - name: 'py39-nocov (ubuntu/aarch64/musllinux)' 157 | python: '3.9' 158 | toxpython: 'python3.9' 159 | python_arch: 'x64' 160 | tox_env: 'py39-nocov' 161 | cibw_arch: 'aarch64' 162 | cibw_build: 'cp39-*musllinux*' 163 | os: 'ubuntu-latest' 164 | - name: 'py39-nocov (windows/AMD64)' 165 | python: '3.9' 166 | toxpython: 'python3.9' 167 | python_arch: 'x64' 168 | tox_env: 'py39-nocov' 169 | cibw_arch: 'AMD64' 170 | cibw_build: 'cp39-*' 171 | os: 'windows-latest' 172 | - name: 'py39-nocov (windows/x86)' 173 | python: '3.9' 174 | toxpython: 'python3.9' 175 | python_arch: 'x86' 176 | tox_env: 'py39-nocov' 177 | cibw_arch: 'x86' 178 | cibw_build: 'cp39-*' 179 | os: 'windows-latest' 180 | - name: 'py39-nocov (macos/x86_64)' 181 | python: '3.9' 182 | toxpython: 'python3.9' 183 | python_arch: 'x64' 184 | tox_env: 'py39-nocov' 185 | cibw_arch: 'x86_64' 186 | cibw_build: 'cp39-*' 187 | os: 'macos-latest' 188 | - name: 'py310-cover (ubuntu/x86_64)' 189 | python: '3.10' 190 | toxpython: 'python3.10' 191 | python_arch: 'x64' 192 | tox_env: 'py310-cover' 193 | cover: true 194 | cibw_arch: 'x86_64' 195 | cibw_build: false 196 | os: 'ubuntu-latest' 197 | - name: 'py310-cover (windows/AMD64)' 198 | python: '3.10' 199 | toxpython: 'python3.10' 200 | python_arch: 'x64' 201 | tox_env: 'py310-cover' 202 | cover: true 203 | cibw_arch: 'AMD64' 204 | cibw_build: false 205 | os: 'windows-latest' 206 | - name: 'py310-cover (macos/x86_64)' 207 | python: '3.10' 208 | toxpython: 'python3.10' 209 | python_arch: 'x64' 210 | tox_env: 'py310-cover' 211 | cover: true 212 | cibw_arch: 'x86_64' 213 | cibw_build: false 214 | os: 'macos-latest' 215 | - name: 'py310-nocov (ubuntu/x86_64/manylinux)' 216 | python: '3.10' 217 | toxpython: 'python3.10' 218 | python_arch: 'x64' 219 | tox_env: 'py310-nocov' 220 | cibw_arch: 'x86_64' 221 | cibw_build: 'cp310-*manylinux*' 222 | os: 'ubuntu-latest' 223 | - name: 'py310-nocov (ubuntu/x86_64/musllinux)' 224 | python: '3.10' 225 | toxpython: 'python3.10' 226 | python_arch: 'x64' 227 | tox_env: 'py310-nocov' 228 | cibw_arch: 'x86_64' 229 | cibw_build: 'cp310-*musllinux*' 230 | os: 'ubuntu-latest' 231 | - name: 'py310-nocov (ubuntu/aarch64/manylinux)' 232 | python: '3.10' 233 | toxpython: 'python3.10' 234 | python_arch: 'x64' 235 | tox_env: 'py310-nocov' 236 | cibw_arch: 'aarch64' 237 | cibw_build: 'cp310-*manylinux*' 238 | os: 'ubuntu-latest' 239 | - name: 'py310-nocov (ubuntu/aarch64/musllinux)' 240 | python: '3.10' 241 | toxpython: 'python3.10' 242 | python_arch: 'x64' 243 | tox_env: 'py310-nocov' 244 | cibw_arch: 'aarch64' 245 | cibw_build: 'cp310-*musllinux*' 246 | os: 'ubuntu-latest' 247 | - name: 'py310-nocov (windows/AMD64)' 248 | python: '3.10' 249 | toxpython: 'python3.10' 250 | python_arch: 'x64' 251 | tox_env: 'py310-nocov' 252 | cibw_arch: 'AMD64' 253 | cibw_build: 'cp310-*' 254 | os: 'windows-latest' 255 | - name: 'py310-nocov (windows/x86)' 256 | python: '3.10' 257 | toxpython: 'python3.10' 258 | python_arch: 'x86' 259 | tox_env: 'py310-nocov' 260 | cibw_arch: 'x86' 261 | cibw_build: 'cp310-*' 262 | os: 'windows-latest' 263 | - name: 'py310-nocov (macos/x86_64)' 264 | python: '3.10' 265 | toxpython: 'python3.10' 266 | python_arch: 'x64' 267 | tox_env: 'py310-nocov' 268 | cibw_arch: 'x86_64' 269 | cibw_build: 'cp310-*' 270 | os: 'macos-latest' 271 | - name: 'py311-cover (ubuntu/x86_64)' 272 | python: '3.11' 273 | toxpython: 'python3.11' 274 | python_arch: 'x64' 275 | tox_env: 'py311-cover' 276 | cover: true 277 | cibw_arch: 'x86_64' 278 | cibw_build: false 279 | os: 'ubuntu-latest' 280 | - name: 'py311-cover (windows/AMD64)' 281 | python: '3.11' 282 | toxpython: 'python3.11' 283 | python_arch: 'x64' 284 | tox_env: 'py311-cover' 285 | cover: true 286 | cibw_arch: 'AMD64' 287 | cibw_build: false 288 | os: 'windows-latest' 289 | - name: 'py311-cover (macos/x86_64)' 290 | python: '3.11' 291 | toxpython: 'python3.11' 292 | python_arch: 'x64' 293 | tox_env: 'py311-cover' 294 | cover: true 295 | cibw_arch: 'x86_64' 296 | cibw_build: false 297 | os: 'macos-latest' 298 | - name: 'py311-nocov (ubuntu/x86_64/manylinux)' 299 | python: '3.11' 300 | toxpython: 'python3.11' 301 | python_arch: 'x64' 302 | tox_env: 'py311-nocov' 303 | cibw_arch: 'x86_64' 304 | cibw_build: 'cp311-*manylinux*' 305 | os: 'ubuntu-latest' 306 | - name: 'py311-nocov (ubuntu/x86_64/musllinux)' 307 | python: '3.11' 308 | toxpython: 'python3.11' 309 | python_arch: 'x64' 310 | tox_env: 'py311-nocov' 311 | cibw_arch: 'x86_64' 312 | cibw_build: 'cp311-*musllinux*' 313 | os: 'ubuntu-latest' 314 | - name: 'py311-nocov (ubuntu/aarch64/manylinux)' 315 | python: '3.11' 316 | toxpython: 'python3.11' 317 | python_arch: 'x64' 318 | tox_env: 'py311-nocov' 319 | cibw_arch: 'aarch64' 320 | cibw_build: 'cp311-*manylinux*' 321 | os: 'ubuntu-latest' 322 | - name: 'py311-nocov (ubuntu/aarch64/musllinux)' 323 | python: '3.11' 324 | toxpython: 'python3.11' 325 | python_arch: 'x64' 326 | tox_env: 'py311-nocov' 327 | cibw_arch: 'aarch64' 328 | cibw_build: 'cp311-*musllinux*' 329 | os: 'ubuntu-latest' 330 | - name: 'py311-nocov (windows/AMD64)' 331 | python: '3.11' 332 | toxpython: 'python3.11' 333 | python_arch: 'x64' 334 | tox_env: 'py311-nocov' 335 | cibw_arch: 'AMD64' 336 | cibw_build: 'cp311-*' 337 | os: 'windows-latest' 338 | - name: 'py311-nocov (windows/x86)' 339 | python: '3.11' 340 | toxpython: 'python3.11' 341 | python_arch: 'x86' 342 | tox_env: 'py311-nocov' 343 | cibw_arch: 'x86' 344 | cibw_build: 'cp311-*' 345 | os: 'windows-latest' 346 | - name: 'py311-nocov (macos/x86_64)' 347 | python: '3.11' 348 | toxpython: 'python3.11' 349 | python_arch: 'x64' 350 | tox_env: 'py311-nocov' 351 | cibw_arch: 'x86_64' 352 | cibw_build: 'cp311-*' 353 | os: 'macos-latest' 354 | - name: 'py312-cover (ubuntu/x86_64)' 355 | python: '3.12' 356 | toxpython: 'python3.12' 357 | python_arch: 'x64' 358 | tox_env: 'py312-cover' 359 | cover: true 360 | cibw_arch: 'x86_64' 361 | cibw_build: false 362 | os: 'ubuntu-latest' 363 | - name: 'py312-cover (windows/AMD64)' 364 | python: '3.12' 365 | toxpython: 'python3.12' 366 | python_arch: 'x64' 367 | tox_env: 'py312-cover' 368 | cover: true 369 | cibw_arch: 'AMD64' 370 | cibw_build: false 371 | os: 'windows-latest' 372 | - name: 'py312-cover (macos/x86_64)' 373 | python: '3.12' 374 | toxpython: 'python3.12' 375 | python_arch: 'x64' 376 | tox_env: 'py312-cover' 377 | cover: true 378 | cibw_arch: 'x86_64' 379 | cibw_build: false 380 | os: 'macos-latest' 381 | - name: 'py312-nocov (ubuntu/x86_64/manylinux)' 382 | python: '3.12' 383 | toxpython: 'python3.12' 384 | python_arch: 'x64' 385 | tox_env: 'py312-nocov' 386 | cibw_arch: 'x86_64' 387 | cibw_build: 'cp312-*manylinux*' 388 | os: 'ubuntu-latest' 389 | - name: 'py312-nocov (ubuntu/x86_64/musllinux)' 390 | python: '3.12' 391 | toxpython: 'python3.12' 392 | python_arch: 'x64' 393 | tox_env: 'py312-nocov' 394 | cibw_arch: 'x86_64' 395 | cibw_build: 'cp312-*musllinux*' 396 | os: 'ubuntu-latest' 397 | - name: 'py312-nocov (ubuntu/aarch64/manylinux)' 398 | python: '3.12' 399 | toxpython: 'python3.12' 400 | python_arch: 'x64' 401 | tox_env: 'py312-nocov' 402 | cibw_arch: 'aarch64' 403 | cibw_build: 'cp312-*manylinux*' 404 | os: 'ubuntu-latest' 405 | - name: 'py312-nocov (ubuntu/aarch64/musllinux)' 406 | python: '3.12' 407 | toxpython: 'python3.12' 408 | python_arch: 'x64' 409 | tox_env: 'py312-nocov' 410 | cibw_arch: 'aarch64' 411 | cibw_build: 'cp312-*musllinux*' 412 | os: 'ubuntu-latest' 413 | - name: 'py312-nocov (windows/AMD64)' 414 | python: '3.12' 415 | toxpython: 'python3.12' 416 | python_arch: 'x64' 417 | tox_env: 'py312-nocov' 418 | cibw_arch: 'AMD64' 419 | cibw_build: 'cp312-*' 420 | os: 'windows-latest' 421 | - name: 'py312-nocov (windows/x86)' 422 | python: '3.12' 423 | toxpython: 'python3.12' 424 | python_arch: 'x86' 425 | tox_env: 'py312-nocov' 426 | cibw_arch: 'x86' 427 | cibw_build: 'cp312-*' 428 | os: 'windows-latest' 429 | - name: 'py312-nocov (macos/x86_64)' 430 | python: '3.12' 431 | toxpython: 'python3.12' 432 | python_arch: 'x64' 433 | tox_env: 'py312-nocov' 434 | cibw_arch: 'x86_64' 435 | cibw_build: 'cp312-*' 436 | os: 'macos-latest' 437 | - name: 'pypy38-cover (ubuntu/x86_64)' 438 | python: 'pypy-3.8' 439 | toxpython: 'pypy3.8' 440 | python_arch: 'x64' 441 | tox_env: 'pypy38-cover' 442 | cover: true 443 | cibw_arch: 'x86_64' 444 | cibw_build: false 445 | os: 'ubuntu-latest' 446 | - name: 'pypy38-cover (windows/AMD64)' 447 | python: 'pypy-3.8' 448 | toxpython: 'pypy3.8' 449 | python_arch: 'x64' 450 | tox_env: 'pypy38-cover' 451 | cover: true 452 | cibw_arch: 'AMD64' 453 | cibw_build: false 454 | os: 'windows-latest' 455 | - name: 'pypy38-cover (macos/x86_64)' 456 | python: 'pypy-3.8' 457 | toxpython: 'pypy3.8' 458 | python_arch: 'x64' 459 | tox_env: 'pypy38-cover' 460 | cover: true 461 | cibw_arch: 'x86_64' 462 | cibw_build: false 463 | os: 'macos-latest' 464 | - name: 'pypy38-nocov (ubuntu/x86_64/manylinux)' 465 | python: 'pypy-3.8' 466 | toxpython: 'pypy3.8' 467 | python_arch: 'x64' 468 | tox_env: 'pypy38-nocov' 469 | cibw_arch: 'x86_64' 470 | cibw_build: false 471 | os: 'ubuntu-latest' 472 | - name: 'pypy38-nocov (windows/AMD64)' 473 | python: 'pypy-3.8' 474 | toxpython: 'pypy3.8' 475 | python_arch: 'x64' 476 | tox_env: 'pypy38-nocov' 477 | cibw_arch: 'AMD64' 478 | cibw_build: false 479 | os: 'windows-latest' 480 | - name: 'pypy38-nocov (macos/x86_64)' 481 | python: 'pypy-3.8' 482 | toxpython: 'pypy3.8' 483 | python_arch: 'x64' 484 | tox_env: 'pypy38-nocov' 485 | cibw_arch: 'x86_64' 486 | cibw_build: false 487 | os: 'macos-latest' 488 | - name: 'pypy39-cover (ubuntu/x86_64)' 489 | python: 'pypy-3.9' 490 | toxpython: 'pypy3.9' 491 | python_arch: 'x64' 492 | tox_env: 'pypy39-cover' 493 | cover: true 494 | cibw_arch: 'x86_64' 495 | cibw_build: false 496 | os: 'ubuntu-latest' 497 | - name: 'pypy39-cover (windows/AMD64)' 498 | python: 'pypy-3.9' 499 | toxpython: 'pypy3.9' 500 | python_arch: 'x64' 501 | tox_env: 'pypy39-cover' 502 | cover: true 503 | cibw_arch: 'AMD64' 504 | cibw_build: false 505 | os: 'windows-latest' 506 | - name: 'pypy39-cover (macos/x86_64)' 507 | python: 'pypy-3.9' 508 | toxpython: 'pypy3.9' 509 | python_arch: 'x64' 510 | tox_env: 'pypy39-cover' 511 | cover: true 512 | cibw_arch: 'x86_64' 513 | cibw_build: false 514 | os: 'macos-latest' 515 | - name: 'pypy39-nocov (ubuntu/x86_64/manylinux)' 516 | python: 'pypy-3.9' 517 | toxpython: 'pypy3.9' 518 | python_arch: 'x64' 519 | tox_env: 'pypy39-nocov' 520 | cibw_arch: 'x86_64' 521 | cibw_build: false 522 | os: 'ubuntu-latest' 523 | - name: 'pypy39-nocov (windows/AMD64)' 524 | python: 'pypy-3.9' 525 | toxpython: 'pypy3.9' 526 | python_arch: 'x64' 527 | tox_env: 'pypy39-nocov' 528 | cibw_arch: 'AMD64' 529 | cibw_build: false 530 | os: 'windows-latest' 531 | - name: 'pypy39-nocov (macos/x86_64)' 532 | python: 'pypy-3.9' 533 | toxpython: 'pypy3.9' 534 | python_arch: 'x64' 535 | tox_env: 'pypy39-nocov' 536 | cibw_arch: 'x86_64' 537 | cibw_build: false 538 | os: 'macos-latest' 539 | - name: 'pypy310-cover (ubuntu/x86_64)' 540 | python: 'pypy-3.10' 541 | toxpython: 'pypy3.10' 542 | python_arch: 'x64' 543 | tox_env: 'pypy310-cover' 544 | cover: true 545 | cibw_arch: 'x86_64' 546 | cibw_build: false 547 | os: 'ubuntu-latest' 548 | - name: 'pypy310-cover (windows/AMD64)' 549 | python: 'pypy-3.10' 550 | toxpython: 'pypy3.10' 551 | python_arch: 'x64' 552 | tox_env: 'pypy310-cover' 553 | cover: true 554 | cibw_arch: 'AMD64' 555 | cibw_build: false 556 | os: 'windows-latest' 557 | - name: 'pypy310-cover (macos/x86_64)' 558 | python: 'pypy-3.10' 559 | toxpython: 'pypy3.10' 560 | python_arch: 'x64' 561 | tox_env: 'pypy310-cover' 562 | cover: true 563 | cibw_arch: 'x86_64' 564 | cibw_build: false 565 | os: 'macos-latest' 566 | - name: 'pypy310-nocov (ubuntu/x86_64/manylinux)' 567 | python: 'pypy-3.10' 568 | toxpython: 'pypy3.10' 569 | python_arch: 'x64' 570 | tox_env: 'pypy310-nocov' 571 | cibw_arch: 'x86_64' 572 | cibw_build: false 573 | os: 'ubuntu-latest' 574 | - name: 'pypy310-nocov (windows/AMD64)' 575 | python: 'pypy-3.10' 576 | toxpython: 'pypy3.10' 577 | python_arch: 'x64' 578 | tox_env: 'pypy310-nocov' 579 | cibw_arch: 'AMD64' 580 | cibw_build: false 581 | os: 'windows-latest' 582 | - name: 'pypy310-nocov (macos/x86_64)' 583 | python: 'pypy-3.10' 584 | toxpython: 'pypy3.10' 585 | python_arch: 'x64' 586 | tox_env: 'pypy310-nocov' 587 | cibw_arch: 'x86_64' 588 | cibw_build: false 589 | os: 'macos-latest' 590 | steps: 591 | - uses: docker/setup-qemu-action@v3 592 | if: matrix.cibw_arch == 'aarch64' 593 | with: 594 | platforms: arm64 595 | - uses: actions/checkout@v4 596 | with: 597 | fetch-depth: 0 598 | - uses: actions/setup-python@v5 599 | with: 600 | python-version: ${{ matrix.python }} 601 | architecture: ${{ matrix.python_arch }} 602 | - name: install dependencies 603 | run: | 604 | python -mpip install --progress-bar=off cibuildwheel -r ci/requirements.txt 605 | virtualenv --version 606 | pip --version 607 | tox --version 608 | pip list --format=freeze 609 | - name: cibw build and test 610 | if: matrix.cibw_build 611 | run: cibuildwheel 612 | env: 613 | TOXPYTHON: '${{ matrix.toxpython }}' 614 | CIBW_ARCHS: '${{ matrix.cibw_arch }}' 615 | CIBW_BUILD: '${{ matrix.cibw_build }}' 616 | CIBW_BUILD_VERBOSITY: '3' 617 | CIBW_TEST_REQUIRES: > 618 | tox 619 | tox-direct 620 | CIBW_TEST_COMMAND: > 621 | cd {project} && 622 | tox --skip-pkg-install --direct-yolo -e ${{ matrix.tox_env }} -v 623 | CIBW_TEST_COMMAND_WINDOWS: > 624 | cd /d {project} && 625 | tox --skip-pkg-install --direct-yolo -e ${{ matrix.tox_env }} -v 626 | - name: regular build and test 627 | env: 628 | TOXPYTHON: '${{ matrix.toxpython }}' 629 | if: > 630 | !matrix.cibw_build 631 | run: > 632 | tox -e ${{ matrix.tox_env }} -v 633 | - uses: coverallsapp/github-action@v2 634 | if: matrix.cover 635 | continue-on-error: true 636 | with: 637 | parallel: true 638 | flag-name: ${{ matrix.tox_env }} 639 | - uses: codecov/codecov-action@v3 640 | if: matrix.cover 641 | with: 642 | verbose: true 643 | flags: ${{ matrix.tox_env }} 644 | - name: check wheel 645 | if: matrix.cibw_build 646 | run: twine check wheelhouse/*.whl 647 | - name: upload wheel 648 | uses: actions/upload-artifact@v3 649 | if: matrix.cibw_build 650 | with: 651 | path: wheelhouse/*.whl 652 | finish: 653 | needs: test 654 | if: ${{ always() }} 655 | runs-on: ubuntu-latest 656 | steps: 657 | - uses: coverallsapp/github-action@v2 658 | with: 659 | parallel-finished: true 660 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.py[cod] 2 | __pycache__ 3 | 4 | # Temp files 5 | .*.sw[po] 6 | *~ 7 | *.bak 8 | .DS_Store 9 | 10 | # C extensions 11 | *.so 12 | 13 | # Build and package files 14 | *.egg 15 | *.egg-info 16 | .bootstrap 17 | .build 18 | .cache 19 | .eggs 20 | .env 21 | .installed.cfg 22 | .ve 23 | bin 24 | build 25 | develop-eggs 26 | dist 27 | eggs 28 | lib 29 | lib64 30 | parts 31 | pip-wheel-metadata/ 32 | pyvenv*/ 33 | sdist 34 | var 35 | venv*/ 36 | wheelhouse 37 | 38 | # Installer logs 39 | pip-log.txt 40 | 41 | # Unit test / coverage reports 42 | .benchmarks 43 | .coverage 44 | .coverage.* 45 | .pytest 46 | .pytest_cache/ 47 | .tox 48 | coverage.xml 49 | htmlcov 50 | nosetests.xml 51 | 52 | # Translations 53 | *.mo 54 | 55 | # Buildout 56 | .mr.developer.cfg 57 | 58 | # IDE project files 59 | *.iml 60 | *.komodoproject 61 | .idea 62 | .project 63 | .pydevproject 64 | .vscode 65 | 66 | # Complexity 67 | output/*.html 68 | output/*/index.html 69 | 70 | # Sphinx 71 | docs/_build 72 | 73 | # Mypy Cache 74 | .mypy_cache/ 75 | 76 | # Generated by setuptools-scm 77 | src/*/_version.py 78 | -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | # To install the git pre-commit hooks run: 2 | # pre-commit install --install-hooks 3 | # To update the versions: 4 | # pre-commit autoupdate 5 | exclude: '^(\.tox|ci/templates|\.bumpversion\.cfg)(/|$)' 6 | # Note the order is intentional to avoid multiple passes of the hooks 7 | repos: 8 | - repo: https://github.com/astral-sh/ruff-pre-commit 9 | rev: v0.3.4 10 | hooks: 11 | - id: ruff 12 | args: [--fix, --exit-non-zero-on-fix, --show-fixes] 13 | - repo: https://github.com/psf/black 14 | rev: 24.3.0 15 | hooks: 16 | - id: black 17 | - repo: https://github.com/pre-commit/pre-commit-hooks 18 | rev: v4.5.0 19 | hooks: 20 | - id: trailing-whitespace 21 | exclude_types: 22 | - c 23 | - id: end-of-file-fixer 24 | exclude_types: 25 | - c 26 | - id: debug-statements 27 | -------------------------------------------------------------------------------- /.readthedocs.yml: -------------------------------------------------------------------------------- 1 | # See https://docs.readthedocs.io/en/stable/config-file/v2.html for details 2 | version: 2 3 | sphinx: 4 | configuration: docs/conf.py 5 | formats: all 6 | build: 7 | os: ubuntu-22.04 8 | tools: 9 | python: "3" 10 | python: 11 | install: 12 | - requirements: docs/requirements.txt 13 | - method: pip 14 | path: . 15 | -------------------------------------------------------------------------------- /AUTHORS.rst: -------------------------------------------------------------------------------- 1 | 2 | Authors 3 | ======= 4 | 5 | * Ionel Cristian Mărieș - https://blog.ionelmc.ro 6 | -------------------------------------------------------------------------------- /CHANGELOG.rst: -------------------------------------------------------------------------------- 1 | 2 | Changelog 3 | ========= 4 | 5 | 1.0.0 (2024-03-23) 6 | ------------------ 7 | 8 | * First release on PyPI. 9 | -------------------------------------------------------------------------------- /CONTRIBUTING.rst: -------------------------------------------------------------------------------- 1 | ============ 2 | Contributing 3 | ============ 4 | 5 | Contributions are welcome, and they are greatly appreciated! Every 6 | little bit helps, and credit will always be given. 7 | 8 | Bug reports 9 | =========== 10 | 11 | When `reporting a bug `_ please include: 12 | 13 | * Your operating system name and version. 14 | * Any details about your local setup that might be helpful in troubleshooting. 15 | * Detailed steps to reproduce the bug. 16 | 17 | Documentation improvements 18 | ========================== 19 | 20 | Nameless could always use more documentation, whether as part of the 21 | official Nameless docs, in docstrings, or even on the web in blog posts, 22 | articles, and such. 23 | 24 | Feature requests and feedback 25 | ============================= 26 | 27 | The best way to send feedback is to file an issue at https://github.com/ionelmc/python-nameless/issues. 28 | 29 | If you are proposing a feature: 30 | 31 | * Explain in detail how it would work. 32 | * Keep the scope as narrow as possible, to make it easier to implement. 33 | * Remember that this is a volunteer-driven project, and that code contributions are welcome :) 34 | 35 | Development 36 | =========== 37 | 38 | To set up `python-nameless` for local development: 39 | 40 | 1. Fork `python-nameless `_ 41 | (look for the "Fork" button). 42 | 2. Clone your fork locally:: 43 | 44 | git clone git@github.com:YOURGITHUBNAME/python-nameless.git 45 | 46 | 3. Create a branch for local development:: 47 | 48 | git checkout -b name-of-your-bugfix-or-feature 49 | 50 | Now you can make your changes locally. 51 | 52 | 4. When you're done making changes run all the checks and docs builder with one command:: 53 | 54 | tox 55 | 56 | 5. Commit your changes and push your branch to GitHub:: 57 | 58 | git add . 59 | git commit -m "Your detailed description of your changes." 60 | git push origin name-of-your-bugfix-or-feature 61 | 62 | 6. Submit a pull request through the GitHub website. 63 | 64 | Pull Request Guidelines 65 | ----------------------- 66 | 67 | If you need some code review or feedback while you're developing the code just make the pull request. 68 | 69 | For merging, you should: 70 | 71 | 1. Include passing tests (run ``tox``). 72 | 2. Update documentation when there's new API, functionality etc. 73 | 3. Add a note to ``CHANGELOG.rst`` about the changes. 74 | 4. Add yourself to ``AUTHORS.rst``. 75 | 76 | Tips 77 | ---- 78 | 79 | To run a subset of tests:: 80 | 81 | tox -e envname -- pytest -k test_myfeature 82 | 83 | To run all the test environments in *parallel*:: 84 | 85 | tox -p auto 86 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 2-Clause License 2 | 3 | Copyright (c) 2019-now, Ionel Cristian Mărieș. All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 8 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 9 | 10 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 11 | -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | ======== 2 | Overview 3 | ======== 4 | 5 | .. start-badges 6 | 7 | .. list-table:: 8 | :stub-columns: 1 9 | 10 | * - docs 11 | - |docs| 12 | * - tests 13 | - |github-actions| |coveralls| |codecov| |scrutinizer| |codeclimate| 14 | * - package 15 | - |version| |wheel| |supported-versions| |supported-implementations| |commits-since| 16 | .. |docs| image:: https://readthedocs.org/projects/python-nameless/badge/?style=flat 17 | :target: https://readthedocs.org/projects/python-nameless/ 18 | :alt: Documentation Status 19 | 20 | .. |github-actions| image:: https://github.com/ionelmc/python-nameless/actions/workflows/github-actions.yml/badge.svg 21 | :alt: GitHub Actions Build Status 22 | :target: https://github.com/ionelmc/python-nameless/actions 23 | 24 | .. |coveralls| image:: https://coveralls.io/repos/github/ionelmc/python-nameless/badge.svg?branch=main 25 | :alt: Coverage Status 26 | :target: https://coveralls.io/github/ionelmc/python-nameless?branch=main 27 | 28 | .. |codecov| image:: https://codecov.io/gh/ionelmc/python-nameless/branch/main/graphs/badge.svg?branch=main 29 | :alt: Coverage Status 30 | :target: https://app.codecov.io/github/ionelmc/python-nameless 31 | 32 | .. |codeclimate| image:: https://codeclimate.com/github/ionelmc/python-nameless/badges/gpa.svg 33 | :target: https://codeclimate.com/github/ionelmc/python-nameless 34 | :alt: CodeClimate Quality Status 35 | 36 | .. |version| image:: https://img.shields.io/pypi/v/nameless.svg 37 | :alt: PyPI Package latest release 38 | :target: https://pypi.org/project/nameless 39 | 40 | .. |wheel| image:: https://img.shields.io/pypi/wheel/nameless.svg 41 | :alt: PyPI Wheel 42 | :target: https://pypi.org/project/nameless 43 | 44 | .. |supported-versions| image:: https://img.shields.io/pypi/pyversions/nameless.svg 45 | :alt: Supported versions 46 | :target: https://pypi.org/project/nameless 47 | 48 | .. |supported-implementations| image:: https://img.shields.io/pypi/implementation/nameless.svg 49 | :alt: Supported implementations 50 | :target: https://pypi.org/project/nameless 51 | 52 | .. |commits-since| image:: https://img.shields.io/github/commits-since/ionelmc/python-nameless/v1.0.0.svg 53 | :alt: Commits since latest release 54 | :target: https://github.com/ionelmc/python-nameless/compare/v1.0.0...main 55 | 56 | 57 | .. |scrutinizer| image:: https://img.shields.io/scrutinizer/quality/g/ionelmc/python-nameless/main.svg 58 | :alt: Scrutinizer Status 59 | :target: https://scrutinizer-ci.com/g/ionelmc/python-nameless/ 60 | 61 | 62 | .. end-badges 63 | 64 | An example package. Generated with cookiecutter-pylibrary. 65 | 66 | * Free software: BSD 2-Clause License 67 | 68 | Installation 69 | ============ 70 | 71 | :: 72 | 73 | pip install nameless 74 | 75 | You can also install the in-development version with:: 76 | 77 | pip install https://github.com/ionelmc/python-nameless/archive/main.zip 78 | 79 | 80 | Documentation 81 | ============= 82 | 83 | 84 | https://python-nameless.readthedocs.io/ 85 | 86 | 87 | Development 88 | =========== 89 | 90 | To run all the tests run:: 91 | 92 | tox 93 | 94 | Note, to combine the coverage data from all the tox environments run: 95 | 96 | .. list-table:: 97 | :widths: 10 90 98 | :stub-columns: 1 99 | 100 | - - Windows 101 | - :: 102 | 103 | set PYTEST_ADDOPTS=--cov-append 104 | tox 105 | 106 | - - Other 107 | - :: 108 | 109 | PYTEST_ADDOPTS=--cov-append tox 110 | -------------------------------------------------------------------------------- /ci/bootstrap.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import os 3 | import pathlib 4 | import subprocess 5 | import sys 6 | 7 | base_path: pathlib.Path = pathlib.Path(__file__).resolve().parent.parent 8 | templates_path = base_path / "ci" / "templates" 9 | 10 | 11 | def check_call(args): 12 | print("+", *args) 13 | subprocess.check_call(args) 14 | 15 | 16 | def exec_in_env(): 17 | env_path = base_path / ".tox" / "bootstrap" 18 | if sys.platform == "win32": 19 | bin_path = env_path / "Scripts" 20 | else: 21 | bin_path = env_path / "bin" 22 | if not env_path.exists(): 23 | import subprocess 24 | 25 | print(f"Making bootstrap env in: {env_path} ...") 26 | try: 27 | check_call([sys.executable, "-m", "venv", env_path]) 28 | except subprocess.CalledProcessError: 29 | try: 30 | check_call([sys.executable, "-m", "virtualenv", env_path]) 31 | except subprocess.CalledProcessError: 32 | check_call(["virtualenv", env_path]) 33 | print("Installing `jinja2` into bootstrap environment...") 34 | check_call([bin_path / "pip", "install", "jinja2", "tox"]) 35 | python_executable = bin_path / "python" 36 | if not python_executable.exists(): 37 | python_executable = python_executable.with_suffix(".exe") 38 | 39 | print(f"Re-executing with: {python_executable}") 40 | print("+ exec", python_executable, __file__, "--no-env") 41 | os.execv(python_executable, [python_executable, __file__, "--no-env"]) 42 | 43 | 44 | def main(): 45 | import jinja2 46 | 47 | print(f"Project path: {base_path}") 48 | 49 | jinja = jinja2.Environment( 50 | loader=jinja2.FileSystemLoader(str(templates_path)), 51 | trim_blocks=True, 52 | lstrip_blocks=True, 53 | keep_trailing_newline=True, 54 | ) 55 | tox_environments = [ 56 | line.strip() 57 | # 'tox' need not be installed globally, but must be importable 58 | # by the Python that is running this script. 59 | # This uses sys.executable the same way that the call in 60 | # cookiecutter-pylibrary/hooks/post_gen_project.py 61 | # invokes this bootstrap.py itself. 62 | for line in subprocess.check_output([sys.executable, "-m", "tox", "--listenvs"], universal_newlines=True).splitlines() 63 | ] 64 | tox_environments = [line for line in tox_environments if line.startswith("py")] 65 | for template in templates_path.rglob("*"): 66 | if template.is_file(): 67 | template_path = template.relative_to(templates_path).as_posix() 68 | destination = base_path / template_path 69 | destination.parent.mkdir(parents=True, exist_ok=True) 70 | destination.write_text(jinja.get_template(template_path).render(tox_environments=tox_environments)) 71 | print(f"Wrote {template_path}") 72 | print("DONE.") 73 | 74 | 75 | if __name__ == "__main__": 76 | args = sys.argv[1:] 77 | if args == ["--no-env"]: 78 | main() 79 | elif not args: 80 | exec_in_env() 81 | else: 82 | print(f"Unexpected arguments: {args}", file=sys.stderr) 83 | sys.exit(1) 84 | -------------------------------------------------------------------------------- /ci/requirements.txt: -------------------------------------------------------------------------------- 1 | virtualenv>=16.6.0 2 | pip>=19.1.1 3 | setuptools>=18.0.1 4 | six>=1.14.0 5 | tox 6 | twine 7 | -------------------------------------------------------------------------------- /ci/templates/.github/workflows/github-actions.yml: -------------------------------------------------------------------------------- 1 | name: build 2 | on: [push, pull_request] 3 | jobs: 4 | test: 5 | name: {{ '${{ matrix.name }}' }} 6 | runs-on: {{ '${{ matrix.os }}' }} 7 | timeout-minutes: 30 8 | strategy: 9 | fail-fast: false 10 | matrix: 11 | include: 12 | - name: 'check' 13 | python: '3.11' 14 | toxpython: 'python3.11' 15 | tox_env: 'check' 16 | os: 'ubuntu-latest' 17 | - name: 'docs' 18 | python: '3.11' 19 | toxpython: 'python3.11' 20 | tox_env: 'docs' 21 | os: 'ubuntu-latest' 22 | {% for env in tox_environments %} 23 | {% set prefix = env.split('-')[0] -%} 24 | {% if prefix.startswith('pypy') %} 25 | {% set python %}pypy-{{ prefix[4] }}.{{ prefix[5:] }}{% endset %} 26 | {% set cpython %}pp{{ prefix[4:5] }}{% endset %} 27 | {% set toxpython %}pypy{{ prefix[4] }}.{{ prefix[5:] }}{% endset %} 28 | {% else %} 29 | {% set python %}{{ prefix[2] }}.{{ prefix[3:] }}{% endset %} 30 | {% set cpython %}cp{{ prefix[2:] }}{% endset %} 31 | {% set toxpython %}python{{ prefix[2] }}.{{ prefix[3:] }}{% endset %} 32 | {% endif %} 33 | {% for os, python_arch, cibw_arch, wheel_arch, include_cover in [ 34 | ['ubuntu', 'x64', 'x86_64', '*manylinux*', True], 35 | ['ubuntu', 'x64', 'x86_64', '*musllinux*', False], 36 | ['ubuntu', 'x64', 'aarch64', '*manylinux*', False], 37 | ['ubuntu', 'x64', 'aarch64', '*musllinux*', False], 38 | ['windows', 'x64', 'AMD64', '*', True], 39 | ['windows', 'x86', 'x86', '*', False], 40 | ['macos', 'x64', 'x86_64', '*', True], 41 | ] %} 42 | {% if include_cover or ('nocov' in env and not prefix.startswith('pypy')) %} 43 | {% set wheel_suffix = 'nocov' in env and wheel_arch.strip('*') %} 44 | {% set name_suffix = '/' + wheel_suffix if wheel_suffix else '' %} 45 | - name: '{{ env }} ({{ os }}/{{ cibw_arch }}{{ name_suffix }})' 46 | python: '{{ python }}' 47 | toxpython: '{{ toxpython }}' 48 | python_arch: '{{ python_arch }}' 49 | tox_env: '{{ env }}' 50 | {% if 'cover' in env %} 51 | cover: true 52 | {% endif %} 53 | cibw_arch: '{{ cibw_arch }}' 54 | {% if 'nocov' in env and not prefix.startswith('pypy') %} 55 | cibw_build: '{{ cpython }}-{{ wheel_arch }}' 56 | {% else %} 57 | cibw_build: false 58 | {% endif %} 59 | os: '{{ os }}-latest' 60 | {% endif %} 61 | {% endfor %} 62 | {% endfor %} 63 | steps: 64 | - uses: docker/setup-qemu-action@v3 65 | if: matrix.cibw_arch == 'aarch64' 66 | with: 67 | platforms: arm64 68 | - uses: actions/checkout@v4 69 | with: 70 | fetch-depth: 0 71 | - uses: actions/setup-python@v5 72 | with: 73 | python-version: {{ '${{ matrix.python }}' }} 74 | architecture: {{ '${{ matrix.python_arch }}' }} 75 | - name: install dependencies 76 | run: | 77 | python -mpip install --progress-bar=off cibuildwheel -r ci/requirements.txt 78 | virtualenv --version 79 | pip --version 80 | tox --version 81 | pip list --format=freeze 82 | - name: cibw build and test 83 | if: matrix.cibw_build 84 | run: cibuildwheel 85 | env: 86 | TOXPYTHON: '{{ '${{ matrix.toxpython }}' }}' 87 | CIBW_ARCHS: '{{ '${{ matrix.cibw_arch }}' }}' 88 | CIBW_BUILD: '{{ '${{ matrix.cibw_build }}' }}' 89 | CIBW_BUILD_VERBOSITY: '3' 90 | CIBW_TEST_REQUIRES: > 91 | tox 92 | tox-direct 93 | CIBW_TEST_COMMAND: > 94 | cd {project} && 95 | tox --skip-pkg-install --direct-yolo -e {{ '${{ matrix.tox_env }}' }} -v 96 | CIBW_TEST_COMMAND_WINDOWS: > 97 | cd /d {project} && 98 | tox --skip-pkg-install --direct-yolo -e {{ '${{ matrix.tox_env }}' }} -v 99 | - name: regular build and test 100 | env: 101 | TOXPYTHON: '{{ '${{ matrix.toxpython }}' }}' 102 | if: > 103 | !matrix.cibw_build 104 | run: > 105 | tox -e {{ '${{ matrix.tox_env }}' }} -v 106 | - uses: coverallsapp/github-action@v2 107 | if: matrix.cover 108 | continue-on-error: true 109 | with: 110 | parallel: true 111 | flag-name: {{ '${{ matrix.tox_env }}' }} 112 | - uses: codecov/codecov-action@v3 113 | if: matrix.cover 114 | with: 115 | verbose: true 116 | flags: {{ '${{ matrix.tox_env }}' }} 117 | - name: check wheel 118 | if: matrix.cibw_build 119 | run: twine check wheelhouse/*.whl 120 | - name: upload wheel 121 | uses: actions/upload-artifact@v3 122 | if: matrix.cibw_build 123 | with: 124 | path: wheelhouse/*.whl 125 | finish: 126 | needs: test 127 | if: {{ '${{ always() }}' }} 128 | runs-on: ubuntu-latest 129 | steps: 130 | - uses: coverallsapp/github-action@v2 131 | with: 132 | parallel-finished: true 133 | -------------------------------------------------------------------------------- /docs/authors.rst: -------------------------------------------------------------------------------- 1 | .. include:: ../AUTHORS.rst 2 | -------------------------------------------------------------------------------- /docs/changelog.rst: -------------------------------------------------------------------------------- 1 | .. include:: ../CHANGELOG.rst 2 | -------------------------------------------------------------------------------- /docs/conf.py: -------------------------------------------------------------------------------- 1 | extensions = [ 2 | "sphinx.ext.autodoc", 3 | "sphinx.ext.autosummary", 4 | "sphinx.ext.coverage", 5 | "sphinx.ext.doctest", 6 | "sphinx.ext.extlinks", 7 | "sphinx.ext.ifconfig", 8 | "sphinx.ext.napoleon", 9 | "sphinx.ext.todo", 10 | "sphinx.ext.viewcode", 11 | ] 12 | source_suffix = ".rst" 13 | master_doc = "index" 14 | project = "Nameless" 15 | year = "2019-now" 16 | author = "Ionel Cristian Mărieș" 17 | copyright = f"{year}, {author}" 18 | try: 19 | from pkg_resources import get_distribution 20 | 21 | version = release = get_distribution("nameless").version 22 | except Exception: 23 | import traceback 24 | 25 | traceback.print_exc() 26 | version = release = "1.0.0" 27 | 28 | pygments_style = "trac" 29 | templates_path = ["."] 30 | extlinks = { 31 | "issue": ("https://github.com/ionelmc/python-nameless/issues/%s", "#"), 32 | "pr": ("https://github.com/ionelmc/python-nameless/pull/%s", "PR #"), 33 | } 34 | 35 | html_theme_options = { 36 | "githuburl": "https://github.com/ionelmc/python-nameless/", 37 | } 38 | 39 | html_use_smartypants = True 40 | html_last_updated_fmt = "%b %d, %Y" 41 | html_split_index = False 42 | html_sidebars = { 43 | "**": ["searchbox.html", "globaltoc.html", "sourcelink.html"], 44 | } 45 | html_short_title = f"{project}-{version}" 46 | 47 | napoleon_use_ivar = True 48 | napoleon_use_rtype = False 49 | napoleon_use_param = False 50 | -------------------------------------------------------------------------------- /docs/contributing.rst: -------------------------------------------------------------------------------- 1 | .. include:: ../CONTRIBUTING.rst 2 | -------------------------------------------------------------------------------- /docs/index.rst: -------------------------------------------------------------------------------- 1 | ======== 2 | Contents 3 | ======== 4 | 5 | .. toctree:: 6 | :maxdepth: 2 7 | 8 | readme 9 | installation 10 | usage 11 | reference/index 12 | contributing 13 | authors 14 | changelog 15 | 16 | Indices and tables 17 | ================== 18 | 19 | * :ref:`genindex` 20 | * :ref:`modindex` 21 | * :ref:`search` 22 | -------------------------------------------------------------------------------- /docs/installation.rst: -------------------------------------------------------------------------------- 1 | ============ 2 | Installation 3 | ============ 4 | 5 | At the command line:: 6 | 7 | pip install nameless 8 | -------------------------------------------------------------------------------- /docs/readme.rst: -------------------------------------------------------------------------------- 1 | .. include:: ../README.rst 2 | -------------------------------------------------------------------------------- /docs/reference/index.rst: -------------------------------------------------------------------------------- 1 | Reference 2 | ========= 3 | 4 | .. toctree:: 5 | :glob: 6 | 7 | nameless* 8 | -------------------------------------------------------------------------------- /docs/reference/nameless.rst: -------------------------------------------------------------------------------- 1 | nameless 2 | ======== 3 | 4 | .. testsetup:: 5 | 6 | from nameless import * 7 | 8 | .. automodule:: nameless 9 | :members: 10 | :undoc-members: 11 | :special-members: __init__, __len__ 12 | -------------------------------------------------------------------------------- /docs/requirements.txt: -------------------------------------------------------------------------------- 1 | sphinx>=1.3 2 | sphinx-rtd-theme 3 | -------------------------------------------------------------------------------- /docs/spelling_wordlist.txt: -------------------------------------------------------------------------------- 1 | builtin 2 | builtins 3 | classmethod 4 | staticmethod 5 | classmethods 6 | staticmethods 7 | args 8 | kwargs 9 | callstack 10 | Changelog 11 | Indices 12 | -------------------------------------------------------------------------------- /docs/usage.rst: -------------------------------------------------------------------------------- 1 | ===== 2 | Usage 3 | ===== 4 | 5 | To use the project: 6 | 7 | .. code-block:: python 8 | 9 | import nameless 10 | nameless.compute(...) 11 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = [ 3 | "setuptools>=30.3.0", 4 | "setuptools_scm>=3.3.1", 5 | ] 6 | 7 | [tool.ruff] 8 | extend-exclude = ["static", "ci/templates"] 9 | line-length = 140 10 | src = ["src", "tests"] 11 | target-version = "py38" 12 | 13 | [tool.ruff.lint.per-file-ignores] 14 | "ci/*" = ["S"] 15 | 16 | [tool.ruff.lint] 17 | ignore = [ 18 | "RUF001", # ruff-specific rules ambiguous-unicode-character-string 19 | "S101", # flake8-bandit assert 20 | "S308", # flake8-bandit suspicious-mark-safe-usage 21 | "S603", # flake8-bandit subprocess-without-shell-equals-true 22 | "S607", # flake8-bandit start-process-with-partial-path 23 | "E501", # pycodestyle line-too-long 24 | ] 25 | select = [ 26 | "B", # flake8-bugbear 27 | "C4", # flake8-comprehensions 28 | "DTZ", # flake8-datetimez 29 | "E", # pycodestyle errors 30 | "EXE", # flake8-executable 31 | "F", # pyflakes 32 | "I", # isort 33 | "INT", # flake8-gettext 34 | "PIE", # flake8-pie 35 | "PLC", # pylint convention 36 | "PLE", # pylint errors 37 | "PT", # flake8-pytest-style 38 | "PTH", # flake8-use-pathlib 39 | "Q", # flake8-quotes 40 | "RSE", # flake8-raise 41 | "RUF", # ruff-specific rules 42 | "S", # flake8-bandit 43 | "UP", # pyupgrade 44 | "W", # pycodestyle warnings 45 | ] 46 | 47 | [tool.ruff.lint.flake8-pytest-style] 48 | fixture-parentheses = false 49 | mark-parentheses = false 50 | 51 | [tool.ruff.lint.isort] 52 | forced-separate = ["conftest"] 53 | force-single-line = true 54 | 55 | [tool.black] 56 | line-length = 140 57 | target-version = ["py38"] 58 | -------------------------------------------------------------------------------- /pytest.ini: -------------------------------------------------------------------------------- 1 | [pytest] 2 | # If a pytest section is found in one of the possible config files 3 | # (pytest.ini, tox.ini or setup.cfg), then pytest will not look for any others, 4 | # so if you add a pytest config section elsewhere, 5 | # you will need to delete this section from setup.cfg. 6 | norecursedirs = 7 | .git 8 | .tox 9 | .env 10 | dist 11 | build 12 | migrations 13 | 14 | python_files = 15 | test_*.py 16 | *_test.py 17 | tests.py 18 | addopts = 19 | -ra 20 | --strict-markers 21 | --ignore=docs/conf.py 22 | --ignore=setup.py 23 | --ignore=ci 24 | --ignore=.eggs 25 | --doctest-modules 26 | --doctest-glob=\*.rst 27 | --tb=short 28 | --pyargs 29 | # The order of these options matters. testpaths comes after addopts so that 30 | # nameless in testpaths is interpreted as 31 | # --pyargs nameless. 32 | # Any tests in the src/ directory (that is, tests installed with the package) 33 | # can be run by any user with pytest --pyargs nameless. 34 | testpaths = 35 | nameless 36 | # If you want to switch back to tests outside package just remove --pyargs 37 | # and edit testpaths to have "tests/" instead of "nameless". 38 | 39 | # Idea from: https://til.simonwillison.net/pytest/treat-warnings-as-errors 40 | filterwarnings = 41 | error 42 | # You can add exclusions, some examples: 43 | # ignore:'nameless' defines default_app_config:PendingDeprecationWarning:: 44 | # ignore:The {{% if::: 45 | # ignore:Coverage disabled via --no-cov switch! 46 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import os 3 | import re 4 | from pathlib import Path 5 | 6 | from setuptools import Extension 7 | from setuptools import find_packages 8 | from setuptools import setup 9 | from setuptools.command.build_ext import build_ext 10 | from setuptools.dist import Distribution 11 | 12 | try: 13 | # Allow installing package without any Cython available. This 14 | # assumes you are going to include the .c files in your sdist. 15 | import Cython 16 | except ImportError: 17 | Cython = None 18 | 19 | # Enable code coverage for C code: we cannot use CFLAGS=-coverage in tox.ini, since that may mess with compiling 20 | # dependencies (e.g. numpy). Therefore, we set SETUPPY_CFLAGS=-coverage in tox.ini and copy it to CFLAGS here (after 21 | # deps have been safely installed). 22 | if "TOX_ENV_NAME" in os.environ and os.environ.get("SETUPPY_EXT_COVERAGE") == "yes": 23 | CFLAGS = os.environ["CFLAGS"] = "-DCYTHON_TRACE=1" 24 | LFLAGS = os.environ["LFLAGS"] = "" 25 | else: 26 | CFLAGS = "" 27 | LFLAGS = "" 28 | 29 | 30 | class OptionalBuildExt(build_ext): 31 | """ 32 | Allow the building of C extensions to fail. 33 | """ 34 | 35 | def run(self): 36 | try: 37 | if os.environ.get("SETUPPY_FORCE_PURE"): 38 | raise Exception("C extensions disabled (SETUPPY_FORCE_PURE)!") 39 | super().run() 40 | except Exception as e: 41 | self._unavailable(e) 42 | self.extensions = [] # avoid copying missing files (it would fail). 43 | 44 | def _unavailable(self, e): 45 | print("*" * 80) 46 | print( 47 | """WARNING: 48 | 49 | An optional code optimization (C extension) could not be compiled. 50 | 51 | Optimizations for this package will not be available! 52 | """ 53 | ) 54 | 55 | print("CAUSE:") 56 | print("") 57 | print(" " + repr(e)) 58 | print("*" * 80) 59 | 60 | 61 | class BinaryDistribution(Distribution): 62 | """ 63 | Distribution which almost always forces a binary package with platform name 64 | """ 65 | 66 | def has_ext_modules(self): 67 | return super().has_ext_modules() or not os.environ.get("SETUPPY_ALLOW_PURE") 68 | 69 | 70 | def read(*names, **kwargs): 71 | with Path(__file__).parent.joinpath(*names).open(encoding=kwargs.get("encoding", "utf8")) as fh: 72 | return fh.read() 73 | 74 | 75 | setup( 76 | name="nameless", 77 | use_scm_version={ 78 | "local_scheme": "dirty-tag", 79 | "write_to": "src/nameless/_version.py", 80 | "fallback_version": "1.0.0", 81 | }, 82 | license="BSD-2-Clause", 83 | description="An example package. Generated with cookiecutter-pylibrary.", 84 | long_description="{}\n{}".format( 85 | re.compile("^.. start-badges.*^.. end-badges", re.M | re.S).sub("", read("README.rst")), 86 | re.sub(":[a-z]+:`~?(.*?)`", r"``\1``", read("CHANGELOG.rst")), 87 | ), 88 | author="Ionel Cristian Mărieș", 89 | author_email="contact@ionelmc.ro", 90 | url="https://github.com/ionelmc/python-nameless", 91 | packages=find_packages("src"), 92 | package_dir={"": "src"}, 93 | py_modules=[path.stem for path in Path("src").glob("*.py")], 94 | include_package_data=True, 95 | zip_safe=False, 96 | classifiers=[ 97 | # complete classifier list: http://pypi.python.org/pypi?%3Aaction=list_classifiers 98 | "Development Status :: 5 - Production/Stable", 99 | "Intended Audience :: Developers", 100 | "License :: OSI Approved :: BSD License", 101 | "Operating System :: Unix", 102 | "Operating System :: POSIX", 103 | "Operating System :: Microsoft :: Windows", 104 | "Programming Language :: Python", 105 | "Programming Language :: Python :: 3", 106 | "Programming Language :: Python :: 3 :: Only", 107 | "Programming Language :: Python :: 3.8", 108 | "Programming Language :: Python :: 3.9", 109 | "Programming Language :: Python :: 3.10", 110 | "Programming Language :: Python :: 3.11", 111 | "Programming Language :: Python :: 3.12", 112 | "Programming Language :: Python :: Implementation :: CPython", 113 | "Programming Language :: Python :: Implementation :: PyPy", 114 | # uncomment if you test on these interpreters: 115 | # "Programming Language :: Python :: Implementation :: IronPython", 116 | # "Programming Language :: Python :: Implementation :: Jython", 117 | # "Programming Language :: Python :: Implementation :: Stackless", 118 | "Topic :: Utilities", 119 | ], 120 | project_urls={ 121 | "Documentation": "https://python-nameless.readthedocs.io/", 122 | "Changelog": "https://python-nameless.readthedocs.io/en/latest/changelog.html", 123 | "Issue Tracker": "https://github.com/ionelmc/python-nameless/issues", 124 | }, 125 | keywords=[ 126 | # eg: "keyword1", "keyword2", "keyword3", 127 | ], 128 | python_requires=">=3.8", 129 | install_requires=[ 130 | # eg: "aspectlib==1.1.1", "six>=1.7", 131 | ], 132 | extras_require={ 133 | # eg: 134 | # "rst": ["docutils>=0.11"], 135 | # ":python_version=="2.6"": ["argparse"], 136 | }, 137 | setup_requires=( 138 | [ 139 | "setuptools_scm>=3.3.1", 140 | "cython", 141 | ] 142 | if Cython 143 | else [ 144 | "setuptools_scm>=3.3.1", 145 | ] 146 | ), 147 | entry_points={ 148 | "console_scripts": [ 149 | "nameless = nameless.cli:run", 150 | ] 151 | }, 152 | cmdclass={"build_ext": OptionalBuildExt}, 153 | ext_modules=[ 154 | Extension( 155 | str(path.relative_to("src").with_suffix("")).replace(os.sep, "."), 156 | sources=[str(path)], 157 | extra_compile_args=CFLAGS.split(), 158 | extra_link_args=LFLAGS.split(), 159 | include_dirs=[str(path.parent)], 160 | ) 161 | for path in Path("src").glob("**/*.pyx" if Cython else "**/*.c") 162 | ], 163 | distclass=BinaryDistribution, 164 | ) 165 | -------------------------------------------------------------------------------- /src/nameless/__init__.py: -------------------------------------------------------------------------------- 1 | __version__ = "1.0.0" 2 | 3 | from .core import compute 4 | 5 | __all__ = [ 6 | "compute", 7 | ] 8 | -------------------------------------------------------------------------------- /src/nameless/__main__.py: -------------------------------------------------------------------------------- 1 | """ 2 | Entrypoint module, in case you use `python -mnameless`. 3 | 4 | 5 | Why does this file exist, and why __main__? For more info, read: 6 | 7 | - https://www.python.org/dev/peps/pep-0338/ 8 | - https://docs.python.org/2/using/cmdline.html#cmdoption-m 9 | - https://docs.python.org/3/using/cmdline.html#cmdoption-m 10 | """ 11 | 12 | from nameless.cli import run 13 | 14 | if __name__ == "__main__": 15 | run() 16 | -------------------------------------------------------------------------------- /src/nameless/_core.pyx: -------------------------------------------------------------------------------- 1 | # cython: linetrace=True, language_level=3str 2 | 3 | def compute(args): 4 | return max(args, key=len) 5 | -------------------------------------------------------------------------------- /src/nameless/cli.py: -------------------------------------------------------------------------------- 1 | """ 2 | Module that contains the command line app. 3 | 4 | Why does this file exist, and why not put this in __main__? 5 | 6 | You might be tempted to import things from __main__ later, but that will cause 7 | problems: the code will get executed twice: 8 | 9 | - When you run `python -mnameless` python will execute 10 | ``__main__.py`` as a script. That means there will not be any 11 | ``nameless.__main__`` in ``sys.modules``. 12 | - When you import __main__ it will get executed again (as a module) because 13 | there"s no ``nameless.__main__`` in ``sys.modules``. 14 | 15 | Also see (1) from http://click.pocoo.org/5/setuptools/#setuptools-integration 16 | """ 17 | 18 | import argparse 19 | 20 | from .core import compute 21 | 22 | parser = argparse.ArgumentParser(description="Command description.") 23 | parser.add_argument( 24 | "names", 25 | metavar="NAME", 26 | nargs=argparse.ZERO_OR_MORE, 27 | help="A name of something.", 28 | ) 29 | 30 | 31 | def run(args=None): 32 | args = parser.parse_args(args=args) 33 | print(compute(args.names)) 34 | parser.exit(0) 35 | -------------------------------------------------------------------------------- /src/nameless/core.py: -------------------------------------------------------------------------------- 1 | try: 2 | from ._core import compute 3 | except ImportError: 4 | 5 | def compute(args): 6 | return max(args, key=len) 7 | -------------------------------------------------------------------------------- /src/nameless/tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ionelmc/python-nameless/3b2607a92d285525b58c2d08b25169328d473c5e/src/nameless/tests/__init__.py -------------------------------------------------------------------------------- /src/nameless/tests/test_cli.py: -------------------------------------------------------------------------------- 1 | import subprocess 2 | 3 | 4 | def test_main(): 5 | assert subprocess.check_output(["nameless", "foo", "foobar"], text=True) == "foobar\n" 6 | -------------------------------------------------------------------------------- /src/nameless/tests/test_core.py: -------------------------------------------------------------------------------- 1 | from .. import compute 2 | 3 | 4 | def test_compute(): 5 | assert compute([b"a", b"bc", b"abc"]) == b"abc" 6 | -------------------------------------------------------------------------------- /tox.ini: -------------------------------------------------------------------------------- 1 | [testenv:bootstrap] 2 | deps = 3 | jinja2 4 | tox 5 | skip_install = true 6 | commands = 7 | python ci/bootstrap.py --no-env 8 | passenv = 9 | * 10 | 11 | ; a generative tox configuration, see: https://tox.wiki/en/latest/user_guide.html#generative-environments 12 | [tox] 13 | envlist = 14 | clean, 15 | check, 16 | docs, 17 | {py38,py39,py310,py311,py312,pypy38,pypy39,pypy310}-{cover,nocov}, 18 | report 19 | ignore_basepython_conflict = true 20 | 21 | [testenv] 22 | basepython = 23 | pypy38: {env:TOXPYTHON:pypy3.8} 24 | pypy39: {env:TOXPYTHON:pypy3.9} 25 | pypy310: {env:TOXPYTHON:pypy3.10} 26 | py38: {env:TOXPYTHON:python3.8} 27 | py39: {env:TOXPYTHON:python3.9} 28 | py310: {env:TOXPYTHON:python3.10} 29 | py311: {env:TOXPYTHON:python3.11} 30 | py312: {env:TOXPYTHON:python3.12} 31 | {bootstrap,clean,check,report,docs,codecov,coveralls,extension-coveralls}: {env:TOXPYTHON:python3} 32 | setenv = 33 | PYTHONPATH={toxinidir}/tests 34 | PYTHONUNBUFFERED=yes 35 | cover: SETUPPY_EXT_COVERAGE=yes 36 | passenv = 37 | * 38 | usedevelop = 39 | cover: true 40 | nocov: false 41 | deps = 42 | pytest 43 | cover: pytest-cov 44 | cython 45 | setuptools 46 | commands = 47 | cover: python setup.py clean --all build_ext --force --inplace 48 | nocov: {posargs:pytest -vv --ignore=src} 49 | cover: {posargs:pytest --cov --cov-report=term-missing --cov-report=xml -vv} 50 | 51 | [testenv:check] 52 | deps = 53 | docutils 54 | pre-commit 55 | readme-renderer 56 | pygments 57 | isort 58 | setuptools-scm 59 | skip_install = true 60 | commands = 61 | python setup.py check --strict --metadata --restructuredtext 62 | pre-commit run --all-files --show-diff-on-failure 63 | 64 | [testenv:cythonize] 65 | basepython = {env:TOXPYTHON:python} 66 | pip_pre = true 67 | deps = 68 | cython 69 | skip_install = true 70 | commands = 71 | {posargs:python setup.py clean --all build_ext --force} 72 | 73 | [testenv:docs] 74 | usedevelop = true 75 | install_command = 76 | python -m pip install --no-use-pep517 {opts} {packages} 77 | deps = 78 | -r{toxinidir}/docs/requirements.txt 79 | commands = 80 | sphinx-build {posargs:-E} -b doctest docs dist/docs 81 | sphinx-build {posargs:-E} -b html docs dist/docs 82 | sphinx-build -b linkcheck docs dist/docs 83 | 84 | [testenv:report] 85 | deps = 86 | coverage 87 | cython 88 | skip_install = true 89 | commands = 90 | coverage report 91 | coverage html 92 | 93 | [testenv:clean] 94 | commands = 95 | python setup.py clean 96 | coverage erase 97 | skip_install = true 98 | deps = 99 | coverage 100 | cython 101 | --------------------------------------------------------------------------------