├── .coveragerc ├── .editorconfig ├── .github ├── FUNDING.yml └── workflows │ ├── macos.yml │ ├── ubuntu.yml │ └── windows.yml ├── .gitignore ├── .pre-commit-config.yaml ├── ChangeLog ├── LICENSE ├── MANIFEST.in ├── Makefile ├── NEWS.md ├── README.rst ├── SECURITY.md ├── THANKS ├── __pkginfo__.py ├── admin-tools ├── check-2.4-2.7-versions.sh ├── check-3.0-3.2-versions.sh ├── check-3.3-3.5-versions.sh ├── check-3.6-3.10-versions.sh ├── check-newest-versions.sh ├── check-versions.sh ├── checkout_common.sh ├── make-dist-2.4-2.7.sh ├── make-dist-3.0-3.5.sh ├── make-dist-newer.sh ├── make-dist.sh ├── merge-for-2.4.sh ├── merge-for-3.0.sh ├── merge-for-3.3.sh ├── merge-for-3.6.sh ├── pyenv-2.4-2.7-versions ├── pyenv-3.0-3.2-versions ├── pyenv-3.3-3.5-versions ├── pyenv-3.6-3.10-versions ├── pyenv-newest-versions ├── setup-master.sh ├── setup-python-2.4.sh ├── setup-python-3.0.sh ├── setup-python-3.3.sh └── setup-python-3.6.sh ├── columnize ├── __init__.py ├── __main__.py └── version.py ├── example.py ├── requirements-dev.txt ├── setup.cfg ├── setup.py ├── test └── test_columnize.py └── tox.ini /.coveragerc: -------------------------------------------------------------------------------- 1 | [report] 2 | exclude_lines = 3 | pragma: no cover 4 | pass 5 | def __repr__ 6 | if self.debug: 7 | if settings.DEBUG 8 | raise AssertionError 9 | raise NotImplementedError 10 | if 0: 11 | if __name__ *== *.__main__.: 12 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # This is an EditorConfig file 2 | # https://EditorConfig.org 3 | 4 | root = true 5 | 6 | [*] 7 | end_of_line = lf 8 | insert_final_newline = true 9 | charset = utf-8 10 | indent_style = tab 11 | indent_size = 4 12 | insert_final_newline = true 13 | 14 | [*.yml] 15 | indent_style = space 16 | indent_size = 2 17 | end_of_line = lf 18 | insert_final_newline = true 19 | 20 | [*.py] 21 | indent_style = space 22 | indent_size = 4 23 | end_of_line = lf 24 | insert_final_newline = true 25 | 26 | # Tab indentation (no size specified) 27 | [Makefile] 28 | indent_style = tab 29 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: ["rocky"] 4 | patreon: # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: "pypi/columnize" 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] 13 | -------------------------------------------------------------------------------- /.github/workflows/macos.yml: -------------------------------------------------------------------------------- 1 | name: pycolumnize (macos) 2 | 3 | on: 4 | push: 5 | branches: [ master ] 6 | pull_request: 7 | branches: [ master ] 8 | 9 | jobs: 10 | build: 11 | runs-on: macos-latest 12 | strategy: 13 | matrix: 14 | os: [macOS] 15 | python-version: ['3.8', '3.9', '3.10', '3.11', '3.12', '3.13'] 16 | steps: 17 | - uses: actions/checkout@v3 18 | - name: Set up Python ${{ matrix.python-version }} 19 | uses: actions/setup-python@v2 20 | with: 21 | python-version: ${{ matrix.python-version }} 22 | - name: Install dependencies 23 | run: | 24 | pip install -e . 25 | pip install -r requirements-dev.txt 26 | - name: Test pycolumnize 27 | run: | 28 | make check 29 | -------------------------------------------------------------------------------- /.github/workflows/ubuntu.yml: -------------------------------------------------------------------------------- 1 | name: pycolumnize (ubuntu) 2 | 3 | on: 4 | push: 5 | branches: [ master ] 6 | pull_request: 7 | branches: [ master ] 8 | 9 | jobs: 10 | build: 11 | runs-on: ubuntu-latest 12 | strategy: 13 | matrix: 14 | python-version: ['3.8', '3.9', '3.10', '3.11', '3.12', '3.13'] 15 | steps: 16 | - uses: actions/checkout@v4 17 | - name: Set up Python ${{ matrix.python-version }} 18 | uses: actions/setup-python@v5 19 | with: 20 | python-version: ${{ matrix.python-version }} 21 | - name: Install dependencies 22 | run: | 23 | python -m pip install --upgrade pip 24 | pip install -e . 25 | pip install -r requirements-dev.txt 26 | - name: Test pycolumnize 27 | run: | 28 | make check 29 | -------------------------------------------------------------------------------- /.github/workflows/windows.yml: -------------------------------------------------------------------------------- 1 | name: pycolumnize (MS Windows) 2 | 3 | on: 4 | push: 5 | branches: [ master ] 6 | pull_request: 7 | branches: [ master ] 8 | 9 | jobs: 10 | build: 11 | runs-on: windows-latest 12 | strategy: 13 | matrix: 14 | os: [windows] 15 | python-version: ['3.8', '3.9', '3.10', '3.11', '3.12', '3.13'] 16 | steps: 17 | - uses: actions/checkout@v3 18 | - name: Set up Python ${{ matrix.python-version }} 19 | uses: actions/setup-python@v2 20 | with: 21 | python-version: ${{ matrix.python-version }} 22 | - name: Install dependencies 23 | run: | 24 | pip install -e . 25 | pip install -r requirements-dev.txt 26 | - name: Test pycolumnize 27 | run: | 28 | make check 29 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.bak 2 | *.pyc 3 | *.so 4 | *~ 5 | .coverage 6 | .eggs/ 7 | .python-version 8 | /*.egg 9 | /*.egg-info 10 | /.cache 11 | /.tox 12 | /build 13 | /columnize.build 14 | /dist 15 | /tmp 16 | __pycache__ 17 | coverage.xml 18 | htmlcov/ 19 | -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | default_language_version: 2 | python: python 3 | repos: 4 | - repo: https://github.com/pre-commit/pre-commit-hooks 5 | rev: v4.0.1 6 | hooks: 7 | - id: check-merge-conflict 8 | - id: debug-statements 9 | stages: [commit] 10 | - id: end-of-file-fixer 11 | stages: [commit] 12 | - repo: https://github.com/psf/black 13 | rev: 22.6.0 14 | hooks: 15 | - id: black 16 | language_version: python 17 | stages: [commit] 18 | additional_dependencies: ["click"] 19 | - repo: https://github.com/pycqa/flake8 20 | rev: 3.9.2 21 | hooks: 22 | - id: flake8 23 | stages: [commit] 24 | -------------------------------------------------------------------------------- /ChangeLog: -------------------------------------------------------------------------------- 1 | 2022-03-11 rocky 2 | 3 | * columnize/version.py: Get ready for release 0.3.11 4 | 5 | 2022-03-11 rocky 6 | 7 | * admin-tools/make-dist-2.4-2.7.sh, 8 | admin-tools/make-dist-3.0-3.5.sh, admin-tools/make-dist-newer.sh: 9 | Administrivia - Start adding updated packaging 10 | 11 | 2022-03-11 rocky 12 | 13 | * admin-tools/{check-3.1-3.5-versions => check-3.0-3.5-versions}, 14 | admin-tools/{pyenv-3.1-3.5-versions => pyenv-3.0-3.5-versions}, 15 | admin-tools/{setup-python-3.1.sh => setup-python-3.0.sh}, 16 | requirements.txt: Try adding 3.0 to the mix 17 | 18 | 2022-03-10 rocky 19 | 20 | * admin-tools/check-3.1-3.5-versions, 21 | admin-tools/pyenv-3.1-3.5-versions, admin-tools/setup-python-3.1.sh: 22 | Admnistrivia 23 | 24 | 2022-03-10 rocky 25 | 26 | * .gitignore, admin-tools/check-2.4-2.7-versions.sh, 27 | admin-tools/check-newest-versions.sh, 28 | admin-tools/check-versions.sh, admin-tools/make-dist.sh, 29 | admin-tools/pyenv-2.4-2.7-versions, 30 | admin-tools/pyenv-newest-versions, admin-tools/setup-master.sh, 31 | admin-tools/setup-python-2.4.sh, setup.py: Administrivia - version 32 | testing 33 | 34 | 2022-03-10 rocky 35 | 36 | * MANIFEST.in, __pkginfo__.py: Administrivia... Add 3.9 and 3.10 to list of Pythons Wrong name in MANIFEST.in 37 | 38 | 2022-03-10 rocky 39 | 40 | * Makefile, setup.cfg: Administrivia Revise Makefile: * Use build package to build package * Turn off universal build. We do separate for Python 2 vs 3 41 | 42 | 2022-03-09 rocky 43 | 44 | * columnize/__init__.py, test/test_columnize.py: Add back all tests 45 | 46 | 2022-03-09 rocky 47 | 48 | * README.rst: Remove obsolete build status badges 49 | 50 | 2022-03-09 rocky 51 | 52 | * .github/workflows/osx.yml, .github/workflows/ubuntu.yml, 53 | .github/workflows/windows.yml, requirements-dev.txt: Go over 54 | workflows CI 55 | 56 | 2022-03-09 rocky 57 | 58 | * NEWS.md, appveyor.yml: Update NEWS remove appveyor 59 | 60 | 2022-03-09 R. Bernstein 61 | 62 | * : Merge pull request #30 from rocky/modernize Modernize 63 | 64 | 2022-03-08 rocky 65 | 66 | * __pkginfo__.py, setup.py, test/test_columnize.py: Reinstate more 67 | tests and ... add pytest to test_requires 68 | 69 | 2022-03-08 rocky 70 | 71 | * .gitignore, .pre-commit-config.yaml, ChangeLog, MANIFEST.in, 72 | Makefile, __pkginfo__.py, columnize/__init__.py, columnize.py => 73 | columnize/__main__.py, VERSION.py => columnize/version.py, 74 | setup.cfg, setup.py, test/test_columnize.py, test_columnize.py: Redo 75 | using more modern conventions This program goes back to 2008. Things have changed not always in an 76 | upward compatibile way. And then some of the newer stuff is a little nicer. 77 | 78 | 2021-06-23 rocky 79 | 80 | * VERSION.py: Black shouldn't format VERSION.py 81 | 82 | 2021-06-23 rocky 83 | 84 | * .editorconfig, columnize.py, setup.cfg: Blacken columnize; add 85 | config files 86 | 87 | 2020-04-16 R. Bernstein 88 | 89 | * .github/FUNDING.yml: Update FUNDING.yml 90 | 91 | 2020-04-16 rocky 92 | 93 | * MANIFEST.in, NEWS => NEWS.md, THANKS, __init__.py, 94 | __pkginfo__.py, columnize.py, requirements.txt, setup.py, 95 | test_columnize.py, tox.ini: Get ready for release 0.3.10 & 96 | portability issues 97 | 98 | 2020-04-16 rocky 99 | 100 | * VERSION.py: Get ready for release 0.3.10 101 | 102 | 2020-04-14 R. Bernstein 103 | 104 | * : Merge pull request #27 from phated/patch-1 Fix project in Tidelift language 105 | 106 | 2020-04-10 rocky 107 | 108 | * __pkginfo__.py: Regularize License 109 | 110 | 2020-04-10 R. Bernstein 111 | 112 | * __pkginfo__.py: Update __pkginfo__.py Changte license from PSF2 to MIT. 113 | 114 | 2020-04-06 rocky 115 | 116 | * appveyor.yml: Another Appveyor try 117 | 118 | 2020-04-06 rocky 119 | 120 | * appveyor.yml: Try to fix appveyor 121 | 122 | 2020-04-06 rocky 123 | 124 | * : commit 76a06c429a7a73646d0a1c20aba3fa9ae53956f4 Author: rocky 125 | Date: Mon Apr 6 20:47:46 2020 -0400 126 | 127 | 2020-04-06 R. Bernstein 128 | 129 | * .github/FUNDING.yml: Create FUNDING.yml 130 | 131 | 2020-04-06 rocky 132 | 133 | * README.rst, SECURITY.md: Add Tidelift security policy 134 | 135 | 2019-12-01 rocky 136 | 137 | * appveyor.yml: Appveyor version update 138 | 139 | 2019-12-01 rocky 140 | 141 | * appveyor.yml: update appveyor Python release testing 142 | 143 | 2019-11-30 rocky 144 | 145 | * Makefile, columnize.py, setup.py, tox.ini: More administrivia... Add Makefile targets: lint, flake8, wheel Lint columnize.py 146 | 147 | 2019-11-30 rocky 148 | 149 | * .travis.yml: Travis: try pypy3 150 | 151 | 2019-11-30 rocky 152 | 153 | * .travis.yml: Travis: try pypy36 154 | 155 | 2019-11-30 rocky 156 | 157 | * .travis.yml: Travis: add pypy testing 158 | 159 | 2019-11-30 rocky 160 | 161 | * .travis.yml: Travis add 2.7 testing 162 | 163 | 2019-11-30 rocky 164 | 165 | * .travis.yml, tox.ini: Travis 3rd try 166 | 167 | 2019-11-30 rocky 168 | 169 | * .travis.yml, __pkginfo__.py, setup.py: Administrivia... Note we handle 3.6-3.8 Travis testing on only later versions of 170 | Python Note that we need mock 171 | 172 | 2019-11-30 rocky 173 | 174 | * README.rst: Change email address 175 | 176 | 2019-11-30 rocky 177 | 178 | * README.rst: More badges 179 | 180 | 2017-08-10 rocky 181 | 182 | * .travis.yml: I said, back off additional Travis testting 183 | 184 | 2017-08-10 rocky 185 | 186 | * tox.ini: Back off the additional Travis environments for now 187 | 188 | 2017-08-10 rocky 189 | 190 | * .travis.yml, tox.ini: Try more travis Python versions 191 | 192 | 2016-11-12 rocky 193 | 194 | * README.rst, appveyor.yml, appveyor/install.ps1, 195 | appveyor/run_with_env.cmd: Try appveyor - with build status markers 196 | 197 | 2016-11-12 rocky 198 | 199 | * appveyor.yml, setup.py: Try appveyor 200 | 201 | 2016-05-05 rocky 202 | 203 | * .travis.yml: Nope 3.2 too old and has dependency problems 204 | 205 | 2016-05-05 rocky 206 | 207 | * .travis.yml: No python 3.5 how about 3.2? 208 | 209 | 2016-05-05 rocky 210 | 211 | * .travis.yml: Try python 3.5 212 | 213 | 2016-03-19 rocky 214 | 215 | * ChangeLog, MANIFEST.in, NEWS, THANKS, VERSION.py: Get ready for 216 | release 0.3.9 217 | 218 | 2016-03-18 R. Bernstein 219 | 220 | * : Merge pull request #26 from martica/patch-2 Fix for line prefix width subtraction bug 221 | 222 | 2016-03-17 Tyler Bindon 223 | 224 | * columnize.py, test_columnize.py: Don't subtract lineprefix width 225 | twice 226 | 227 | 2016-03-17 Tyler Bindon 228 | 229 | * test_columnize.py: Add test for prefix length bug 230 | 231 | 2016-03-17 Tyler Bindon 232 | 233 | * test_columnize.py: Tweak test to cause crash without fix. 234 | 235 | 2016-03-17 Tyler Bindon 236 | 237 | * test_columnize.py: Fix the test to reflect the single column 238 | output 239 | 240 | 2016-03-17 Tyler Bindon 241 | 242 | * columnize.py: Fix crash when the displayWidth is too small for two 243 | columns It is a degenerate case, but if there is no solution with more than 244 | one column, the algorithm currently dies trying to look up the width 245 | of the non-existent second column. 246 | 247 | 2015-12-15 rocky 248 | 249 | * .travis.yml: I said remove tex testingfor Python 3.5 on travis! 250 | 251 | 2015-12-15 rocky 252 | 253 | * tox.ini: Remove Python 3.5 tox testing on travis - it dose not 254 | work 255 | 256 | 2015-12-15 rocky 257 | 258 | * .travis.yml: Travis: tox is broken for python 3.2. Try python 3.5. 259 | 260 | 2015-12-15 rocky 261 | 262 | * __pkginfo__.py: Note for ActiveState that we support lots of 263 | Python versoins 264 | 265 | 2015-05-17 rocky 266 | 267 | * README.rst: Remove weird quote in rSt 268 | 269 | 2015-05-17 rocky 270 | 271 | * __init__.py: Add doc 272 | 273 | 2015-04-16 rocky 274 | 275 | * README.rst: CI Status was pointing to wrong place (2nd try) 276 | 277 | 2015-04-16 rocky 278 | 279 | * README.rst: CI Status was pointing to wrong place 280 | 281 | 2015-04-16 rocky 282 | 283 | * README.rst: Correct README.rst example output 284 | 285 | 2015-04-16 rocky 286 | 287 | * .gitignore, .python-version, columnize.py: columnize.py: demo code 288 | now python3 safe .python-version: should not be in git 289 | 290 | 2015-01-26 rocky 291 | 292 | * README.rst: I said remove coderwall endorse 293 | 294 | 2015-01-26 rocky 295 | 296 | * README.rst: Remove coderwall endorse 297 | 298 | 2015-01-26 rocky 299 | 300 | * .gitignore, README.rst: Forgot to add README.rst 301 | 302 | 2015-01-26 rocky 303 | 304 | * MANIFEST.in, Makefile, README.md, README.txt: Try with just 305 | ReStructuredText README. 306 | 307 | 2015-01-24 rocky 308 | 309 | * __pkginfo__.py: We are no longer beta. 310 | 311 | 2015-01-23 rocky 312 | 313 | * .python-version: Svg link was to wrong project 314 | 315 | 2015-01-13 rocky 316 | 317 | * __pkginfo__.py: Need to remove NEWS as well 318 | 319 | 2015-01-13 rocky 320 | 321 | * .gitignore, .travis.yml, ChangeLog, MANIFEST.in, Makefile, NEWS, 322 | README.rst, README.txt, VERSION.py, __pkginfo__.py: README.rst is 323 | derived so it should not be in github. README.txt will be used when 324 | README.rst isn't there (for travis) Get ready for release 0.3.8 325 | 326 | 2015-01-13 rocky 327 | 328 | * MANIFEST.in, Makefile, README.rst, README.txt: Make README.rst 329 | from README.md. Fixes issue #22 330 | 331 | 2015-01-13 rocky 332 | 333 | * NEWS: Regularize dates. 334 | 335 | 2015-01-13 rocky 336 | 337 | * : commit 93e7a027c25b7774eedee4045995e3649d5d9856 Author: rocky 338 | Date: Tue Jan 13 05:38:58 2015 -0500 339 | 340 | 2015-01-13 Marc Abramowitz 341 | 342 | * NEWS: NEWS: Fix date for 0.3.7 343 | 344 | 2015-01-13 rocky 345 | 346 | * .python-version, ChangeLog, NEWS, VERSION.py: Get ready for 347 | release 0.3.7 348 | 349 | 2015-01-12 rocky 350 | 351 | * : commit 8778302455baed1b02a6822b058a86029bb17729 Merge: 5352178 352 | 58c6e01 Author: R. Bernstein Date: 353 | Mon Jan 12 13:50:35 2015 -0500 354 | 355 | 2015-01-12 rocky 356 | 357 | * : commit 535217850ce78dd20a9d3c2ae4901e80489f492e Merge: 4cfbdae 358 | 24d61dd Author: R. Bernstein Date: 359 | Mon Jan 12 13:07:49 2015 -0500 360 | 361 | 2015-01-11 rocky 362 | 363 | * .python-version: More ignore 364 | 365 | 2015-01-11 rocky 366 | 367 | * MANIFEST.in, Makefile, setup.cfg: Makefile: "check" target just 368 | runs one version of python. "check-full" does everything. Add 369 | comments. setup.cfg, MANIFEST.in: correct for moved tests 370 | 371 | 2015-01-10 R. Bernstein 372 | 373 | * : Merge pull request #20 from msabramo/patch-4 README.md: Fix typos in Python examples 374 | 375 | 2015-01-10 R. Bernstein 376 | 377 | * : Merge pull request #18 from msabramo/add_2_more_tests Add 2 more tests 378 | 379 | 2015-01-09 Marc Abramowitz 380 | 381 | * columnize.py, setup.py, test_columnize.py: Use 382 | shutil.get_terminal_size on Python >= 3.3 and backports.shutil_get_terminal_size on Python < 3.3 Fixes #16 383 | 384 | 2015-01-09 Marc Abramowitz 385 | 386 | * test_columnize.py: Add 2 more tests 387 | 388 | 2015-01-09 Marc Abramowitz 389 | 390 | * .coveragerc, columnize.py: Use .coveragerc to exclude lines This is more effective an nicer than littering the code with `# 391 | pragma: no cover` for every `pass` and such. 392 | 393 | 2015-01-10 R. Bernstein 394 | 395 | * : Merge pull request #14 from msabramo/patch-2 Simplify get_option 396 | 397 | 2015-01-09 Marc Abramowitz 398 | 399 | * columnize.py: isinstance can take a tuple of types 400 | 401 | 2015-01-09 Marc Abramowitz 402 | 403 | * columnize.py: Simplify get_option 404 | 405 | 2015-01-10 R. Bernstein 406 | 407 | * : Merge pull request #12 from msabramo/patch-1 Ignore coverage for __main__ 408 | 409 | 2015-01-09 R. Bernstein 410 | 411 | * : Merge pull request #11 from msabramo/increase_coverage Increase coverage + fix prob when stty size fails 412 | 413 | 2015-01-09 R. Bernstein 414 | 415 | * : Merge pull request #10 from msabramo/patch-1 .travis.yml: Run "cover" target 416 | 417 | 2015-01-09 R. Bernstein 418 | 419 | * : Merge pull request #9 from msabramo/measure_coverage Add `cover` tox target 420 | 421 | 2015-01-09 R. Bernstein 422 | 423 | * : Merge pull request #1 from 424 | msabramo/smarter_computed_displaywidth Make computed_displaywidth use tput or stty 425 | 426 | 2015-01-09 R. Bernstein 427 | 428 | * : Merge pull request #2 from msabramo/test_computed_displaywidth Test computed displaywidth 429 | 430 | 2015-01-09 rocky 431 | 432 | * README.md: Put string examples before numeric examples since 433 | issues of one will lead into the other. 434 | 435 | 2015-01-09 R. Bernstein 436 | 437 | * : Merge pull request #8 from msabramo/example Add example.py 438 | 439 | 2015-01-09 Marc Abramowitz 440 | 441 | * test_columnize.py: 442 | test_computed_displaywidth_environ_COLUMNS_not_an_int 443 | 444 | 2015-01-09 Marc Abramowitz 445 | 446 | * test_columnize.py: 447 | test_computed_displaywidth_environ_COLUMNS_unset 448 | 449 | 2015-01-09 Marc Abramowitz 450 | 451 | * test_columnize.py: Add 452 | test_computed_displaywidth_environ_COLUMNS_set 453 | 454 | 2015-01-09 Marc Abramowitz 455 | 456 | * requirements.txt, tox.ini: Add mock and pytest as test 457 | dependencies 458 | 459 | 2015-01-09 R. Bernstein 460 | 461 | * : Merge pull request #7 from msabramo/tox_add_more_envs tox.ini: Add py32, py33, py34 to envlist 462 | 463 | 2015-01-09 R. Bernstein 464 | 465 | * : Merge pull request #5 from msabramo/pkginfo_updates __pkginfo__.py: Update web url 466 | 467 | 2015-01-09 Marc Abramowitz 468 | 469 | * tox.ini: tox.ini: Add py32, py33, py34 to envlist 470 | 471 | 2015-01-09 R. Bernstein 472 | 473 | * : Merge pull request #4 from msabramo/pytest_can_find_tests Make sure py.test can find and run tests 474 | 475 | 2015-01-09 Marc Abramowitz 476 | 477 | * MANIFEST.in, __pkginfo__.py: MANIFEST.in: Add README.md 478 | 479 | 2015-01-09 Marc Abramowitz 480 | 481 | * .travis.yml: .travis.yml: Use tox instead of `make` 482 | 483 | 2015-01-09 Marc Abramowitz 484 | 485 | * Makefile, test/.gitignore, test/Makefile, test/test-basic.py => 486 | test_columnize.py: Make sure py.test can find and run tests Before when running py.test or tox, it wasn't running any tests. I ended up getting rid of the `test` directory and putting the tests 487 | in a single file called `test_columnize.py`. 488 | 489 | 2015-01-09 R. Bernstein 490 | 491 | * : Merge pull request #3 from msabramo/gitignore_eggs .gitignore: Add .eggs/ 492 | 493 | 2015-01-09 rocky 494 | 495 | * README.markdown => README.md, README.txt: Reinstate README.md and 496 | README.txt link. 497 | 498 | 2015-01-09 rocky 499 | 500 | * README.md => README.markdown: See if this clears up travis 501 | 502 | 2015-01-09 rocky 503 | 504 | * : commit f915e19cfdf02aa6c836a1fd2078c5d7e8ca9adc Author: rocky 505 | Date: Fri Jan 9 08:41:55 2015 -0500 506 | 507 | 2015-01-09 rocky 508 | 509 | * README.txt: Badge image name change from "pypi" to "version" 510 | 511 | 2015-01-09 rocky 512 | 513 | * README.txt: Add travis badge 514 | 515 | 2015-01-09 rocky 516 | 517 | * .travis.yml: Travis 3rd try 518 | 519 | 2015-01-09 rocky 520 | 521 | * requirements.txt: Missing requirements file. Travis 2nd try 522 | 523 | 2015-01-09 rocky 524 | 525 | * README.txt: Markdown styling in README. See if travis kicks off 526 | 527 | 2015-01-09 rocky 528 | 529 | * .travis.yml, columnize.py, tox.ini: Add tox.ini file and we'll try 530 | travis soon. 531 | 532 | 2015-01-09 rocky 533 | 534 | * README.md, README.txt: Convert READMER to markdown. 535 | 536 | 2015-01-09 rocky 537 | 538 | * : commit ed822f072d2c32d4912c77f9f966adbf775536ef Author: rocky 539 | Date: Fri Jan 9 07:03:13 2015 -0500 540 | 541 | 2015-01-09 R. Bernstein 542 | 543 | * LICENSE: Initial commit 544 | 545 | 2013-04-22 rocky 546 | 547 | * : commit 08d6e764ad32594df3d4b04e9720f51dd18deb8f Author: rocky 548 | Date: Mon Apr 22 11:19:55 2013 -0400 549 | 550 | 2013-04-22 rocky 551 | 552 | * ChangeLog, NEWS, VERSION.py, columnize.py, test/test-basic.py: Fix 553 | bugs in arrange_array. Get ready for release 0.3.6 554 | 555 | 2013-04-21 rocky 556 | 557 | * VERSION.py, columnize.py: Fix bug in getting computed displaywidth 558 | 559 | 2013-04-18 rocky 560 | 561 | * ChangeLog, Makefile, NEWS, VERSION.py, make-check-filter.py: Get 562 | ready for release 0.3.5 563 | 564 | 2013-03-17 rocky 565 | 566 | * .gitignore, NEWS, test/.cvsignore: Various administrivia 567 | 568 | 2013-03-17 rocky 569 | 570 | * VERSION.py: Bump version 571 | 572 | 2013-03-17 rocky 573 | 574 | * MANIFEST.in, columnize.py: Python 2.5-2.7 and 3.2 compatibility 575 | 576 | 2013-03-17 rocky 577 | 578 | * columnize.py: Add arrange_array option 579 | 580 | 2013-03-17 rocky 581 | 582 | * Makefile, columnize.py, test/test-basic.py: Start an options hash. 583 | Add more options like linesuffix. 584 | 585 | 2013-02-22 rocky 586 | 587 | * columnize.py: Remove relying on outer lexically scoped "ncols" 588 | 589 | 2013-02-14 rocky 590 | 591 | * Makefile: Set reasonable default values for PYTHON and GIT2CL 592 | 593 | 2013-01-06 rocky 594 | 595 | * ChangeLog, MANIFEST.in, Makefile: Fixes to make source tarball 596 | work. 597 | 598 | 2013-01-03 rocky 599 | 600 | * NEWS: Get ready for release 0.3.4 601 | 602 | 2013-01-03 rocky 603 | 604 | * Makefile, NEWS, VERSION.py: Make 3k tolerant. Add "remake" target 605 | comments to Makefile and use git2cl to make ChangeLog. Bump version. 606 | 607 | 2013-01-02 rocky 608 | 609 | * svn2cl_usermap: Administriva 610 | 611 | 2013-01-02 rocky 612 | 613 | * .gitignore, __pkginfo__.py, columnize.py, setup.cfg, setup.py, 614 | test/test-basic.py: Port to 3k 615 | 616 | 2010-10-29 rocky.bernstein 617 | 618 | * __pkginfo__.py, setup.py: VERSION variable was incorrect. git-svn-id: https://pycolumnize.googlecode.com/svn/trunk@33 619 | 220420d0-c99f-11dd-87b6-9d1a99559f42 620 | 621 | 2010-10-28 rocky.bernstein 622 | 623 | * NEWS, VERSION.py, __pkginfo__.py, setup.py, svn2cl_usermap: Get 624 | ready for release git-svn-id: https://pycolumnize.googlecode.com/svn/trunk@32 625 | 220420d0-c99f-11dd-87b6-9d1a99559f42 626 | 627 | 2010-06-15 rocky.bernstein 628 | 629 | * columnize.py: Remove pyflake warning git-svn-id: https://pycolumnize.googlecode.com/svn/trunk@31 630 | 220420d0-c99f-11dd-87b6-9d1a99559f42 631 | 632 | 2010-06-15 rocky.bernstein 633 | 634 | * __pkginfo__.py, columnize.py: Remove reference to GPL3. git-svn-id: https://pycolumnize.googlecode.com/svn/trunk@30 635 | 220420d0-c99f-11dd-87b6-9d1a99559f42 636 | 637 | 2009-06-23 rocky.bernstein 638 | 639 | * LICENSE, __pkginfo__.py: Add PSF2 license. git-svn-id: https://pycolumnize.googlecode.com/svn/trunk@29 640 | 220420d0-c99f-11dd-87b6-9d1a99559f42 641 | 642 | 2009-03-08 rocky.bernstein 643 | 644 | * NEWS, __pkginfo__.py: Get ready fo 0.3.2 release git-svn-id: https://pycolumnize.googlecode.com/svn/trunk@27 645 | 220420d0-c99f-11dd-87b6-9d1a99559f42 646 | 647 | 2009-01-31 rocky.bernstein 648 | 649 | * columnize.py, test/test-basic.py: Relax restriction that array has 650 | to be string. Now is just something we can call str() on each of the 651 | elements on. git-svn-id: https://pycolumnize.googlecode.com/svn/trunk@26 652 | 220420d0-c99f-11dd-87b6-9d1a99559f42 653 | 654 | 2009-01-31 rocky.bernstein 655 | 656 | * columnize.py, test/test-basic.py: Missed align-vertical case. 657 | Really should DRY code. git-svn-id: https://pycolumnize.googlecode.com/svn/trunk@25 658 | 220420d0-c99f-11dd-87b6-9d1a99559f42 659 | 660 | 2009-01-31 rocky.bernstein 661 | 662 | * __pkginfo__.py: Bump version git-svn-id: https://pycolumnize.googlecode.com/svn/trunk@24 663 | 220420d0-c99f-11dd-87b6-9d1a99559f42 664 | 665 | 2009-01-31 rocky.bernstein 666 | 667 | * columnize.py, test/test-basic.py: Add an optional initial line 668 | prefix string git-svn-id: https://pycolumnize.googlecode.com/svn/trunk@23 669 | 220420d0-c99f-11dd-87b6-9d1a99559f42 670 | 671 | 2009-01-10 rocky.bernstein 672 | 673 | * __pkginfo__.py: Ooops forgot version number update git-svn-id: https://pycolumnize.googlecode.com/svn/trunk@21 674 | 220420d0-c99f-11dd-87b6-9d1a99559f42 675 | 676 | 2009-01-10 rocky.bernstein 677 | 678 | * NEWS: get ready for 0.3.1 release git-svn-id: https://pycolumnize.googlecode.com/svn/trunk@19 679 | 220420d0-c99f-11dd-87b6-9d1a99559f42 680 | 681 | 2009-01-10 rocky.bernstein 682 | 683 | * setup.cfg, test/test-basic.py: Some small typos. git-svn-id: https://pycolumnize.googlecode.com/svn/trunk@18 684 | 220420d0-c99f-11dd-87b6-9d1a99559f42 685 | 686 | 2009-01-06 rocky.bernstein 687 | 688 | * NEWS, __pkginfo__.py, columnize.py, test/test-basic.py: Fix those 689 | bad formatting bugs. Add ability to right-justify text in columns. git-svn-id: https://pycolumnize.googlecode.com/svn/trunk@16 690 | 220420d0-c99f-11dd-87b6-9d1a99559f42 691 | 692 | 2009-01-05 rocky.bernstein 693 | 694 | * columnize.py: arrange_vertical is buggy. Start to redo. Not 695 | completely correct - more later. git-svn-id: https://pycolumnize.googlecode.com/svn/trunk@15 696 | 220420d0-c99f-11dd-87b6-9d1a99559f42 697 | 698 | 2009-01-01 rocky.bernstein 699 | 700 | * columnize.py: Doc typo git-svn-id: https://pycolumnize.googlecode.com/svn/trunk@13 701 | 220420d0-c99f-11dd-87b6-9d1a99559f42 702 | 703 | 2009-01-01 rocky.bernstein 704 | 705 | * NEWS, README.txt: Update for 0.2.0 release. git-svn-id: https://pycolumnize.googlecode.com/svn/trunk@11 706 | 220420d0-c99f-11dd-87b6-9d1a99559f42 707 | 708 | 2008-12-31 rocky.bernstein 709 | 710 | * columnize.py, test/Makefile, test/test-basic.py: Remove duplicate 711 | trainling \n from horizontal formatting. git-svn-id: https://pycolumnize.googlecode.com/svn/trunk@10 712 | 220420d0-c99f-11dd-87b6-9d1a99559f42 713 | 714 | 2008-12-31 rocky.bernstein 715 | 716 | * __pkginfo__.py, columnize.py, test/test-basic.py: Allow horizontal 717 | arrangement as well as vertical arrangement git-svn-id: https://pycolumnize.googlecode.com/svn/trunk@9 718 | 220420d0-c99f-11dd-87b6-9d1a99559f42 719 | 720 | 2008-12-16 rocky.bernstein 721 | 722 | * columnize.py: Revert trying to arrange vertically - it's a little 723 | more complicated. This time, for sure\! git-svn-id: https://pycolumnize.googlecode.com/svn/trunk@8 724 | 220420d0-c99f-11dd-87b6-9d1a99559f42 725 | 726 | 2008-12-16 rocky.bernstein 727 | 728 | * columnize.py: Revert trying to arrange vertically - it's a little 729 | more compilcated git-svn-id: https://pycolumnize.googlecode.com/svn/trunk@7 730 | 220420d0-c99f-11dd-87b6-9d1a99559f42 731 | 732 | 2008-12-15 rocky.bernstein 733 | 734 | * columnize.py, test/test-basic.py: Start a horizontally-arranged 735 | version. Buggy. git-svn-id: https://pycolumnize.googlecode.com/svn/trunk@6 736 | 220420d0-c99f-11dd-87b6-9d1a99559f42 737 | 738 | 2008-12-15 rocky.bernstein 739 | 740 | * .gitignore, test/.gitignore: Administrivia - add .gitignore. git-svn-id: https://pycolumnize.googlecode.com/svn/trunk@5 741 | 220420d0-c99f-11dd-87b6-9d1a99559f42 742 | 743 | 2008-12-14 rocky.bernstein 744 | 745 | * __pkginfo__.py, setup.py: Nuke download URL. Was messing up pypi. git-svn-id: https://pycolumnize.googlecode.com/svn/trunk@4 746 | 220420d0-c99f-11dd-87b6-9d1a99559f42 747 | 748 | 2008-12-14 rocky.bernstein 749 | 750 | * __pkginfo__.py: Add web address now that we have one. git-svn-id: https://pycolumnize.googlecode.com/svn/trunk@3 751 | 220420d0-c99f-11dd-87b6-9d1a99559f42 752 | 753 | 2008-12-14 rocky.bernstein 754 | 755 | * Makefile, README.txt, __init__.py, __pkginfo__.py, columnize.py, 756 | setup.cfg, setup.py, test/.cvsignore, test/test-basic.py: Promote 757 | Python's columnize function inside cmd.py to a module. Some small 758 | adjustments have been made. git-svn-id: https://pycolumnize.googlecode.com/svn/trunk@2 759 | 220420d0-c99f-11dd-87b6-9d1a99559f42 760 | 761 | 2008-12-14 (no author) <(no author)@220420d0-c99f-11dd-87b6-9d1a99559f42> 762 | 763 | * Initial directory structure. git-svn-id: https://pycolumnize.googlecode.com/svn/trunk@1 764 | 220420d0-c99f-11dd-87b6-9d1a99559f42 765 | 766 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 R. Bernstein 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include Makefile 2 | include ChangeLog 3 | include README.rst 4 | include NEWS.md 5 | include THANKS 6 | include LICENSE 7 | include __pkginfo__.py 8 | exclude .editorconfig 9 | exclude .coveragerc 10 | exclude .gitignore 11 | exclude .pre-commit-config.yaml 12 | recursive-include columnize *.py 13 | recursive-include test *.py 14 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # Compatibility for us old-timers. 2 | 3 | # Note: This makefile include remake-style target comments. 4 | # These comments before the targets start with #: 5 | # remake --tasks to shows the targets and the comments 6 | 7 | PHONY=check check-full check3 check-short check-short2 check-short3 clean dist distclean test 8 | GIT2CL ?= git2cl 9 | PYTHON ?= python 10 | PYTHON3 ?= python3 11 | RM ?= rm 12 | LINT = flake8 13 | 14 | #: the default target - same as running "check" 15 | all: check 16 | 17 | #: Run tests (one version of Python) 18 | check: 19 | pytest test 20 | 21 | #: Clean up temporary files 22 | clean: 23 | $(PYTHON) ./setup.py $@ 24 | $(RM) *.so */*.so || /bin/true 25 | 26 | #: Create source (tarball) and binary (egg) distribution 27 | dist: README.rst 28 | $(PYTHON) -m build 29 | 30 | #: Create source tarball 31 | sdist: README.rst 32 | $(PYTHON) -m build --sdist 33 | 34 | #: Run mypy 35 | mypy: 36 | mypy columnize 37 | 38 | #: Run mypyc 39 | mypyc: mypy 40 | mypyc columnize 41 | 42 | #: Style check. Set env var LINT to pyflakes, flake, or flake8 43 | lint: flake8 44 | 45 | #: Lint program 46 | flake8: 47 | $(LINT) columnize 48 | 49 | #: Create binary egg distribution 50 | bdist_egg: README.rst 51 | $(PYTHON) ./setup.py bdist_egg 52 | 53 | # It is too much work to figure out how to add a new command to distutils 54 | # to do the following. I'm sure distutils will someday get there. 55 | DISTCLEAN_FILES = build dist *.egg-info *.pyc *.so py*.py 56 | 57 | #: Remove ALL dervied files 58 | distclean: clean 59 | -rm -fr $(DISTCLEAN_FILES) || true 60 | 61 | #: Install package locally 62 | install: 63 | $(PYTHON) ./setup.py install 64 | 65 | #: Same as 'check' target 66 | test: check 67 | 68 | rmChangeLog: 69 | rm ChangeLog || true 70 | 71 | #: Create a ChangeLog from git via git log and git2cl 72 | ChangeLog: rmChangeLog 73 | git log --pretty --numstat --summary | $(GIT2CL) >$@ 74 | 75 | .PHONY: $(PHONY) 76 | -------------------------------------------------------------------------------- /NEWS.md: -------------------------------------------------------------------------------- 1 | 0.3.11 2022-03-11 2 | ================= 3 | 4 | Revise for modern Python project organization and practice: 5 | * store source-code module in a directory 6 | * black files 7 | * use pytest 8 | * use `__version__` for version number 9 | * start using github workflows 10 | * Bundle tests into tarball 11 | 12 | 13 | 0.3.10 2020-04-16 14 | ================= 15 | 16 | Go over portability issues. Is compatible from Python version 2.4..3.8 now 17 | 18 | Use TideLift security and make compliant 19 | 20 | 0.3.9 2016-03-19 21 | ================ 22 | 23 | - Bug fixes 24 | 25 | 0.3.8 2015-01-13 26 | ================= 27 | 28 | - Rerelease for PyPI and its f*cking Rst. 29 | 30 | 0.3.7 2015-01-13 31 | ================= 32 | 33 | - Get terminal size more portably and reliably (Marc Abramowitz) 34 | - More complete test coverage and testing across python versions, and 35 | add an additional demo program (Marc Abramowitz) 36 | - README changes, move to github, 37 | 38 | 0.3.6 2014-22-13 39 | ================ 40 | 41 | - Fix bugs in arrange_array 42 | 43 | 0.3.5 2014-18-13 44 | ================ 45 | 46 | - Reinstate ability to run on older Pythons. In particular Python 47 | 2.4.6 and 2.5.6 now. I suppose other version in between work too. 48 | 49 | - Add opts hash to bundle the growing options old and new: 50 | * arrange_array 51 | * arrange_vertical 52 | * arrange_horizontal 53 | * array_prefix 54 | * array_suffix 55 | * colsep 56 | * colfmt 57 | * displaywidth 58 | * lineprefix 59 | * linesuffix 60 | * ljust 61 | 62 | - Fixes to make source tarball work. (Added test files properly) 63 | 64 | 0.3.4 2013-01-03 65 | ================ 66 | 67 | - Make 3k tolerant. This means it no longer works for versions less 68 | than Python 2.6. 69 | 70 | 0.3.3 2010-28-10 71 | ================ 72 | 73 | - Work on packaging 74 | - Remove pyflakes warnings 75 | - Correct licensing information 76 | 77 | 0.3.2 2009-03-08 - Ron Frankel -1 Release 78 | ========================================= 79 | 80 | 81 | - Relax restriction that array has to be string. Now is just something 82 | we can call str() on each of the elements on. 83 | 84 | - Correct bug in vertical alignment 85 | 86 | - Add an optional initial line prefix string 87 | 88 | 0.3.1 2009-01-10 - Sam Woodward Release 89 | ========================================= 90 | 91 | - Some small typos fixed. 92 | 93 | 0.3.0 2009-01-05 94 | ================ 95 | 96 | 97 | - 0.2.0 had bad bugs - don't use. 98 | Allow specifying right justification as well as left justification 99 | 100 | 0.2.0 2008-12-31 101 | ================ 102 | 103 | - Add ability to run columns vertically 104 | -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | |Pypi Installs| |Supported Python Versions| 2 | 3 | |packagestatus| 4 | 5 | In showing a long lists, sometimes one would prefer to see the value 6 | arranged aligned in columns. Some examples include listing methods of an 7 | object, listing debugger commands, or showing a numeric array with data 8 | aligned. 9 | 10 | This is a Python module to format a simple (i.e. not nested) list into 11 | aligned columns. A string with embedded newline characters is returned. 12 | 13 | Setup 14 | ----- 15 | 16 | .. code:: python 17 | 18 | $ python 19 | >>> import columnize 20 | 21 | With String data 22 | ---------------- 23 | 24 | Each column is only as wide as necessary. By default, columns are 25 | separated by two spaces; one was not legible enough. Set *colsep* to 26 | adjust the string separate columns. Set *displaywidth* to set the line 27 | width. 28 | 29 | .. code:: python 30 | 31 | >>> g = ('bibrons', 'golden', 'madascar', 'leopard', 'mourning', 'suras', 'tokay') 32 | >>> print(columnize.columnize(g, displaywidth=15)) 33 | bibrons suras 34 | golden tokay 35 | madascar 36 | leopard 37 | mourning 38 | 39 | >>> print(columnize.columnize(g, displaywidth=19, colsep=' | ')) 40 | bibrons | mourning 41 | golden | suras 42 | madascar | tokay 43 | leopard 44 | 45 | >>> print(columnize.columnize(g, displaywidth=18, colsep=' | ', ljust=False)) 46 | bibrons | suras 47 | golden | tokay 48 | madascar 49 | leopard 50 | 51 | Normally, consecutive items go down from the top to bottom from the 52 | left-most column to the right-most. If *arrange\_vertical* is set false, 53 | consecutive items will go across, left to right, top to bottom. 54 | 55 | With numeric data 56 | ----------------- 57 | 58 | .. code:: python 59 | 60 | >>> print(columnize.columnize(['1', '2', '3', '4'], displaywidth=6)) # => '1 3\n2 4\n' 61 | 1 3 62 | 2 4 63 | 64 | >>> print(columnize.columnize(list(range(1,6)), displaywidth=8)) 65 | 1 3 5 66 | 2 4 67 | 68 | By default entries are left justified: 69 | 70 | .. code:: python 71 | 72 | >>> print(columnize.columnize(list(range(1,16)), displaywidth=10)) 73 | 74 | 1 6 11 75 | 2 7 12 76 | 3 8 13 77 | 4 9 14 78 | 5 10 15 79 | 80 | but you can change that with *ljust* or if *arrange\_array* is set to 81 | *True*: 82 | 83 | .. code:: python 84 | 85 | >>> print(columnize.columnize(list(range(1,16)), displaywidth=10, ljust=False)) 86 | 1 6 11 87 | 2 7 12 88 | 3 8 13 89 | 4 9 14 90 | 5 10 15 91 | 92 | >>> print(columnize.columnize(list(range(1,5)), opts={'arrange_array':True, 'displaywidth':6})) 93 | [1, 2 94 | 3, 4] 95 | 96 | Credits 97 | ------- 98 | 99 | This module (essentially one function) was adapted from a private method 100 | of the same name from Python's 101 | `cmd `__ module. Some 102 | adjustments and generalizations have been made. 103 | 104 | pycolumnize for enterprise 105 | ========================== 106 | 107 | Available as part of the Tidelift Subscription. 108 | 109 | The maintainers of pycolumnize and thousands of other packages are working with Tidelift to deliver commercial support and maintenance for the open source dependencies you use to build your applications. Save time, reduce risk, and improve code health, while paying the maintainers of the exact dependencies you use. `Learn more. `_ 110 | 111 | Security contact information 112 | ============================ 113 | 114 | To report a security vulnerability, please use the `Tidelift security contact `_ and Tidelift will coordinate the fix and disclosure. 115 | 116 | Other stuff 117 | ----------- 118 | 119 | Authors: Rocky Bernstein rb@dustyfeet.com 120 | 121 | License: MIT 122 | 123 | .. |Supported Python Versions| image:: https://img.shields.io/pypi/pyversions/columnize.svg 124 | :target: https://pypi.python.org/pypi/columnize/ 125 | .. |Pypi Installs| image:: https://pepy.tech/badge/columnize 126 | .. |packagestatus| image:: https://repology.org/badge/vertical-allrepos/python:columnize.svg 127 | :target: https://repology.org/project/python:columnize/versions 128 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Supported Versions 4 | 5 | | Version | Supported | 6 | | ------- | ------------------ | 7 | | 0.9.0 | :white_check_mark: | 8 | 9 | 10 | ## Reporting a Vulnerability 11 | 12 | We are using the [Tidelift security policy](https://tidelift.com/docs/security) which contains information on how to report vulnerabilites. 13 | -------------------------------------------------------------------------------- /THANKS: -------------------------------------------------------------------------------- 1 | Tyler Bindon (martica) - bug fixes 2 | Blaine Bublitz (phated) - Tidelift-ification 3 | -------------------------------------------------------------------------------- /__pkginfo__.py: -------------------------------------------------------------------------------- 1 | """packaging information""" 2 | 3 | import os.path as osp 4 | 5 | # Things that change more often go here. 6 | pkg_copyright = """ 7 | Copyright (C) 2008-2010, 2013, 2015, 2020, 2022-2024 Rocky Bernstein . 8 | """ 9 | classifiers = [ 10 | "Development Status :: 5 - Production/Stable", 11 | "Intended Audience :: Developers", 12 | "License :: OSI Approved :: MIT License", 13 | "Programming Language :: Python", 14 | "Topic :: Software Development :: Libraries :: Python Modules", 15 | "Programming Language :: Python :: 2.4", 16 | "Programming Language :: Python :: 2.5", 17 | "Programming Language :: Python :: 2.6", 18 | "Programming Language :: Python :: 2.7", 19 | "Programming Language :: Python :: 3.1", 20 | "Programming Language :: Python :: 3.2", 21 | "Programming Language :: Python :: 3.3", 22 | "Programming Language :: Python :: 3.4", 23 | "Programming Language :: Python :: 3.5", 24 | "Programming Language :: Python :: 3.6", 25 | "Programming Language :: Python :: 3.7", 26 | "Programming Language :: Python :: 3.8", 27 | "Programming Language :: Python :: 3.9", 28 | "Programming Language :: Python :: 3.10", 29 | "Programming Language :: Python :: 3.11", 30 | "Programming Language :: Python :: 3.12 ", 31 | "Programming Language :: Python :: 3.13 ", 32 | ] 33 | 34 | 35 | def get_srcdir(): 36 | filename = osp.normcase(osp.dirname(osp.abspath(__file__))) 37 | return osp.realpath(filename) 38 | 39 | 40 | def read(*rnames): 41 | return open(osp.join(get_srcdir(), *rnames)).read() 42 | 43 | 44 | exec(read("columnize/version.py")) 45 | 46 | # The rest in alphabetic order 47 | author = "Rocky Bernstein" 48 | author_email = "rocky@gnu.org" 49 | pkg_license = "MIT" 50 | modname = "columnize" 51 | 52 | short_desc = "Format a simple (i.e. not nested) list into aligned columns." 53 | py_modules = [modname] 54 | test_requires = ["pytest"] 55 | web = "https://github.com/rocky/pycolumnize" 56 | 57 | readme = "README.txt" 58 | if osp.exists("README.rst"): 59 | readme = "README.rst" 60 | long_description = read(readme) + "\n" 61 | -------------------------------------------------------------------------------- /admin-tools/check-2.4-2.7-versions.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | function finish { 3 | cd $owd 4 | } 5 | owd=$(pwd) 6 | trap finish EXIT 7 | 8 | cd $(dirname ${BASH_SOURCE[0]}) 9 | if ! source ./pyenv-2.4-2.7-versions ; then 10 | exit $? 11 | fi 12 | if ! source ./setup-python-2.4.sh ; then 13 | exit $? 14 | fi 15 | 16 | cd .. 17 | for version in $PYVERSIONS; do 18 | if ! pyenv local $version ; then 19 | exit $? 20 | fi 21 | make clean && python setup.py develop 22 | if ! make check ; then 23 | exit $? 24 | fi 25 | echo === $version === 26 | done 27 | -------------------------------------------------------------------------------- /admin-tools/check-3.0-3.2-versions.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | check_pycolumnize_30_owd=$(pwd) 4 | 5 | cd $(dirname ${BASH_SOURCE[0]}) 6 | if ! source ./pyenv-3.0-3.2-versions ; then 7 | exit $? 8 | fi 9 | if ! source ./setup-python-3.0.sh ; then 10 | exit $? 11 | fi 12 | cd .. 13 | for version in $PYVERSIONS; do 14 | echo --- $version --- 15 | if ! pyenv local $version ; then 16 | exit $? 17 | fi 18 | make clean && pip install -e . 19 | if ! make check; then 20 | exit $? 21 | fi 22 | echo === $version === 23 | done 24 | cd $check_pycolumnize_30_owd 25 | -------------------------------------------------------------------------------- /admin-tools/check-3.3-3.5-versions.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | check_pycolumnize_33_owd=$(pwd) 4 | 5 | cd $(dirname ${BASH_SOURCE[0]}) 6 | if ! source ./pyenv-3.3-3.5-versions ; then 7 | exit $? 8 | fi 9 | if ! source ./setup-python-3.3.sh ; then 10 | exit $? 11 | fi 12 | cd .. 13 | for version in $PYVERSIONS; do 14 | echo --- $version --- 15 | if ! pyenv local $version ; then 16 | exit $? 17 | fi 18 | make clean && pip install -e . 19 | if ! make check; then 20 | exit $? 21 | fi 22 | echo === $version === 23 | done 24 | cd $check_pycolumnize_33_owd 25 | -------------------------------------------------------------------------------- /admin-tools/check-3.6-3.10-versions.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | check_pytracer_36_owd=$(pwd) 4 | 5 | cd $(dirname ${BASH_SOURCE[0]}) 6 | if ! source ./pyenv-3.6-3.10-versions ; then 7 | exit $? 8 | fi 9 | if ! source ./setup-python-3.6.sh ; then 10 | exit $? 11 | fi 12 | cd .. 13 | for version in $PYVERSIONS; do 14 | echo --- $version --- 15 | if ! pyenv local $version ; then 16 | exit $? 17 | fi 18 | make clean && pip install -e . 19 | if ! make check; then 20 | exit $? 21 | fi 22 | echo === $version === 23 | done 24 | cd $check_pytracer_36_owd 25 | -------------------------------------------------------------------------------- /admin-tools/check-newest-versions.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | function finish { 3 | cd $pycolumnize_owd 4 | } 5 | 6 | # FIXME put some of the below in a common routine 7 | pycolumnize_owd=$(pwd) 8 | trap finish EXIT 9 | 10 | cd $(dirname ${BASH_SOURCE[0]}) 11 | if ! source ./pyenv-newest-versions ; then 12 | exit $? 13 | fi 14 | if ! source ./setup-master.sh ; then 15 | exit $? 16 | fi 17 | cd .. 18 | for version in $PYVERSIONS; do 19 | echo --- $version --- 20 | if ! pyenv local $version ; then 21 | exit $? 22 | fi 23 | make clean && pip install -e . 24 | if ! make check; then 25 | exit $? 26 | fi 27 | echo === $version === 28 | done 29 | -------------------------------------------------------------------------------- /admin-tools/check-versions.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | function finish { 3 | cd $owd 4 | } 5 | 6 | # FIXME put some of the below in a common routine 7 | owd=$(pwd) 8 | trap finish EXIT 9 | 10 | cd $(dirname ${BASH_SOURCE[0]}) 11 | if ! source ./pyenv-versions ; then 12 | exit $? 13 | fi 14 | cd .. 15 | for version in $PYVERSIONS; do 16 | echo --- $version --- 17 | if ! pyenv local $version ; then 18 | exit $? 19 | fi 20 | make clean && pip install -e . 21 | if ! make check-short; then 22 | exit $? 23 | fi 24 | echo === $version === 25 | done 26 | -------------------------------------------------------------------------------- /admin-tools/checkout_common.sh: -------------------------------------------------------------------------------- 1 | # Common checkout routine 2 | export PATH=$HOME/.pyenv/bin/pyenv:$PATH 3 | bs=${BASH_SOURCE[0]} 4 | mydir=$(dirname $bs) 5 | fulldir=$(readlink -f $mydir) 6 | 7 | function setup_version { 8 | local repo=$1 9 | version=$2 10 | echo Running setup $version on $repo ... 11 | (cd ../$repo && . ./admin-tools/setup-${version}.sh) 12 | return $? 13 | } 14 | 15 | function checkout_finish { 16 | branch=$1 17 | cd $pytracer_owd 18 | git checkout $branch && pyenv local $PYTHON_VERSION && git pull 19 | rc=$? 20 | return $rc 21 | } 22 | -------------------------------------------------------------------------------- /admin-tools/make-dist-2.4-2.7.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | PACKAGE=columnize 3 | 4 | # FIXME put some of the below in a common routine 5 | function finish { 6 | cd $owd 7 | } 8 | owd=$(pwd) 9 | trap finish EXIT 10 | 11 | cd $(dirname ${BASH_SOURCE[0]}) 12 | if ! source ./pyenv-2.4-2.7-versions ; then 13 | exit $? 14 | fi 15 | if ! source ./setup-python-2.4.sh ; then 16 | exit $? 17 | fi 18 | 19 | cd .. 20 | source $PACKAGE/version.py 21 | echo $__version__ 22 | 23 | for pyversion in $PYVERSIONS; do 24 | if ! pyenv local $pyversion ; then 25 | exit $? 26 | fi 27 | 28 | rm -fr build 29 | python setup.py bdist_egg 30 | echo === $pyversion === 31 | done 32 | 33 | echo "--- python 2.7 wheel ---" 34 | pyenv local 2.7.18 35 | python setup.py bdist_wheel 36 | echo === $pyversion === 37 | 38 | 39 | # Pypi can only have one source tarball. 40 | # Tarballs can get created from the above setup, so make sure to remove them since we want 41 | # the tarball from master. 42 | 43 | python ./setup.py sdist 44 | tarball=dist/${PACKAGE}-${__version__}.tar.gz 45 | if [[ -f $tarball ]]; then 46 | mv -v $tarball dist/${PACKAGE}_24-${__version__}.tar.gz 47 | fi 48 | -------------------------------------------------------------------------------- /admin-tools/make-dist-3.0-3.5.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | PACKAGE=columnize 3 | 4 | # FIXME put some of the below in a common routine 5 | function finish { 6 | cd $owd 7 | } 8 | 9 | cd $(dirname ${BASH_SOURCE[0]}) 10 | owd=$(pwd) 11 | trap finish EXIT 12 | 13 | if ! source ./pyenv-3.0-3.5-versions ; then 14 | exit $? 15 | fi 16 | if ! source ./setup-python-3.0.sh ; then 17 | exit $? 18 | fi 19 | 20 | cd .. 21 | source $PACKAGE/version.py 22 | echo $VERSION 23 | 24 | for pyversion in $PYVERSIONS; do 25 | echo --- $pyversion --- 26 | if ! pyenv local $pyversion ; then 27 | exit $? 28 | fi 29 | # pip bdist_egg create too-general wheels. So 30 | # we narrow that by moving the generated wheel. 31 | 32 | # Pick out first two number of version, e.g. 3.5.1 -> 35 33 | first_two=$(echo $pyversion | cut -d'.' -f 1-2 | sed -e 's/\.//') 34 | rm -fr build 35 | python setup.py bdist_egg bdist_wheel 36 | mv -v dist/${PACKAGE}-$VERSION-{py3,py$first_two}-none-any.whl 37 | echo === $pyversion === 38 | done 39 | -------------------------------------------------------------------------------- /admin-tools/make-dist-newer.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | PACKAGE=columnize 3 | 4 | # FIXME put some of the below in a common routine 5 | function finish { 6 | cd $owd 7 | } 8 | 9 | cd $(dirname ${BASH_SOURCE[0]}) 10 | owd=$(pwd) 11 | trap finish EXIT 12 | 13 | if ! source ./pyenv-newest-versions ; then 14 | exit $? 15 | fi 16 | if ! source ./setup-master.sh ; then 17 | exit $? 18 | fi 19 | 20 | cd .. 21 | source $PACKAGE/version.py 22 | echo $__version__ 23 | 24 | for pyversion in $PYVERSIONS; do 25 | echo --- $pyversion --- 26 | if ! pyenv local $pyversion ; then 27 | exit $? 28 | fi 29 | # pip bdist_egg create too-general wheels. So 30 | # we narrow that by moving the generated wheel. 31 | 32 | # Pick out first two numbers of version, e.g. 3.5.1 -> 35 33 | first_two=$(echo $pyversion | cut -d'.' -f 1-2 | sed -e 's/\.//') 34 | rm -fr build 35 | python setup.py bdist_egg 36 | if [[ $first_two =~ py* ]]; then 37 | continue 38 | else 39 | mv -v dist/${PACKAGE}-$__version__-{py3,py$first_two}-none-any.whl 40 | fi 41 | echo === $pyversion === 42 | done 43 | 44 | python ./setup.py sdist bdist_wheel 45 | -------------------------------------------------------------------------------- /admin-tools/make-dist.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | PACKAGE=columnize 3 | 4 | # FIXME put some of the below in a common routine 5 | function finish { 6 | cd $owd 7 | } 8 | 9 | cd $(dirname ${BASH_SOURCE[0]}) 10 | owd=$(pwd) 11 | trap finish EXIT 12 | 13 | if ! source ./pyenv-versions ; then 14 | exit $? 15 | fi 16 | 17 | cd .. 18 | source ./VERSION.py 19 | echo $VERSION 20 | 21 | for pyversion in $PYVERSIONS; do 22 | echo --- $pyversion --- 23 | if ! pyenv local $pyversion ; then 24 | exit $? 25 | fi 26 | # pip bdist_egg create too-general wheels. So 27 | # we narrow that by moving the generated wheel. 28 | 29 | # Pick out first two number of version, e.g. 3.5.1 -> 35 30 | first_two=$(echo $pyversion | cut -d'.' -f 1-2 | sed -e 's/\.//') 31 | rm -fr build 32 | if (( first_two >= 26 )) && (( first_two != 31 )); then 33 | python setup.py bdist_egg bdist_wheel 34 | mv -v dist/${PACKAGE}-$VERSION-{py2.py3,py$first_two}-none-any.whl 35 | else 36 | python setup.py bdist_egg 37 | fi 38 | 39 | echo === $pyversion === 40 | done 41 | 42 | python ./setup.py sdist 43 | -------------------------------------------------------------------------------- /admin-tools/merge-for-2.4.sh: -------------------------------------------------------------------------------- 1 | #/bin/bash 2 | pycolumnize_merge_24_owd=$(pwd) 3 | PYTHON_VERSION=2.4 4 | pyenv local $PYTHON_VERSION 5 | cd $(dirname ${BASH_SOURCE[0]}) 6 | if . ./setup-python-2.4.sh; then 7 | git merge python-3.0-to-3.2 8 | fi 9 | cd $pycolumnize_merge_24_owd 10 | -------------------------------------------------------------------------------- /admin-tools/merge-for-3.0.sh: -------------------------------------------------------------------------------- 1 | #/bin/bash 2 | pycolumnize_merge_30_owd=$(pwd) 3 | PYTHON_VERSION=3.0 4 | pyenv local $PYTHON_VERSION 5 | cd $(dirname ${BASH_SOURCE[0]}) 6 | if . ./setup-python-3.0.sh; then 7 | git merge python-3.3-to-3.5 8 | fi 9 | cd $pycolumnize_merge_30_owd 10 | -------------------------------------------------------------------------------- /admin-tools/merge-for-3.3.sh: -------------------------------------------------------------------------------- 1 | #/bin/bash 2 | pycolumnize_merge_33_owd=$(pwd) 3 | PYTHON_VERSION=3.3 4 | pyenv local $PYTHON_VERSION 5 | cd $(dirname ${BASH_SOURCE[0]}) 6 | if . ./setup-python-3.3.sh; then 7 | git merge python-3.6-to-3.10 8 | fi 9 | cd $pycolumnize_merge_33_owd 10 | -------------------------------------------------------------------------------- /admin-tools/merge-for-3.6.sh: -------------------------------------------------------------------------------- 1 | #/bin/bash 2 | pycolumnize_merge_36_owd=$(pwd) 3 | PYTHON_VERSION=3.6 4 | pyenv local $PYTHON_VERSION 5 | cd $(dirname ${BASH_SOURCE[0]}) 6 | if . ./setup-python-3.6.sh; then 7 | git merge master 8 | fi 9 | cd $pycolumnize_merge_36_owd 10 | -------------------------------------------------------------------------------- /admin-tools/pyenv-2.4-2.7-versions: -------------------------------------------------------------------------------- 1 | # -*- shell-script -*- 2 | # Sets PYVERSIONS to be pyenv versions that 3 | # we can use in the python-2.4-to-2.7 branch. 4 | 5 | if [[ $0 == ${BASH_SOURCE[0]} ]] ; then 6 | echo "This script should be *sourced* rather than run directly through bash" 7 | exit 1 8 | fi 9 | export PYVERSIONS='2.4.6 2.5.6 2.6.9 2.7.18' 10 | -------------------------------------------------------------------------------- /admin-tools/pyenv-3.0-3.2-versions: -------------------------------------------------------------------------------- 1 | # -*- shell-script -*- 2 | # Sets PYVERSIONS to be pyenv versions that 3 | # we can use in the python-3.1-to-3.2 branch. 4 | 5 | if [[ $0 == ${BASH_SOURCE[0]} ]] ; then 6 | echo "This script should be *sourced* rather than run directly through bash" 7 | exit 1 8 | fi 9 | export PYVERSIONS='3.0 3.1 3.2' 10 | -------------------------------------------------------------------------------- /admin-tools/pyenv-3.3-3.5-versions: -------------------------------------------------------------------------------- 1 | # -*- shell-script -*- 2 | # Sets PYVERSIONS to be pyenv versions that 3 | # we can use in the master 4 | 5 | if [[ $0 == ${BASH_SOURCE[0]} ]] ; then 6 | echo "This script should be *sourced* rather than run directly through bash" 7 | exit 1 8 | fi 9 | 10 | export PYVERSIONS='3.5 3.3 3.4' 11 | -------------------------------------------------------------------------------- /admin-tools/pyenv-3.6-3.10-versions: -------------------------------------------------------------------------------- 1 | # -*- shell-script -*- 2 | # Sets PYVERSIONS to be pyenv versions that 3 | # we can use in the master 4 | 5 | if [[ $0 == ${BASH_SOURCE[0]} ]] ; then 6 | echo "This script should be *sourced* rather than run directly through bash" 7 | exit 1 8 | fi 9 | 10 | export PYVERSIONS='3.6 pypy3.6 3.7 pypy3.7 pypy3.8 pypy3.9 pyston-2.3.5 3.8 3.9 3.10' 11 | -------------------------------------------------------------------------------- /admin-tools/pyenv-newest-versions: -------------------------------------------------------------------------------- 1 | # -*- shell-script -*- 2 | # Sets PYVERSIONS to be pyenv versions that 3 | # we can use in the master 4 | 5 | if [[ $0 == ${BASH_SOURCE[0]} ]] ; then 6 | echo "This script should be *sourced* rather than run directly through bash" 7 | exit 1 8 | fi 9 | 10 | export PYVERSIONS='3.11 3.12 3.13' 11 | -------------------------------------------------------------------------------- /admin-tools/setup-master.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | PYTHON_VERSION=3.6.15 3 | pyenv local $PYTHON_VERSION 4 | 5 | if [[ $0 == $${BASH_SOURCE[0]} ]] ; then 6 | echo "This script should be *sourced* rather than run directly through bash" 7 | exit 1 8 | fi 9 | 10 | git checkout master && git pull && pyenv local $PYTHON_VERSION 11 | -------------------------------------------------------------------------------- /admin-tools/setup-python-2.4.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | PYTHON_VERSION=2.4.6 3 | 4 | if [[ $0 == $${BASH_SOURCE[0]} ]] ; then 5 | echo "This script should be *sourced* rather than run directly through bash" 6 | exit 1 7 | fi 8 | 9 | git checkout python-2.4-to-2.7 && git pull && pyenv local $PYTHON_VERSION 10 | -------------------------------------------------------------------------------- /admin-tools/setup-python-3.0.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | PYTHON_VERSION=3.0 3 | 4 | if [[ $0 == $${BASH_SOURCE[0]} ]] ; then 5 | echo "This script should be *sourced* rather than run directly through bash" 6 | exit 1 7 | fi 8 | 9 | git checkout python-3.0-to-3.2 && git pull && pyenv local $PYTHON_VERSION 10 | -------------------------------------------------------------------------------- /admin-tools/setup-python-3.3.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Check out 3.3-to-3.5 branch and dependant development branches 3 | 4 | bs=${BASH_SOURCE[0]} 5 | if [[ $0 == $bs ]] ; then 6 | echo "This script should be *sourced* rather than run directly through bash" 7 | exit 1 8 | fi 9 | 10 | PYTHON_VERSION=3.3 11 | 12 | export PATH=$HOME/.pyenv/bin/pyenv:$PATH 13 | pytracer_owd=$(pwd) 14 | mydir=$(dirname $bs) 15 | cd $mydir 16 | . ./checkout_common.sh 17 | (cd $fulldir/.. && \ 18 | setup_version python-spark python-3.3 && \ 19 | setup_version python-xdis python-3.3 && \ 20 | setup_version python-filecache python-3.3 && \ 21 | setup_version pycolumnize python-3.0 && \ 22 | setup_version python-uncompyle6 python-3.3 \ 23 | ) 24 | cd $pytracer_owd 25 | rm -v */.python-version 2>/dev/null || true 26 | 27 | checkout_finish python-3.3-to-3.5 28 | -------------------------------------------------------------------------------- /admin-tools/setup-python-3.6.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Check out 3.6-to-3.10 branch and dependant development branches 3 | 4 | bs=${BASH_SOURCE[0]} 5 | if [[ $0 == $bs ]] ; then 6 | echo "This script should be *sourced* rather than run directly through bash" 7 | exit 1 8 | fi 9 | 10 | PYTHON_VERSION=3.6 11 | 12 | export PATH=$HOME/.pyenv/bin/pyenv:$PATH 13 | pytracer_owd=$(pwd) 14 | mydir=$(dirname $bs) 15 | cd $mydir 16 | . ./checkout_common.sh 17 | (cd $fulldir/.. && \ 18 | setup_version python-uncompyle6 master && \ 19 | setup_version python-filecache master && \ 20 | setup_version pycolumnize master && \ 21 | setup_version python-xdis python-3.6 \ 22 | ) 23 | 24 | checkout_finish python-3.6-to-3.10 25 | -------------------------------------------------------------------------------- /columnize/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Copyright (C) 2022-2023 Rocky Bernstein 3 | # This program is free software: you can redistribute it and/or modify 4 | # it under the terms of the GNU General Public License as published by 5 | # the Free Software Foundation, either version 3 of the License, or 6 | # (at your option) any later version. 7 | # 8 | # This program is distributed in the hope that it will be useful, 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | # GNU General Public License for more details. 12 | # 13 | # You should have received a copy of the GNU General Public License 14 | # along with this program. If not, see . 15 | r""" 16 | |Downloads| |Build Status| |Latest Version| |Supported Python versions| 17 | 18 | In showing a long lists, sometimes one would prefer to see the value 19 | arranged aligned in columns. Some examples include listing methods of an 20 | object, listing debugger commands, or showing a numeric array with data 21 | aligned. 22 | 23 | This is a Python module to format a simple (i.e. not nested) list into 24 | aligned columns. A string with embedded newline characters is returned. 25 | 26 | Setup 27 | ----- 28 | 29 | .. code:: python 30 | 31 | $ python 32 | >>> import columnize 33 | 34 | With String data 35 | ---------------- 36 | 37 | Each column is only as wide as necessary. By default, columns are 38 | separated by two spaces; one was not legible enough. Set *colsep* to 39 | adjust the string separate columns. Set *displaywidth* to set the line 40 | width. 41 | 42 | .. code:: python 43 | 44 | >>> g = ('bibrons', 'golden', 'madascar', 'leopard', 'mourning', 'suras', 'tokay') 45 | >>> print(columnize.columnize(g, displaywidth=15)) 46 | bibrons suras 47 | golden tokay 48 | madascar 49 | leopard 50 | mourning 51 | 52 | >>> print(columnize.columnize(g, displaywidth=19, colsep=' | ')) 53 | bibrons | mourning 54 | golden | suras 55 | madascar | tokay 56 | leopard 57 | 58 | >>> print(columnize.columnize(g, displaywidth=18, colsep=' | ', ljust=False)) 59 | bibrons | suras 60 | golden | tokay 61 | madascar 62 | leopard 63 | 64 | Normally, consecutive items go down from the top to bottom from the 65 | left-most column to the right-most. If *arrange\_vertical* is set false, 66 | consecutive items will go across, left to right, top to bottom. 67 | 68 | With numeric data 69 | ----------------- 70 | 71 | .. code:: python 72 | 73 | >>> print(columnize.columnize(['1', '2', '3', '4'], displaywidth=6)) # => '1 3\n2 4\n' 74 | 1 3 75 | 2 4 76 | 77 | >>> print(columnize.columnize(list(range(1,6)), displaywidth=8)) 78 | 1 3 5 79 | 2 4 80 | 81 | By default entries are left justified: 82 | 83 | .. code:: python 84 | 85 | >>> print(columnize.columnize(list(range(1,16)), displaywidth=10)) 86 | 87 | 1 6 11 88 | 2 7 12 89 | 3 8 13 90 | 4 9 14 91 | 5 10 15 92 | 93 | but you can change that with *ljust* or if *arrange\_array* is set to 94 | *True*: 95 | 96 | .. code:: python 97 | 98 | >>> print(columnize.columnize(list(range(1,16)), displaywidth=10, ljust=False)) 99 | 1 6 11 100 | 2 7 12 101 | 3 8 13 102 | 4 9 14 103 | 5 10 15 104 | 105 | >>> print(columnize.columnize(list(range(1,5)), opts={'arrange_array':True, 'displaywidth':6})) 106 | [1, 2 107 | 3, 4] 108 | 109 | Credits 110 | ------- 111 | 112 | This module (essentially one function) was adapted from a private method 113 | of the same name from Python s 114 | `cmd `__ module. Some 115 | adjustments and generalizations have been made. 116 | 117 | Other stuff 118 | ----------- 119 | 120 | Authors: Rocky Bernstein rb@dustyfeet.com 121 | 122 | License: MIT 123 | 124 | .. |Downloads| image:: https://pypip.in/download/columnize/badge.svg 125 | .. |Build Status| image:: https://travis-ci.org/rocky/pycolumnize.svg 126 | :target: https://travis-ci.org/rocky/pycolumnize/ 127 | .. |Latest Version| image:: https://pypip.in/version/columnize/badge.svg?text=version 128 | :target: https://pypi.python.org/pypi/columnize/ 129 | .. |Supported Python versions| image:: https://pypip.in/py_versions/columnize/badge.svg 130 | :target: https://pypi.python.org/pypi/columnize/ 131 | 132 | """ 133 | __docformat__ = "restructuredtext" 134 | from columnize.__main__ import columnize, computed_displaywidth # noqa 135 | from columnize.version import __version__ # noqa 136 | 137 | __all__ = ["__version__", "columnize", "computed_displaywidth"] 138 | -------------------------------------------------------------------------------- /columnize/__main__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """Return compact set of columns as a string with newlines for an 3 | array of strings. 4 | 5 | Adapted from the routine of the same name inside cmd.py""" 6 | 7 | import os 8 | 9 | # Python >= 3.3 10 | # older Python's use 11 | # from backports.shutil_get_terminal_size import get_terminal_size 12 | from shutil import get_terminal_size 13 | 14 | DEFAULT_WIDTH = 80 15 | 16 | 17 | def computed_displaywidth(): 18 | """Figure out a reasonable default with. Use os.environ['COLUMNS'] if possible, 19 | and failing that use 80. 20 | """ 21 | try: 22 | width = int(os.environ["COLUMNS"]) 23 | except (KeyError, ValueError): 24 | try: 25 | width = get_terminal_size().columns 26 | except: # noqa 27 | width = DEFAULT_WIDTH 28 | 29 | return width or DEFAULT_WIDTH 30 | 31 | 32 | default_opts = { 33 | "arrange_array": False, # Check if file has changed since last time 34 | "arrange_vertical": True, 35 | "array_prefix": "", 36 | "array_suffix": "", 37 | "colfmt": None, 38 | "colsep": " ", 39 | "displaywidth": computed_displaywidth(), 40 | "lineprefix": "", 41 | "linesuffix": "\n", 42 | "ljust": None, 43 | "term_adjust": False, 44 | } 45 | 46 | 47 | def get_option(key, options): 48 | return options.get(key, default_opts.get(key)) 49 | 50 | 51 | def columnize( 52 | array, 53 | displaywidth=80, 54 | colsep=" ", 55 | arrange_vertical=True, 56 | ljust=True, 57 | lineprefix="", 58 | opts=None, 59 | ): 60 | """Return a list of strings as a compact set of columns arranged 61 | horizontally or vertically. 62 | 63 | For example, for a line width of 4 characters (arranged vertically): 64 | ['1', '2,', '3', '4'] => '1 3\n2 4\n' 65 | 66 | or arranged horizontally: 67 | ['1', '2,', '3', '4'] => '1 2\n3 4\n' 68 | 69 | Each column is only as wide as necessary. By default, columns are 70 | separated by two spaces - one was not legible enough. Set "colsep" 71 | to adjust the string separate columns. Set `displaywidth' to set 72 | the line width. 73 | 74 | Normally, consecutive items go down from the top to bottom from 75 | the left-most column to the right-most. If "arrange_vertical" is 76 | set false, consecutive items will go across, left to right, top to 77 | bottom.""" 78 | if opts is None: 79 | opts = {} 80 | if not isinstance(array, (list, tuple)): 81 | raise TypeError(("array needs to be an instance of a list or a tuple")) 82 | 83 | o = {} 84 | if len(opts.keys()) > 0: 85 | for key in default_opts.keys(): 86 | o[key] = get_option(key, opts) 87 | pass 88 | if o["arrange_array"]: 89 | o["array_prefix"] = "[" 90 | o["lineprefix"] = " " 91 | o["linesuffix"] = ",\n" 92 | o["array_suffix"] = "]\n" 93 | o["colsep"] = ", " 94 | o["arrange_vertical"] = False 95 | pass 96 | 97 | else: 98 | o = default_opts.copy() 99 | o["displaywidth"] = displaywidth 100 | o["colsep"] = colsep 101 | o["arrange_vertical"] = arrange_vertical 102 | o["ljust"] = ljust 103 | o["lineprefix"] = lineprefix 104 | pass 105 | 106 | # if o['ljust'] is None: 107 | # o['ljust'] = !(list.all?{|datum| datum.kind_of?(Numeric)}) 108 | # pass 109 | 110 | if o["colfmt"]: 111 | array = [(o["colfmt"] % i) for i in array] 112 | else: 113 | array = [str(i) for i in array] 114 | pass 115 | 116 | # Some degenerate cases 117 | size = len(array) 118 | if 0 == size: 119 | return "\n" 120 | elif size == 1: 121 | return "%s%s%s\n" % (o["array_prefix"], str(array[0]), o["array_suffix"]) 122 | 123 | o["displaywidth"] = max(4, o["displaywidth"] - len(o["lineprefix"])) 124 | if o["arrange_vertical"]: 125 | array_index = lambda nrows, row, col: nrows * col + row 126 | # Try every row count from 1 upwards 127 | for nrows in range(1, size + 1): 128 | ncols = (size + nrows - 1) // nrows 129 | colwidths = [] 130 | totwidth = -len(o["colsep"]) 131 | for col in range(ncols): 132 | # get max column width for this column 133 | colwidth = 0 134 | for row in range(nrows): 135 | i = array_index(nrows, row, col) 136 | if i >= size: 137 | break 138 | x = array[i] 139 | colwidth = max(colwidth, len(x)) 140 | pass 141 | colwidths.append(colwidth) 142 | totwidth += colwidth + len(o["colsep"]) 143 | if totwidth > o["displaywidth"]: 144 | break 145 | pass 146 | if totwidth <= o["displaywidth"]: 147 | break 148 | pass 149 | # The smallest number of rows computed and the 150 | # max widths for each column has been obtained. 151 | # Now we just have to format each of the 152 | # rows. 153 | s = "" 154 | for row in range(nrows): 155 | texts = [] 156 | for col in range(ncols): 157 | i = row + nrows * col 158 | if i >= size: 159 | x = "" 160 | else: 161 | x = array[i] 162 | texts.append(x) 163 | while texts and not texts[-1]: 164 | del texts[-1] 165 | for col in range(len(texts)): 166 | if o["ljust"]: 167 | texts[col] = texts[col].ljust(colwidths[col]) 168 | else: 169 | texts[col] = texts[col].rjust(colwidths[col]) 170 | pass 171 | pass 172 | s += "%s%s%s" % ( 173 | o["lineprefix"], 174 | str(o["colsep"].join(texts)), 175 | o["linesuffix"], 176 | ) 177 | pass 178 | return s 179 | else: 180 | array_index = lambda ncols, row, col: ncols * (row - 1) + col 181 | # Try every column count from size downwards 182 | colwidths = [] 183 | for ncols in range(size, 0, -1): 184 | # Try every row count from 1 upwards 185 | min_rows = (size + ncols - 1) // ncols 186 | nrows = min_rows - 1 187 | while nrows < size: 188 | nrows += 1 189 | rounded_size = nrows * ncols 190 | colwidths = [] 191 | totwidth = -len(o["colsep"]) 192 | for col in range(ncols): 193 | # get max column width for this column 194 | colwidth = 0 195 | for row in range(1, nrows + 1): 196 | i = array_index(ncols, row, col) 197 | if i >= rounded_size: 198 | break 199 | elif i < size: 200 | x = array[i] 201 | colwidth = max(colwidth, len(x)) 202 | pass 203 | pass 204 | colwidths.append(colwidth) 205 | totwidth += colwidth + len(o["colsep"]) 206 | if totwidth >= o["displaywidth"]: 207 | break 208 | pass 209 | if totwidth <= o["displaywidth"] and i >= rounded_size - 1: 210 | # Found the right nrows and ncols 211 | # print "right nrows and ncols" 212 | nrows = row 213 | break 214 | elif totwidth >= o["displaywidth"]: 215 | # print "reduce ncols", ncols 216 | # Need to reduce ncols 217 | break 218 | pass 219 | if totwidth <= o["displaywidth"] and i >= rounded_size - 1: 220 | break 221 | pass 222 | # The smallest number of rows computed and the 223 | # max widths for each column has been obtained. 224 | # Now we just have to format each of the 225 | # rows. 226 | s = "" 227 | if len(o["array_prefix"]) != 0: 228 | prefix = o["array_prefix"] 229 | else: 230 | prefix = o["lineprefix"] 231 | pass 232 | for row in range(1, nrows + 1): 233 | texts = [] 234 | for col in range(ncols): 235 | i = array_index(ncols, row, col) 236 | if i >= size: 237 | break 238 | else: 239 | x = array[i] 240 | texts.append(x) 241 | pass 242 | for col in range(len(texts)): 243 | if o["ljust"]: 244 | texts[col] = texts[col].ljust(colwidths[col]) 245 | else: 246 | texts[col] = texts[col].rjust(colwidths[col]) 247 | pass 248 | pass 249 | s += "%s%s%s" % (prefix, str(o["colsep"].join(texts)), o["linesuffix"]) 250 | prefix = o["lineprefix"] 251 | pass 252 | if o["arrange_array"]: 253 | colsep = o["colsep"].rstrip() 254 | colsep_pos = -(len(colsep) + 1) 255 | if s[colsep_pos:] == colsep + "\n": 256 | s = s[:colsep_pos] + o["array_suffix"] + "\n" 257 | pass 258 | pass 259 | else: 260 | s += o["array_suffix"] 261 | pass 262 | return s 263 | pass 264 | 265 | 266 | # Demo it 267 | if __name__ == "__main__": 268 | # from trepan.api import debug 269 | # debug() 270 | from typing import List, Tuple, Union 271 | print(columnize(list(range(12)), opts={"displaywidth": 6, "arrange_array": True})) 272 | print(columnize(list(range(12)), opts={"displaywidth": 10, "arrange_array": True})) 273 | for t in ( 274 | ( 275 | 4, 276 | 4, 277 | ), 278 | (4, 7), 279 | (100, 80), 280 | ): 281 | width = t[1] 282 | data: Union[List, Tuple] = [str(i) for i in range(t[0])] 283 | options = {} 284 | for t2 in ( 285 | ( 286 | False, 287 | "horizontal", 288 | ), 289 | ( 290 | True, 291 | "vertical", 292 | ), 293 | ): 294 | print("Width: %d, direction: %s" % (width, t2[1])) 295 | options["displaywidth"] = width 296 | options["arrange_vertical"] = t2[0] 297 | print(columnize(data, opts=options)) 298 | pass 299 | pass 300 | print(columnize([])) 301 | print(columnize(["a", "2", "c"], 10, ", ")) 302 | print(columnize(["oneitem"])) 303 | print( 304 | columnize( 305 | ( 306 | "one", 307 | "two", 308 | "three", 309 | ) 310 | ) 311 | ) 312 | data = ( 313 | "one", 314 | "two", 315 | "three", 316 | "for", 317 | "five", 318 | "six", 319 | "seven", 320 | "eight", 321 | "nine", 322 | "ten", 323 | "eleven", 324 | "twelve", 325 | "thirteen", 326 | "fourteen", 327 | "fifteen", 328 | "sixteen", 329 | "seventeen", 330 | "eightteen", 331 | "nineteen", 332 | "twenty", 333 | "twentyone", 334 | "twentytwo", 335 | "twentythree", 336 | "twentyfour", 337 | "twentyfive", 338 | "twentysix", 339 | "twentyseven", 340 | ) 341 | print(columnize(data)) 342 | print(columnize(data, arrange_vertical=False)) 343 | data = [str(i) for i in range(55)] 344 | print(columnize(data, opts={"displaywidth": 39, "arrange_array": True})) 345 | print(columnize(data, displaywidth=39, ljust=False, colsep=", ", lineprefix=" ")) 346 | print( 347 | columnize( 348 | data, displaywidth=39, ljust=False, arrange_vertical=False, colsep=", " 349 | ) 350 | ) 351 | 352 | print( 353 | columnize( 354 | data, 355 | displaywidth=39, 356 | ljust=False, 357 | arrange_vertical=False, 358 | colsep=", ", 359 | lineprefix=" ", 360 | ) 361 | ) 362 | 363 | import sys 364 | 365 | try: 366 | print(columnize(5)) 367 | except TypeError: 368 | err = sys.exc_info()[1] 369 | print(err) 370 | pass 371 | 372 | print(columnize(list(range(4)))) 373 | -------------------------------------------------------------------------------- /columnize/version.py: -------------------------------------------------------------------------------- 1 | # This file is needs to be multi-lingual in both Python and POSIX 2 | # shell which "execfile" or "source" it respectively. 3 | 4 | # This file should define a variable VERSION which we use as the 5 | # debugger version number. 6 | 7 | # fmt: off 8 | __version__="0.3.11" # noqa 9 | -------------------------------------------------------------------------------- /example.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | from random import randint 4 | 5 | from columnize import columnize 6 | 7 | lst = [] 8 | for i in range(200): 9 | num_digits = randint(1, 6) 10 | lst.append(randint(0, 10 ** num_digits)) 11 | 12 | output = columnize(lst, opts={'ljust': True}) 13 | print(output) 14 | -------------------------------------------------------------------------------- /requirements-dev.txt: -------------------------------------------------------------------------------- 1 | pytest 2 | pre-commit 3 | -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [nosetests] 2 | # Location of test programs. "where" can be given several times. 3 | # If "where is a directory, then that's the working directory. 4 | where=./test 5 | 6 | # Our tests are also executable since they are allowed to be run 7 | # individually. By default nose excludes these. 8 | exe=on 9 | 10 | # Show individual tests run 11 | verbosity=2 12 | 13 | #debug=nose.loader 14 | # pdb=on 15 | detailed-errors=on 16 | 17 | [bdist_wheel] 18 | universal=0 19 | 20 | [bdist_rpm] 21 | packager = Rocky Bernstein 22 | provides = pycolumnize # Seems to go in rpm's "provides"? 23 | doc_files = README 24 | 25 | [metadata] 26 | description_file = README.rst 27 | ChangeLog 28 | LICENSE 29 | NEWS.md 30 | 31 | 32 | [flake8] 33 | # max-line-length setting: NO we do not want everyone writing 120-character lines! 34 | # We are setting the maximum line length big here because there are longer 35 | # lines allowed by black in some cases that are forbidden by flake8. Since 36 | # black has the final say about code formatting issues, this setting is here to 37 | # make sure that flake8 doesn't fail the build on longer lines allowed by 38 | # black. 39 | max-line-length = 120 40 | max-complexity = 12 41 | select = E,F,W,C,B,B9 42 | ignore = 43 | # E123 closing bracket does not match indentation of opening bracket's line 44 | E123 45 | # E203 whitespace before ':' (Not PEP8 compliant, Python Black) 46 | E203 47 | # E501 line too long (82 > 79 characters) (replaced by B950 from flake8-bugbear, 48 | # https://github.com/PyCQA/flake8-bugbear) 49 | E501 50 | # W503 line break before binary operator (Not PEP8 compliant, Python Black) 51 | W503 52 | # W504 line break after binary operator (Not PEP8 compliant, Python Black) 53 | W504 54 | # C901 function too complex - since many of zz9 functions are too complex with a lot 55 | # of if branching 56 | C901 57 | # module level import not at top of file. This is too restrictive. Can't even have a 58 | # docstring higher. 59 | E402 60 | per-file-ignores = 61 | # These are config files. The `c` variable them is injected not defined. 62 | pow/ansible/roles/jupyterhub/templates/jupyterhub_config*.py:F821 63 | # Ignore some errors in files that are stolen from other projects to avoid lots 64 | # of merge problems later . 65 | pow/ansible/roles/webtier/files/supervisor_httpgroupok.py:E126,E128,E222,E225,E226,E261,E301,E302,E305,F841,E201,E202 66 | silhouette/src/silhouette/gprof2dot.py:E711,E713,E741,F401 67 | # Ignore undefined name errors in "expectation" test Python code. 68 | # These files get exec'd in an environment that defines the variables. 69 | server/tests/files/expectations/*.py:F821 70 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """ 3 | distutils setup (setup.py) 4 | 5 | This gets a bit of package info from __pkginfo__.py file 6 | """ 7 | # Get the required package information 8 | from setuptools import find_packages, setup 9 | 10 | from __pkginfo__ import ( 11 | __version__, 12 | author, 13 | author_email, 14 | classifiers, 15 | pkg_license, 16 | long_description, 17 | modname, 18 | py_modules, 19 | short_desc, 20 | web, 21 | ) 22 | 23 | setup( 24 | author=author, 25 | author_email=author_email, 26 | classifiers=classifiers, 27 | description=short_desc, 28 | install_requires=[], 29 | license=pkg_license, 30 | long_description=long_description, 31 | long_description_content_type="text/x-rst", 32 | name=modname, 33 | packages=find_packages(), 34 | py_modules=py_modules, 35 | url=web, 36 | version=__version__, 37 | ) 38 | -------------------------------------------------------------------------------- /test/test_columnize.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- Python -*- 3 | "Unit test for Columnize" 4 | import sys 5 | from unittest import mock 6 | 7 | import pytest 8 | 9 | from columnize import columnize 10 | 11 | 12 | def test_basic(): 13 | """Basic sanity and status testing.""" 14 | assert "1, 2, 3\n" == columnize(["1", "2", "3"], 10, ", ") 15 | assert "1 3\n2 4\n" == columnize(["1", "2", "3", "4"], 4) 16 | 17 | assert "1 3\n2 4\n" == columnize(["1", "2", "3", "4"], 7) 18 | 19 | assert "0 1 2\n3\n" == columnize(["0", "1", "2", "3"], 7, arrange_vertical=False) 20 | 21 | assert "\n" == columnize([]) 22 | assert "oneitem\n" == columnize(["oneitem"]) 23 | 24 | data = [str(i) for i in range(55)] 25 | assert ( 26 | "0, 6, 12, 18, 24, 30, 36, 42, 48, 54\n" 27 | + "1, 7, 13, 19, 25, 31, 37, 43, 49\n" 28 | + "2, 8, 14, 20, 26, 32, 38, 44, 50\n" 29 | + "3, 9, 15, 21, 27, 33, 39, 45, 51\n" 30 | + "4, 10, 16, 22, 28, 34, 40, 46, 52\n" 31 | + "5, 11, 17, 23, 29, 35, 41, 47, 53\n" 32 | == columnize( 33 | data, displaywidth=39, ljust=False, arrange_vertical=True, colsep=", " 34 | ) 35 | ) 36 | 37 | assert ( 38 | " 0, 7, 14, 21, 28, 35, 42, 49\n" 39 | + " 1, 8, 15, 22, 29, 36, 43, 50\n" 40 | + " 2, 9, 16, 23, 30, 37, 44, 51\n" 41 | + " 3, 10, 17, 24, 31, 38, 45, 52\n" 42 | + " 4, 11, 18, 25, 32, 39, 46, 53\n" 43 | + " 5, 12, 19, 26, 33, 40, 47, 54\n" 44 | + " 6, 13, 20, 27, 34, 41, 48\n" 45 | == columnize( 46 | data, 47 | displaywidth=39, 48 | ljust=False, 49 | arrange_vertical=True, 50 | colsep=", ", 51 | lineprefix=" ", 52 | ) 53 | ) 54 | 55 | assert ( 56 | " 0, 1, 2, 3, 4, 5, 6, 7, 8, 9\n" 57 | + "10, 11, 12, 13, 14, 15, 16, 17, 18, 19\n" 58 | + "20, 21, 22, 23, 24, 25, 26, 27, 28, 29\n" 59 | + "30, 31, 32, 33, 34, 35, 36, 37, 38, 39\n" 60 | + "40, 41, 42, 43, 44, 45, 46, 47, 48, 49\n" 61 | + "50, 51, 52, 53, 54\n" 62 | == columnize( 63 | data, displaywidth=39, ljust=False, arrange_vertical=False, colsep=", " 64 | ) 65 | ) 66 | 67 | assert ( 68 | " 0, 1, 2, 3, 4, 5, 6, 7\n" 69 | + " 8, 9, 10, 11, 12, 13, 14, 15\n" 70 | + " 16, 17, 18, 19, 20, 21, 22, 23\n" 71 | + " 24, 25, 26, 27, 28, 29, 30, 31\n" 72 | + " 32, 33, 34, 35, 36, 37, 38, 39\n" 73 | + " 40, 41, 42, 43, 44, 45, 46, 47\n" 74 | + " 48, 49, 50, 51, 52, 53, 54\n" 75 | == columnize( 76 | data, 77 | displaywidth=34, 78 | ljust=False, 79 | arrange_vertical=False, 80 | colsep=", ", 81 | lineprefix=" ", 82 | ) 83 | ) 84 | 85 | data = ( 86 | "one", 87 | "two", 88 | "three", 89 | "for", 90 | "five", 91 | "six", 92 | "seven", 93 | "eight", 94 | "nine", 95 | "ten", 96 | "eleven", 97 | "twelve", 98 | "thirteen", 99 | "fourteen", 100 | "fifteen", 101 | "sixteen", 102 | "seventeen", 103 | "eightteen", 104 | "nineteen", 105 | "twenty", 106 | "twentyone", 107 | "twentytwo", 108 | "twentythree", 109 | "twentyfour", 110 | "twentyfive", 111 | "twentysix", 112 | "twentyseven", 113 | ) 114 | 115 | assert ( 116 | "one two three for five six \n" 117 | + "seven eight nine ten eleven twelve \n" 118 | + "thirteen fourteen fifteen sixteen seventeen eightteen \n" 119 | + "nineteen twenty twentyone twentytwo twentythree twentyfour\n" 120 | + "twentyfive twentysix twentyseven\n" 121 | == columnize(data, arrange_vertical=False) 122 | ) 123 | 124 | assert ( 125 | "one five nine thirteen seventeen twentyone twentyfive \n" 126 | + "two six ten fourteen eightteen twentytwo twentysix \n" 127 | + "three seven eleven fifteen nineteen twentythree twentyseven\n" 128 | + "for eight twelve sixteen twenty twentyfour \n" 129 | == columnize(data) 130 | ) 131 | 132 | assert "0 1 2 3\n" == columnize(list(range(4))) 133 | 134 | assert ( 135 | "[ 0, 1, 2, 3, 4, 5, 6, 7, 8,\n" 136 | + " 9, 10, 11, 12, 13, 14, 15, 16, 17,\n" 137 | + " 18, 19, 20, 21, 22, 23, 24, 25, 26,\n" 138 | + " 27, 28, 29, 30, 31, 32, 33, 34, 35,\n" 139 | + " 36, 37, 38, 39, 40, 41, 42, 43, 44,\n" 140 | + " 45, 46, 47, 48, 49, 50, 51, 52, 53,\n" 141 | + " 54]\n\n" 142 | == columnize(list(range(55)), opts={"displaywidth": 38, "arrange_array": True}) 143 | ) 144 | 145 | assert ( 146 | "[ 0,\n 1,\n 2,\n 3,\n 4,\n 5,\n 6,\n 7,\n 8,\n 9,\n 10,\n 11]\n\n" 147 | == columnize(list(range(12)), opts={"displaywidth": 6, "arrange_array": True}) 148 | ) 149 | 150 | assert ( 151 | "[ 0, 1,\n 2, 3,\n 4, 5,\n 6, 7,\n 8, 9,\n 10, 11]\n\n" 152 | == columnize(list(range(12)), opts={"displaywidth": 9, "arrange_array": True}) 153 | ) 154 | return 155 | 156 | 157 | def test_colfmt(): 158 | assert " 0 1 2 3\n" == columnize( 159 | [0, 1, 2, 3], 7, arrange_vertical=False, opts={"colfmt": "%5d"} 160 | ) 161 | 162 | 163 | def test_lineprefix(): 164 | assert ">>> 0\n>>> 1\n>>> 2\n>>> 3\n" == columnize( 165 | [0, 1, 2, 3], 166 | 7, 167 | arrange_vertical=False, 168 | opts={"colfmt": "%5d", "displaywidth": 16, "lineprefix": ">>> "}, 169 | ) 170 | 171 | 172 | def test_lineprefix_just_wide_enough(): 173 | assert ">>>10 12\n>>>11 13\n" == columnize( 174 | [10, 11, 12, 13], opts={"lineprefix": ">>>", "displaywidth": 9} 175 | ) 176 | 177 | 178 | if sys.version_info[:2] >= (3, 6): 179 | 180 | @mock.patch.dict("os.environ", {"COLUMNS": "87"}, clear=True) 181 | def test_computed_displaywidth_environ_columns_set(): 182 | from columnize import computed_displaywidth 183 | 184 | width = computed_displaywidth() 185 | assert width == 87 186 | 187 | 188 | def test_errors(): 189 | """Test various error conditions.""" 190 | with pytest.raises(TypeError): 191 | columnize(5) 192 | return 193 | 194 | 195 | if __name__ == "__main__": 196 | test_basic() 197 | -------------------------------------------------------------------------------- /tox.ini: -------------------------------------------------------------------------------- 1 | [tox] 2 | envlist = py27, py37 3 | 4 | [flake8] 5 | exclude = .tox,./tmp,./build 6 | filename = columnize.py 7 | ignore = C901,E123,E127,E203,E221,E225,E226,E231,E241,E251,E701,E731 8 | 9 | [testenv] 10 | deps = -r{toxinidir}/requirements.txt 11 | commands = py.test {posargs} 12 | 13 | [testenv:cover] 14 | commands = py.test {posargs:--cov pycolumnize.columnize --cov-report=term-missing --cov-report=xml --cov-report=html} 15 | --------------------------------------------------------------------------------