{"id":17115230,"url":"https://github.com/sundarnagarajan/py23compat","last_synced_at":"2025-07-29T19:40:00.805Z","repository":{"id":132721766,"uuid":"72054597","full_name":"sundarnagarajan/py23compat","owner":"sundarnagarajan","description":"Module to inject python 2-3 compatible features from python-future","archived":false,"fork":false,"pushed_at":"2016-10-27T00:06:41.000Z","size":21,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-01-29T06:51:23.631Z","etag":null,"topics":["compatibility","python","python-future","python2","python3"],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/sundarnagarajan.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2016-10-26T23:58:43.000Z","updated_at":"2017-05-21T03:04:23.000Z","dependencies_parsed_at":null,"dependency_job_id":"25e25d55-113e-4494-8a09-c3d5631b966f","html_url":"https://github.com/sundarnagarajan/py23compat","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sundarnagarajan%2Fpy23compat","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sundarnagarajan%2Fpy23compat/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sundarnagarajan%2Fpy23compat/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sundarnagarajan%2Fpy23compat/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sundarnagarajan","download_url":"https://codeload.github.com/sundarnagarajan/py23compat/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245186921,"owners_count":20574554,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["compatibility","python","python-future","python2","python3"],"created_at":"2024-10-14T17:22:23.249Z","updated_at":"2025-03-23T23:43:53.143Z","avatar_url":"https://github.com/sundarnagarajan.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# py23compat\nModule to inject python 2-3 compatible features from python-future\n\nI wanted a way to do the following:\n- Make new python source files Py2-3 compatible from the start using python-future\n- Consistently import (inject) python-future features into all source files in a package\n- Avoid having to do multiple imports at the top of each source file - potentially\nleading to mistakes or inconsistencies\n\n\n\nDependencies:\n------------\n    Uses and requires installation of the excellent 'future' package.\n    Install with pip install future\n\n    This module has no other external dependencies. You can place it\n    anywhere on your PYTHONPATH\n\n    Does not work with Python2 \u003c 2.6 - importing this module or calling\n    inject_compat() should have no effect in such cases\n\nFour capabilities, three variables to set and one method:\n--------------------------------------------------------\n    Capability                              Variable / Method\n    ----------                              --------\n    Customize features for source files     ALWAYS_AVOID variable\n    Customize features for REPL             ALWAYS_AVOID_REPL variable\n    Select features by just importing       AUTOLOAD_ALL variable\n    Select features on per-file basis       inject_compat method\n\n    AUTOLOAD_ALL versus calling inject_compat:\n        If you want to choose different features for different source\n        files, you NEED TO:\n            Add following TWO lines to the top of each source file\n                from py23compat import inject_compat\n                inject_compat()\n            You can avoid SOME features across ALL source files by\n            adding those features to ALWAYS_AVOID, and add ADDITIONAL\n            features to avoid on a per-file basis by adding avoid=[...]\n            to the inject_compat() call in each source file\n\n            In this model, you NEED to add TWO lines to each source file,\n            though you may not need the avoid=[..] in the call to\n            inject_compat in all source files.\n\n        If all your source files are in the SAME STAGE of Python-2-3\n        compatibility / migration, you can:\n            Disable some features across ALL source files using\n            ALWAYS_AVOID\n            Set AUTOLOAD_ALL = True\n            Load remaining features in each source file by JUST importing\n            py23compat using a line like:\n                import py23compat     # noqa: F401\n\n            '# noqa: F401' asks PEP8 not to complain about an unused import\n\n            In this model, you CANNOT customize features on a per-file\n            basis.\n\n    The features avoided in the REPL are separate (ALWAYS_AVOID_REPL).\n    Features are ALWAYS injected into the REPL by JUST importing py23compat.\n\nis_int and is_str methods:\n-------------------------\n    Some modules (such as simplejson, but I am sure there are more), can\n    RETURN objects of type 'unicode' or 'long' in Python2. If you have\n    disabled 'unicode' and 'long' in Python2 (e.g. by having an empty\n    ALWAYS_AVOID list), then you have no way to check if the returned\n    valus is an instance of 'unicode' or 'long' respectively. In addition,\n    in such cases, the returned variable will NOT be an instance of\n    str | int respectively (although it's BEHAVIOR will be similar to those\n    respective types).\n\n    In such cases, you can use the is_str and is_int methods by importing\n    them from this module. On Python2 is_int will match int and long and\n    is_str will match str and unicode, while on Python3 is_int will match\n    only int and is_str will match only str.\n\n    You only need these methods if you would have otherwise used isinstance\n    for this purpose.\n\nPython version variables:\n------------------------\n    PY2--\u003eboolean: Whether running in python2 (any minor version)\n    PY3--\u003eboolean: Whether running in python3 (any minor version)\n    PYPY--\u003eboolean: Whether running in pypy (any minor version)\n    PY_MINOR--\u003eint: Python minor version\n\nVariables, imports and what is injected:\n---------------------------------------\n    REPL    Variable            import          Effect\n    -----------------------------------------------------------------------\n    YES     ALWAYS_AVOID_REPL   plain import    Except ALWAYS_AVOID_REPL\n                                                is_int and is_str automatic\n\n    YES     ALWAYS_AVOID_REPL   import +        Except ALWAYS_AVOID_REPL\n            avoid param         inject_compat   avoid param has no effect\n                                                is_int, is_str need import\n\n    Source  ALWAYS_AVOID        plain import    Except ALWAYS_AVOID\n                                                is_int, is_str need import\n\n    Source  ALWAYS_AVOID        import +        Except ALWAYS_AVOID AND\n            avoid param         inject_compat   except avoid param\n                                                is_int, is_str need import\n    -----------------------------------------------------------------------\n\n    inject_compat ONLY injects compatibility names into:\n        Caller's stack frame\n        Top-most stack frame ONLY if running in REPL\n\n    Importing this module ONLY injects compatibility names into:\n        Top-most stack frame ONLY if running in REPL\n        Into caller's (importer's) stack frame if AUTOLOAD_ALL is set\n\n    When using the REPL, if ANY module IMPORTS py23compat, the\n    compatibility names will be injected into the TOP-MOST stack\n    frame (repeat: ONLY when using the REPL)\n\n    Note the difference between the CALLER (importer) stack frame and\n    the TOP-MOST stack frame.\n\nUsage for NEW python packages starting from scratch:\n---------------------------------------------------\n    A. Make a COPY of this module (file) for EACH package - it has\n       variables at the top that you CAN (and SHOULD) change to reflect\n       the stage the package is in  (in terms of Python2-3 compatibility)\n\n    B. For a NEW package started from scratch, I recommend:\n        1. Keep ALWAYS_AVOID and ALWAYS_AVOID_REPL EMPTY\n        2. Set AUTOLOAD_ALL = True\n            Allows injecting compatibility code by JUST importing py23compat\n            Still obeys ALWAYS_AVOID and ALWAYS_AVOID_REPL\n            if you need them\n        3. Write your package using (only) Python3 idioms and constructs.\n          It should run unchanged in Python2 (need to pip install future)\n\nUsage for making existing Python2 packages compatible with Python2-3:\n--------------------------------------------------------------------\n\n    A. Make a COPY of this module (file) for EACH package - it has\n       variables at the top that you CAN (and SHOULD) change to reflect\n       the stage the package is in  (in terms of Python2-3 compatibility)\n\n    B. Make a list of all the changed features and obsoleted features\n       being used by your package.\n            See future_imports for NEW behavior in Python3\n            See builtins_imports for CHANGED behavior\n            See obsolete_imports for OBSOLETED classes, methods\n\n    E. Use one of the following strategies. Note there are MANY possible\n       strategies, and the python-future website has a much more robust\n       and complete discussion of migration strategies.\n\n        Feature-by-feature\n            1. Start by adding ALL the features your package is using that has\n               been changed or obsoleted in Python3 to ALWAYS_AVOID.\n\n            2. If you regularly explore your package interactively using a REPL,\n                add JUST the changed features (not the obsoleted features) to\n                ALWAYS_AVOID_REPL also.\n\n            3. Go through your package feature-by-feature and once a\n                feature has been upgraded across your package, remove it\n                from ALWAYS_AVOID and ALWAYS_AVOID_REPL.\n\n            4. During this time, you can keep AUTOLOAD_ALL = True and\n               JUST import py23compat at the top of each source file\n\n            5. Once you have emptied ALWAYS_AVOID and ALWAYS_AVOID_REPL,\n               your package should run unchanged in Python 2 and 3\n\n        File-by-file\n            1. Add two lines at the top of each source file:\n                   from py23compat import inject_compat\n                   inject_compat(avoid=xyz)\n               where xyz is a set of features to disable for that file\n\n            2. In each file, upgrade each disabled feature and then\n               remove it from the avoid list\n\n            3. Once the avoid list is empty, you can change the two lines\n               at the top to be just:\n                   import py23compat\n\n            4. Once all files have been upgraded and have an empty avoid list,\n               your package should run unchanged in Python 2 and 3\n\nKnown bug: interaction with pydoc on Python2:\n--------------------------------------------\nIf using AUTOLOAD_ALL=True, AND 'unicode' is not in ALWAYS_AVOID,\npydoc2 (pydoc on python2) will fail for this module.\nTo use pydoc on py23compat with AUTOLOAD_ALL=True, do one of the\nfollowing:\n\n  - Use pydoc3 in a python3 virtualenv\n  - In a REPL, import py23compat and then do help(py23compat)\n  - Call pydoc setting (shell) environment var PY23COMPAT_NO_AUTOLOAD)\n  - Alias pydoc to 'PY23COMPAT_NO_AUTOLOAD=yes pydoc'\n\nNote that PY23COMPAT_NO_AUTOLOAD disables effect of AUTOLOAD_ALL in\nALL conditions- not just for pydoc - there is no way to effect special\nbehavior when being imported by pydoc\n\n\nMore information on python-future and Python2-3 compatibility:\n-------------------------------------------------------------\n    See the python-future site for more information on writing python\n    programs that can run in Python 2.x or 3.x, Python 2--\u003e3 migration\n    and the python-future package.\n\n    Python-future Quick Start Guide: http://python-future.org/quickstart.html\n\n    Idioms for writing Python 2-3 compatible code:\n        http://python-future.org/compatible_idioms.html\n\n    Importing explicitly:\n    http://python-future.org/imports.html#explicit-imports\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsundarnagarajan%2Fpy23compat","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsundarnagarajan%2Fpy23compat","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsundarnagarajan%2Fpy23compat/lists"}