{"id":25874658,"url":"https://github.com/lyft/syx","last_synced_at":"2025-10-14T08:10:12.246Z","repository":{"id":66215831,"uuid":"116994854","full_name":"lyft/syx","owner":"lyft","description":"Python 2 and 3 compatibility library from Lyft.","archived":false,"fork":false,"pushed_at":"2023-03-20T03:12:59.000Z","size":7,"stargazers_count":7,"open_issues_count":0,"forks_count":7,"subscribers_count":158,"default_branch":"master","last_synced_at":"2025-04-05T00:41:19.060Z","etag":null,"topics":["lyft"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/lyft.png","metadata":{"files":{"readme":"README.rst","changelog":null,"contributing":null,"funding":null,"license":null,"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":"2018-01-10T18:24:59.000Z","updated_at":"2024-01-03T14:15:27.000Z","dependencies_parsed_at":"2025-03-02T09:38:46.631Z","dependency_job_id":null,"html_url":"https://github.com/lyft/syx","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/lyft/syx","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lyft%2Fsyx","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lyft%2Fsyx/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lyft%2Fsyx/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lyft%2Fsyx/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/lyft","download_url":"https://codeload.github.com/lyft/syx/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lyft%2Fsyx/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":279018306,"owners_count":26086334,"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","status":"online","status_checked_at":"2025-10-14T02:00:06.444Z","response_time":60,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["lyft"],"created_at":"2025-03-02T09:28:39.249Z","updated_at":"2025-10-14T08:10:12.239Z","avatar_url":"https://github.com/lyft.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"syx\n===\n\nPython 2 and 3 compatibility library from Lyft.  Pronounced \"Six with a Y\".\n\n``syx`` builds off of the ubiquitous\n`six \u003chttps://github.com/benjaminp/six\u003e`__ library, backporting some behavior\nfrom Python 3 to Python 2 and includes some helper methods for handling\n``bytes`` and ``str`` differences between Python 2 and Python 3.\n\nBytes vs. strings\n-----------------\n\nPython 3 splits up strings and bytes into separate data types. To go\nfrom bytes to a string, you must decode. To go from a string to bytes,\nyou must encode. These changes propagated through the standard library.\nFor example, in `Python 2\nb64encode \u003chttps://docs.python.org/2/library/base64.html\u003e`__ accepted a\nstring and returned a string, whereas `Python 3's\nb64encode \u003chttps://docs.python.org/3.6/library/base64.html\u003e`__ requires\na bytes-like object and returns bytes. Dealing with these small changes\ncan be arduous as mentioned during a `PyCon 2017\nKeynote \u003chttps://youtu.be/66XoCk79kjM?t=1828\u003e`__, so ``syx`` includes\ntwo helper methods, ``ensure_bytes`` (aliased as ``b``) and\n``ensure_str`` (aliased as ``s``). ``ensure_bytes`` converts it's input\nto ``bytes`` if needed, ``ensure_str`` converts it's input to a string\nif needed.\n\nFor example, say we have a function ``encode_value_as_b64_str`` that\naccepts a value that could be a string or bytes and returns a base64\nencoded string. Using ``syx``, this function can be written as:\n\n.. code:: python\n\n    from base64 import b64encode\n    from syx import b, s\n\n    def encode_value_as_b64_str(value):\n      return s(b64encode(b(value)))\n\nRounding\n--------\n\nPython 3 changed the default rounding implementation from \"Round away\nfrom 0\" to \"Banker's Rounding\". As the name implies, banker's rounding\nis the internationally accepted way of rounding numbers for financial\ntransactions. The main difference is instead of always rounding up\nduring a tie (which introduces a slight skew upwards in your data)\nbanker's rounding rounds towards the nearest even. So, for example,\nrounding both ``1.5`` and ``2.5`` will result in ``2``. While this is\nnot what's taught in grade school, it is more accurate.\n\nAs a concrete example:\n\n.. code:: python\n\n    import numpy as np\n    from syx import round\n\n    def bad_round(num):\n        return int(num + .5)\n\n    count = int(1e6)\n    values = np.random.randint(101, size=count) / 10\n    real_mean = sum(values) / count\n    py3_rounded_mean = sum(round(x) for x in values) / count\n    py2_rounded_mean = sum(bad_round(x) for x in values) / count\n\n    print('actual %f' % real_mean)\n    print('py3 round: %f, error: %f' % (py3_rounded_mean, abs(real_mean - py3_rounded_mean)))\n    print('py2 round: %f, error: %f' % (py2_rounded_mean, abs(real_mean - py2_rounded_mean)))\n\n::\n\n    actual 4.998499\n    py3 round: 4.998387, error: 0.000112\n    py2 round: 5.048665, error: 0.050166\n\nThe old rounding method predictably introduces a 1% error upwards.\n``syx`` ships an implementation of banker's rounding in Cython so it's\nas fast or faster than the built in rounding method.\n\nhasattr\n-------\n\nAs has been observed by others, ``hasattr`` in Python 2 can dangerously\nhide bugs. Some would even say that `hasattr is Considered\nHarmful \u003chttps://hynek.me/articles/hasattr/\u003e`__. ``syx`` ships a\nbackport of Python 3's ``hasattr`` behavior.\n\n.. code:: python\n\n    from syx import hasattr\n\n    class GoesBoom(object):\n          @property\n          def boom(self):\n              raise Exception('Oh Noes!')\n\n    hasattr(GoesBoom(), 'boom')  # Now properly raises an Exception\n\n\nFixers\n======\n\n``syx`` ships with some ``lib2to3`` fixers to automatically start using\nthe Python 3 backports of ``round`` and ``hasattr``. You can run these\nfixers with\n`python-modernize \u003chttps://github.com/python-modernize/python-modernize\u003e`__,\nfor example:\n\n::\n\n    python-modernize -w -f syx.fixers.fix_hasattr -f syx.fixers.fix_round ...\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flyft%2Fsyx","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flyft%2Fsyx","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flyft%2Fsyx/lists"}