Repository: wistbean/learn_python3_spider Branch: master Commit: aef4159f8542 Files: 2270 Total size: 23.1 MB Directory structure: gitextract_cqvzh202/ ├── .gitattributes ├── CloudCreat ├── GaoKao_Score/ │ ├── 2006-2016浙江高考录取分数线.html │ ├── 2006-2016海南高考录取分数线.html │ ├── 2006-2017上海高考录取分数线.html │ ├── 2006-2017安徽高考录取分数线.html │ ├── 2006-2017山东高考录取分数线.html │ ├── 2006-2017山西高考录取分数线.html │ ├── 2006-2017新疆高考录取分数线.html │ ├── 2006-2017河南高考录取分数线.html │ ├── 2006-2017福建高考录取分数线.html │ ├── 2006-2017重庆高考录取分数线.html │ ├── 2006-2017黑龙江高考录取分数线.html │ ├── 2006-2018云南高考录取分数线.html │ ├── 2006-2018内蒙古高考录取分数线.html │ ├── 2006-2018北京高考录取分数线.html │ ├── 2006-2018吉林高考录取分数线.html │ ├── 2006-2018四川高考录取分数线.html │ ├── 2006-2018天津高考录取分数线.html │ ├── 2006-2018宁夏高考录取分数线.html │ ├── 2006-2018广东高考录取分数线.html │ ├── 2006-2018广西高考录取分数线.html │ ├── 2006-2018江西高考分数线.html │ ├── 2006-2018河北高考录取分数线.html │ ├── 2006-2018湖北高考录取分数线.html │ ├── 2006-2018湖南高考录取分数线.html │ ├── 2006-2018甘肃高考录取分数线.html │ ├── 2006-2018西藏高考录取分数线.html │ ├── 2006-2018贵州高考录取分数线.html │ ├── 2006-2018辽宁高考录取分数线.html │ ├── 2006-2018陕西高考录取分数线.html │ ├── 2006-2018青海高考录取分数线.html │ ├── 2010-2017江苏高考录取分数线.html │ ├── 文科(一本)全国高考录取分数平均值比较.html │ └── 理科(一本)全国高考录取分数平均值比较.html ├── LICENSE ├── README.md ├── biaoqingbao/ │ ├── biaoqingbao.py │ └── search.py ├── dangdang_top_500.py ├── douban_top_250_books.py ├── douban_top_250_books_mul_process.py ├── fuck_bilibili_captcha.py ├── ikun_basketball.py ├── meizitu.py ├── qiushibaike/ │ ├── qiushibaike/ │ │ ├── __init__.py │ │ ├── items.py │ │ ├── middlewares.py │ │ ├── pipelines.py │ │ ├── settings.py │ │ └── spiders/ │ │ ├── __init__.py │ │ └── qiushibaike_spider.py │ └── scrapy.cfg ├── stackoverflow/ │ ├── .idea/ │ │ ├── inspectionProfiles/ │ │ │ └── profiles_settings.xml │ │ ├── misc.xml │ │ ├── modules.xml │ │ ├── stackoverflow.iml │ │ ├── vcs.xml │ │ └── workspace.xml │ ├── scrapy.cfg │ ├── stackoverflow/ │ │ ├── __init__.py │ │ ├── items.py │ │ ├── middlewares/ │ │ │ ├── StackoverflowDownloaderMiddleware.py │ │ │ └── __init__.py │ │ ├── middlewares.py │ │ ├── pipelines.py │ │ ├── requirement.txt │ │ ├── settings.py │ │ └── spiders/ │ │ ├── __init__.py │ │ └── stackoverflow-python-spider.py │ └── venv/ │ ├── bin/ │ │ ├── activate │ │ ├── activate.csh │ │ ├── activate.fish │ │ ├── automat-visualize │ │ ├── cftp │ │ ├── ckeygen │ │ ├── conch │ │ ├── easy_install │ │ ├── easy_install-3.6 │ │ ├── mailmail │ │ ├── pip │ │ ├── pip3 │ │ ├── pip3.6 │ │ ├── pyhtmlizer │ │ ├── python │ │ ├── python3 │ │ ├── scrapy │ │ ├── tkconch │ │ ├── trial │ │ ├── twist │ │ └── twistd │ ├── lib/ │ │ └── python3.6/ │ │ └── site-packages/ │ │ ├── .libs_cffi_backend/ │ │ │ └── libffi-10449faf.so.5.0.6 │ │ ├── Automat-0.8.0.dist-info/ │ │ │ ├── INSTALLER │ │ │ ├── LICENSE │ │ │ ├── METADATA │ │ │ ├── RECORD │ │ │ ├── WHEEL │ │ │ ├── entry_points.txt │ │ │ └── top_level.txt │ │ ├── OpenSSL/ │ │ │ ├── SSL.py │ │ │ ├── __init__.py │ │ │ ├── _util.py │ │ │ ├── crypto.py │ │ │ ├── debug.py │ │ │ ├── rand.py │ │ │ ├── tsafe.py │ │ │ └── version.py │ │ ├── PyDispatcher-2.0.5-py3.6.egg-info/ │ │ │ ├── PKG-INFO │ │ │ ├── SOURCES.txt │ │ │ ├── dependency_links.txt │ │ │ ├── installed-files.txt │ │ │ └── top_level.txt │ │ ├── PyHamcrest-1.9.0.dist-info/ │ │ │ ├── DESCRIPTION.rst │ │ │ ├── INSTALLER │ │ │ ├── METADATA │ │ │ ├── RECORD │ │ │ ├── WHEEL │ │ │ ├── metadata.json │ │ │ ├── pbr.json │ │ │ └── top_level.txt │ │ ├── Scrapy-1.7.4.dist-info/ │ │ │ ├── AUTHORS │ │ │ ├── INSTALLER │ │ │ ├── LICENSE │ │ │ ├── METADATA │ │ │ ├── RECORD │ │ │ ├── WHEEL │ │ │ ├── entry_points.txt │ │ │ └── top_level.txt │ │ ├── Twisted-19.7.0.dist-info/ │ │ │ ├── INSTALLER │ │ │ ├── LICENSE │ │ │ ├── METADATA │ │ │ ├── RECORD │ │ │ ├── WHEEL │ │ │ ├── entry_points.txt │ │ │ └── top_level.txt │ │ ├── attr/ │ │ │ ├── __init__.py │ │ │ ├── __init__.pyi │ │ │ ├── _compat.py │ │ │ ├── _config.py │ │ │ ├── _funcs.py │ │ │ ├── _make.py │ │ │ ├── _version_info.py │ │ │ ├── _version_info.pyi │ │ │ ├── converters.py │ │ │ ├── converters.pyi │ │ │ ├── exceptions.py │ │ │ ├── exceptions.pyi │ │ │ ├── filters.py │ │ │ ├── filters.pyi │ │ │ ├── py.typed │ │ │ ├── validators.py │ │ │ └── validators.pyi │ │ ├── attrs-19.3.0.dist-info/ │ │ │ ├── INSTALLER │ │ │ ├── LICENSE │ │ │ ├── METADATA │ │ │ ├── RECORD │ │ │ ├── WHEEL │ │ │ └── top_level.txt │ │ ├── automat/ │ │ │ ├── __init__.py │ │ │ ├── _core.py │ │ │ ├── _discover.py │ │ │ ├── _introspection.py │ │ │ ├── _methodical.py │ │ │ ├── _test/ │ │ │ │ ├── __init__.py │ │ │ │ ├── test_core.py │ │ │ │ ├── test_discover.py │ │ │ │ ├── test_methodical.py │ │ │ │ ├── test_trace.py │ │ │ │ └── test_visualize.py │ │ │ └── _visualize.py │ │ ├── bson/ │ │ │ ├── __init__.py │ │ │ ├── binary.py │ │ │ ├── code.py │ │ │ ├── codec_options.py │ │ │ ├── dbref.py │ │ │ ├── decimal128.py │ │ │ ├── errors.py │ │ │ ├── int64.py │ │ │ ├── json_util.py │ │ │ ├── max_key.py │ │ │ ├── min_key.py │ │ │ ├── objectid.py │ │ │ ├── py3compat.py │ │ │ ├── raw_bson.py │ │ │ ├── regex.py │ │ │ ├── son.py │ │ │ ├── timestamp.py │ │ │ └── tz_util.py │ │ ├── cffi/ │ │ │ ├── __init__.py │ │ │ ├── _cffi_errors.h │ │ │ ├── _cffi_include.h │ │ │ ├── _embedding.h │ │ │ ├── api.py │ │ │ ├── backend_ctypes.py │ │ │ ├── cffi_opcode.py │ │ │ ├── commontypes.py │ │ │ ├── cparser.py │ │ │ ├── error.py │ │ │ ├── ffiplatform.py │ │ │ ├── lock.py │ │ │ ├── model.py │ │ │ ├── parse_c_type.h │ │ │ ├── pkgconfig.py │ │ │ ├── recompiler.py │ │ │ ├── setuptools_ext.py │ │ │ ├── vengine_cpy.py │ │ │ ├── vengine_gen.py │ │ │ └── verifier.py │ │ ├── cffi-1.13.1.dist-info/ │ │ │ ├── INSTALLER │ │ │ ├── LICENSE.txt │ │ │ ├── METADATA │ │ │ ├── RECORD │ │ │ ├── WHEEL │ │ │ ├── entry_points.txt │ │ │ └── top_level.txt │ │ ├── constantly/ │ │ │ ├── __init__.py │ │ │ ├── _constants.py │ │ │ └── _version.py │ │ ├── constantly-15.1.0.dist-info/ │ │ │ ├── DESCRIPTION.rst │ │ │ ├── INSTALLER │ │ │ ├── METADATA │ │ │ ├── RECORD │ │ │ ├── WHEEL │ │ │ ├── metadata.json │ │ │ ├── pbr.json │ │ │ └── top_level.txt │ │ ├── cryptography/ │ │ │ ├── __about__.py │ │ │ ├── __init__.py │ │ │ ├── exceptions.py │ │ │ ├── fernet.py │ │ │ ├── hazmat/ │ │ │ │ ├── __init__.py │ │ │ │ ├── _der.py │ │ │ │ ├── _oid.py │ │ │ │ ├── backends/ │ │ │ │ │ ├── __init__.py │ │ │ │ │ ├── interfaces.py │ │ │ │ │ └── openssl/ │ │ │ │ │ ├── __init__.py │ │ │ │ │ ├── aead.py │ │ │ │ │ ├── backend.py │ │ │ │ │ ├── ciphers.py │ │ │ │ │ ├── cmac.py │ │ │ │ │ ├── decode_asn1.py │ │ │ │ │ ├── dh.py │ │ │ │ │ ├── dsa.py │ │ │ │ │ ├── ec.py │ │ │ │ │ ├── ed25519.py │ │ │ │ │ ├── ed448.py │ │ │ │ │ ├── encode_asn1.py │ │ │ │ │ ├── hashes.py │ │ │ │ │ ├── hmac.py │ │ │ │ │ ├── ocsp.py │ │ │ │ │ ├── poly1305.py │ │ │ │ │ ├── rsa.py │ │ │ │ │ ├── utils.py │ │ │ │ │ ├── x25519.py │ │ │ │ │ ├── x448.py │ │ │ │ │ └── x509.py │ │ │ │ ├── bindings/ │ │ │ │ │ ├── __init__.py │ │ │ │ │ └── openssl/ │ │ │ │ │ ├── __init__.py │ │ │ │ │ ├── _conditional.py │ │ │ │ │ └── binding.py │ │ │ │ └── primitives/ │ │ │ │ ├── __init__.py │ │ │ │ ├── asymmetric/ │ │ │ │ │ ├── __init__.py │ │ │ │ │ ├── dh.py │ │ │ │ │ ├── dsa.py │ │ │ │ │ ├── ec.py │ │ │ │ │ ├── ed25519.py │ │ │ │ │ ├── ed448.py │ │ │ │ │ ├── padding.py │ │ │ │ │ ├── rsa.py │ │ │ │ │ ├── utils.py │ │ │ │ │ ├── x25519.py │ │ │ │ │ └── x448.py │ │ │ │ ├── ciphers/ │ │ │ │ │ ├── __init__.py │ │ │ │ │ ├── aead.py │ │ │ │ │ ├── algorithms.py │ │ │ │ │ ├── base.py │ │ │ │ │ └── modes.py │ │ │ │ ├── cmac.py │ │ │ │ ├── constant_time.py │ │ │ │ ├── hashes.py │ │ │ │ ├── hmac.py │ │ │ │ ├── kdf/ │ │ │ │ │ ├── __init__.py │ │ │ │ │ ├── concatkdf.py │ │ │ │ │ ├── hkdf.py │ │ │ │ │ ├── kbkdf.py │ │ │ │ │ ├── pbkdf2.py │ │ │ │ │ ├── scrypt.py │ │ │ │ │ └── x963kdf.py │ │ │ │ ├── keywrap.py │ │ │ │ ├── padding.py │ │ │ │ ├── poly1305.py │ │ │ │ ├── serialization/ │ │ │ │ │ ├── __init__.py │ │ │ │ │ ├── base.py │ │ │ │ │ ├── pkcs12.py │ │ │ │ │ └── ssh.py │ │ │ │ └── twofactor/ │ │ │ │ ├── __init__.py │ │ │ │ ├── hotp.py │ │ │ │ ├── totp.py │ │ │ │ └── utils.py │ │ │ ├── utils.py │ │ │ └── x509/ │ │ │ ├── __init__.py │ │ │ ├── base.py │ │ │ ├── certificate_transparency.py │ │ │ ├── extensions.py │ │ │ ├── general_name.py │ │ │ ├── name.py │ │ │ ├── ocsp.py │ │ │ └── oid.py │ │ ├── cryptography-2.8.dist-info/ │ │ │ ├── AUTHORS.rst │ │ │ ├── INSTALLER │ │ │ ├── LICENSE │ │ │ ├── LICENSE.APACHE │ │ │ ├── LICENSE.BSD │ │ │ ├── LICENSE.PSF │ │ │ ├── METADATA │ │ │ ├── RECORD │ │ │ ├── WHEEL │ │ │ └── top_level.txt │ │ ├── cssselect/ │ │ │ ├── __init__.py │ │ │ ├── parser.py │ │ │ └── xpath.py │ │ ├── cssselect-1.1.0.dist-info/ │ │ │ ├── AUTHORS │ │ │ ├── INSTALLER │ │ │ ├── LICENSE │ │ │ ├── METADATA │ │ │ ├── RECORD │ │ │ ├── WHEEL │ │ │ └── top_level.txt │ │ ├── easy-install.pth │ │ ├── exampleproj/ │ │ │ ├── __init__.py │ │ │ └── _version.py │ │ ├── gridfs/ │ │ │ ├── __init__.py │ │ │ ├── errors.py │ │ │ └── grid_file.py │ │ ├── hamcrest/ │ │ │ ├── __init__.py │ │ │ ├── core/ │ │ │ │ ├── __init__.py │ │ │ │ ├── assert_that.py │ │ │ │ ├── base_description.py │ │ │ │ ├── base_matcher.py │ │ │ │ ├── compat.py │ │ │ │ ├── core/ │ │ │ │ │ ├── __init__.py │ │ │ │ │ ├── allof.py │ │ │ │ │ ├── anyof.py │ │ │ │ │ ├── described_as.py │ │ │ │ │ ├── is_.py │ │ │ │ │ ├── isanything.py │ │ │ │ │ ├── isequal.py │ │ │ │ │ ├── isinstanceof.py │ │ │ │ │ ├── isnone.py │ │ │ │ │ ├── isnot.py │ │ │ │ │ ├── issame.py │ │ │ │ │ └── raises.py │ │ │ │ ├── description.py │ │ │ │ ├── helpers/ │ │ │ │ │ ├── __init__.py │ │ │ │ │ ├── hasmethod.py │ │ │ │ │ └── wrap_matcher.py │ │ │ │ ├── matcher.py │ │ │ │ ├── selfdescribing.py │ │ │ │ ├── selfdescribingvalue.py │ │ │ │ └── string_description.py │ │ │ └── library/ │ │ │ ├── __init__.py │ │ │ ├── collection/ │ │ │ │ ├── __init__.py │ │ │ │ ├── is_empty.py │ │ │ │ ├── isdict_containing.py │ │ │ │ ├── isdict_containingentries.py │ │ │ │ ├── isdict_containingkey.py │ │ │ │ ├── isdict_containingvalue.py │ │ │ │ ├── isin.py │ │ │ │ ├── issequence_containing.py │ │ │ │ ├── issequence_containinginanyorder.py │ │ │ │ ├── issequence_containinginorder.py │ │ │ │ └── issequence_onlycontaining.py │ │ │ ├── integration/ │ │ │ │ ├── __init__.py │ │ │ │ └── match_equality.py │ │ │ ├── number/ │ │ │ │ ├── __init__.py │ │ │ │ ├── iscloseto.py │ │ │ │ └── ordering_comparison.py │ │ │ ├── object/ │ │ │ │ ├── __init__.py │ │ │ │ ├── haslength.py │ │ │ │ ├── hasproperty.py │ │ │ │ └── hasstring.py │ │ │ └── text/ │ │ │ ├── __init__.py │ │ │ ├── isequal_ignoring_case.py │ │ │ ├── isequal_ignoring_whitespace.py │ │ │ ├── stringcontains.py │ │ │ ├── stringcontainsinorder.py │ │ │ ├── stringendswith.py │ │ │ ├── stringmatches.py │ │ │ ├── stringstartswith.py │ │ │ └── substringmatcher.py │ │ ├── hyperlink/ │ │ │ ├── __init__.py │ │ │ ├── _url.py │ │ │ └── test/ │ │ │ ├── __init__.py │ │ │ ├── common.py │ │ │ ├── test_common.py │ │ │ ├── test_decoded_url.py │ │ │ ├── test_parse.py │ │ │ ├── test_scheme_registration.py │ │ │ └── test_url.py │ │ ├── hyperlink-19.0.0.dist-info/ │ │ │ ├── DESCRIPTION.rst │ │ │ ├── INSTALLER │ │ │ ├── METADATA │ │ │ ├── RECORD │ │ │ ├── WHEEL │ │ │ ├── metadata.json │ │ │ └── top_level.txt │ │ ├── idna/ │ │ │ ├── __init__.py │ │ │ ├── codec.py │ │ │ ├── compat.py │ │ │ ├── core.py │ │ │ ├── idnadata.py │ │ │ ├── intranges.py │ │ │ ├── package_data.py │ │ │ └── uts46data.py │ │ ├── idna-2.8.dist-info/ │ │ │ ├── INSTALLER │ │ │ ├── LICENSE.rst │ │ │ ├── METADATA │ │ │ ├── RECORD │ │ │ ├── WHEEL │ │ │ └── top_level.txt │ │ ├── incremental/ │ │ │ ├── __init__.py │ │ │ ├── _version.py │ │ │ ├── tests/ │ │ │ │ ├── __init__.py │ │ │ │ ├── test_update.py │ │ │ │ └── test_version.py │ │ │ └── update.py │ │ ├── incremental-17.5.0.dist-info/ │ │ │ ├── DESCRIPTION.rst │ │ │ ├── INSTALLER │ │ │ ├── METADATA │ │ │ ├── RECORD │ │ │ ├── WHEEL │ │ │ ├── entry_points.txt │ │ │ ├── metadata.json │ │ │ └── top_level.txt │ │ ├── lxml/ │ │ │ ├── ElementInclude.py │ │ │ ├── __init__.py │ │ │ ├── _elementpath.py │ │ │ ├── builder.py │ │ │ ├── cssselect.py │ │ │ ├── doctestcompare.py │ │ │ ├── etree.h │ │ │ ├── etree_api.h │ │ │ ├── html/ │ │ │ │ ├── ElementSoup.py │ │ │ │ ├── __init__.py │ │ │ │ ├── _diffcommand.py │ │ │ │ ├── _html5builder.py │ │ │ │ ├── _setmixin.py │ │ │ │ ├── builder.py │ │ │ │ ├── clean.py │ │ │ │ ├── defs.py │ │ │ │ ├── diff.py │ │ │ │ ├── formfill.py │ │ │ │ ├── html5parser.py │ │ │ │ ├── soupparser.py │ │ │ │ └── usedoctest.py │ │ │ ├── includes/ │ │ │ │ ├── __init__.pxd │ │ │ │ ├── __init__.py │ │ │ │ ├── c14n.pxd │ │ │ │ ├── config.pxd │ │ │ │ ├── dtdvalid.pxd │ │ │ │ ├── etree_defs.h │ │ │ │ ├── etreepublic.pxd │ │ │ │ ├── htmlparser.pxd │ │ │ │ ├── libexslt/ │ │ │ │ │ ├── exslt.h │ │ │ │ │ ├── exsltconfig.h │ │ │ │ │ └── exsltexports.h │ │ │ │ ├── libxml/ │ │ │ │ │ ├── DOCBparser.h │ │ │ │ │ ├── HTMLparser.h │ │ │ │ │ ├── HTMLtree.h │ │ │ │ │ ├── SAX.h │ │ │ │ │ ├── SAX2.h │ │ │ │ │ ├── c14n.h │ │ │ │ │ ├── catalog.h │ │ │ │ │ ├── chvalid.h │ │ │ │ │ ├── debugXML.h │ │ │ │ │ ├── dict.h │ │ │ │ │ ├── encoding.h │ │ │ │ │ ├── entities.h │ │ │ │ │ ├── globals.h │ │ │ │ │ ├── hash.h │ │ │ │ │ ├── list.h │ │ │ │ │ ├── nanoftp.h │ │ │ │ │ ├── nanohttp.h │ │ │ │ │ ├── parser.h │ │ │ │ │ ├── parserInternals.h │ │ │ │ │ ├── relaxng.h │ │ │ │ │ ├── schemasInternals.h │ │ │ │ │ ├── schematron.h │ │ │ │ │ ├── threads.h │ │ │ │ │ ├── tree.h │ │ │ │ │ ├── uri.h │ │ │ │ │ ├── valid.h │ │ │ │ │ ├── xinclude.h │ │ │ │ │ ├── xlink.h │ │ │ │ │ ├── xmlIO.h │ │ │ │ │ ├── xmlautomata.h │ │ │ │ │ ├── xmlerror.h │ │ │ │ │ ├── xmlexports.h │ │ │ │ │ ├── xmlmemory.h │ │ │ │ │ ├── xmlmodule.h │ │ │ │ │ ├── xmlreader.h │ │ │ │ │ ├── xmlregexp.h │ │ │ │ │ ├── xmlsave.h │ │ │ │ │ ├── xmlschemas.h │ │ │ │ │ ├── xmlschemastypes.h │ │ │ │ │ ├── xmlstring.h │ │ │ │ │ ├── xmlunicode.h │ │ │ │ │ ├── xmlversion.h │ │ │ │ │ ├── xmlwriter.h │ │ │ │ │ ├── xpath.h │ │ │ │ │ ├── xpathInternals.h │ │ │ │ │ └── xpointer.h │ │ │ │ ├── libxslt/ │ │ │ │ │ ├── attributes.h │ │ │ │ │ ├── documents.h │ │ │ │ │ ├── extensions.h │ │ │ │ │ ├── extra.h │ │ │ │ │ ├── functions.h │ │ │ │ │ ├── imports.h │ │ │ │ │ ├── keys.h │ │ │ │ │ ├── namespaces.h │ │ │ │ │ ├── numbersInternals.h │ │ │ │ │ ├── pattern.h │ │ │ │ │ ├── preproc.h │ │ │ │ │ ├── security.h │ │ │ │ │ ├── templates.h │ │ │ │ │ ├── transform.h │ │ │ │ │ ├── variables.h │ │ │ │ │ ├── xslt.h │ │ │ │ │ ├── xsltInternals.h │ │ │ │ │ ├── xsltconfig.h │ │ │ │ │ ├── xsltexports.h │ │ │ │ │ ├── xsltlocale.h │ │ │ │ │ └── xsltutils.h │ │ │ │ ├── lxml-version.h │ │ │ │ ├── relaxng.pxd │ │ │ │ ├── schematron.pxd │ │ │ │ ├── tree.pxd │ │ │ │ ├── uri.pxd │ │ │ │ ├── xinclude.pxd │ │ │ │ ├── xmlerror.pxd │ │ │ │ ├── xmlparser.pxd │ │ │ │ ├── xmlschema.pxd │ │ │ │ ├── xpath.pxd │ │ │ │ └── xslt.pxd │ │ │ ├── isoschematron/ │ │ │ │ ├── __init__.py │ │ │ │ └── resources/ │ │ │ │ ├── rng/ │ │ │ │ │ └── iso-schematron.rng │ │ │ │ └── xsl/ │ │ │ │ ├── RNG2Schtrn.xsl │ │ │ │ ├── XSD2Schtrn.xsl │ │ │ │ └── iso-schematron-xslt1/ │ │ │ │ ├── iso_abstract_expand.xsl │ │ │ │ ├── iso_dsdl_include.xsl │ │ │ │ ├── iso_schematron_message.xsl │ │ │ │ ├── iso_schematron_skeleton_for_xslt1.xsl │ │ │ │ ├── iso_svrl_for_xslt1.xsl │ │ │ │ └── readme.txt │ │ │ ├── lxml.etree.h │ │ │ ├── lxml.etree_api.h │ │ │ ├── pyclasslookup.py │ │ │ ├── sax.py │ │ │ └── usedoctest.py │ │ ├── lxml-4.4.1.dist-info/ │ │ │ ├── INSTALLER │ │ │ ├── METADATA │ │ │ ├── RECORD │ │ │ ├── WHEEL │ │ │ └── top_level.txt │ │ ├── parsel/ │ │ │ ├── __init__.py │ │ │ ├── csstranslator.py │ │ │ ├── selector.py │ │ │ ├── utils.py │ │ │ └── xpathfuncs.py │ │ ├── parsel-1.5.2.dist-info/ │ │ │ ├── INSTALLER │ │ │ ├── LICENSE │ │ │ ├── METADATA │ │ │ ├── RECORD │ │ │ ├── WHEEL │ │ │ └── top_level.txt │ │ ├── pip-19.0.3-py3.6.egg/ │ │ │ ├── EGG-INFO/ │ │ │ │ ├── PKG-INFO │ │ │ │ ├── SOURCES.txt │ │ │ │ ├── dependency_links.txt │ │ │ │ ├── entry_points.txt │ │ │ │ ├── not-zip-safe │ │ │ │ └── top_level.txt │ │ │ └── pip/ │ │ │ ├── __init__.py │ │ │ ├── __main__.py │ │ │ ├── _internal/ │ │ │ │ ├── __init__.py │ │ │ │ ├── build_env.py │ │ │ │ ├── cache.py │ │ │ │ ├── cli/ │ │ │ │ │ ├── __init__.py │ │ │ │ │ ├── autocompletion.py │ │ │ │ │ ├── base_command.py │ │ │ │ │ ├── cmdoptions.py │ │ │ │ │ ├── main_parser.py │ │ │ │ │ ├── parser.py │ │ │ │ │ └── status_codes.py │ │ │ │ ├── commands/ │ │ │ │ │ ├── __init__.py │ │ │ │ │ ├── check.py │ │ │ │ │ ├── completion.py │ │ │ │ │ ├── configuration.py │ │ │ │ │ ├── download.py │ │ │ │ │ ├── freeze.py │ │ │ │ │ ├── hash.py │ │ │ │ │ ├── help.py │ │ │ │ │ ├── install.py │ │ │ │ │ ├── list.py │ │ │ │ │ ├── search.py │ │ │ │ │ ├── show.py │ │ │ │ │ ├── uninstall.py │ │ │ │ │ └── wheel.py │ │ │ │ ├── configuration.py │ │ │ │ ├── download.py │ │ │ │ ├── exceptions.py │ │ │ │ ├── index.py │ │ │ │ ├── locations.py │ │ │ │ ├── models/ │ │ │ │ │ ├── __init__.py │ │ │ │ │ ├── candidate.py │ │ │ │ │ ├── format_control.py │ │ │ │ │ ├── index.py │ │ │ │ │ └── link.py │ │ │ │ ├── operations/ │ │ │ │ │ ├── __init__.py │ │ │ │ │ ├── check.py │ │ │ │ │ ├── freeze.py │ │ │ │ │ └── prepare.py │ │ │ │ ├── pep425tags.py │ │ │ │ ├── pyproject.py │ │ │ │ ├── req/ │ │ │ │ │ ├── __init__.py │ │ │ │ │ ├── constructors.py │ │ │ │ │ ├── req_file.py │ │ │ │ │ ├── req_install.py │ │ │ │ │ ├── req_set.py │ │ │ │ │ ├── req_tracker.py │ │ │ │ │ └── req_uninstall.py │ │ │ │ ├── resolve.py │ │ │ │ ├── utils/ │ │ │ │ │ ├── __init__.py │ │ │ │ │ ├── appdirs.py │ │ │ │ │ ├── compat.py │ │ │ │ │ ├── deprecation.py │ │ │ │ │ ├── encoding.py │ │ │ │ │ ├── filesystem.py │ │ │ │ │ ├── glibc.py │ │ │ │ │ ├── hashes.py │ │ │ │ │ ├── logging.py │ │ │ │ │ ├── misc.py │ │ │ │ │ ├── models.py │ │ │ │ │ ├── outdated.py │ │ │ │ │ ├── packaging.py │ │ │ │ │ ├── setuptools_build.py │ │ │ │ │ ├── temp_dir.py │ │ │ │ │ ├── typing.py │ │ │ │ │ └── ui.py │ │ │ │ ├── vcs/ │ │ │ │ │ ├── __init__.py │ │ │ │ │ ├── bazaar.py │ │ │ │ │ ├── git.py │ │ │ │ │ ├── mercurial.py │ │ │ │ │ └── subversion.py │ │ │ │ └── wheel.py │ │ │ └── _vendor/ │ │ │ ├── __init__.py │ │ │ ├── appdirs.py │ │ │ ├── cachecontrol/ │ │ │ │ ├── __init__.py │ │ │ │ ├── _cmd.py │ │ │ │ ├── adapter.py │ │ │ │ ├── cache.py │ │ │ │ ├── caches/ │ │ │ │ │ ├── __init__.py │ │ │ │ │ ├── file_cache.py │ │ │ │ │ └── redis_cache.py │ │ │ │ ├── compat.py │ │ │ │ ├── controller.py │ │ │ │ ├── filewrapper.py │ │ │ │ ├── heuristics.py │ │ │ │ ├── serialize.py │ │ │ │ └── wrapper.py │ │ │ ├── certifi/ │ │ │ │ ├── __init__.py │ │ │ │ ├── __main__.py │ │ │ │ ├── cacert.pem │ │ │ │ └── core.py │ │ │ ├── chardet/ │ │ │ │ ├── __init__.py │ │ │ │ ├── big5freq.py │ │ │ │ ├── big5prober.py │ │ │ │ ├── chardistribution.py │ │ │ │ ├── charsetgroupprober.py │ │ │ │ ├── charsetprober.py │ │ │ │ ├── cli/ │ │ │ │ │ ├── __init__.py │ │ │ │ │ └── chardetect.py │ │ │ │ ├── codingstatemachine.py │ │ │ │ ├── compat.py │ │ │ │ ├── cp949prober.py │ │ │ │ ├── enums.py │ │ │ │ ├── escprober.py │ │ │ │ ├── escsm.py │ │ │ │ ├── eucjpprober.py │ │ │ │ ├── euckrfreq.py │ │ │ │ ├── euckrprober.py │ │ │ │ ├── euctwfreq.py │ │ │ │ ├── euctwprober.py │ │ │ │ ├── gb2312freq.py │ │ │ │ ├── gb2312prober.py │ │ │ │ ├── hebrewprober.py │ │ │ │ ├── jisfreq.py │ │ │ │ ├── jpcntx.py │ │ │ │ ├── langbulgarianmodel.py │ │ │ │ ├── langcyrillicmodel.py │ │ │ │ ├── langgreekmodel.py │ │ │ │ ├── langhebrewmodel.py │ │ │ │ ├── langhungarianmodel.py │ │ │ │ ├── langthaimodel.py │ │ │ │ ├── langturkishmodel.py │ │ │ │ ├── latin1prober.py │ │ │ │ ├── mbcharsetprober.py │ │ │ │ ├── mbcsgroupprober.py │ │ │ │ ├── mbcssm.py │ │ │ │ ├── sbcharsetprober.py │ │ │ │ ├── sbcsgroupprober.py │ │ │ │ ├── sjisprober.py │ │ │ │ ├── universaldetector.py │ │ │ │ ├── utf8prober.py │ │ │ │ └── version.py │ │ │ ├── colorama/ │ │ │ │ ├── __init__.py │ │ │ │ ├── ansi.py │ │ │ │ ├── ansitowin32.py │ │ │ │ ├── initialise.py │ │ │ │ ├── win32.py │ │ │ │ └── winterm.py │ │ │ ├── distlib/ │ │ │ │ ├── __init__.py │ │ │ │ ├── _backport/ │ │ │ │ │ ├── __init__.py │ │ │ │ │ ├── misc.py │ │ │ │ │ ├── shutil.py │ │ │ │ │ ├── sysconfig.cfg │ │ │ │ │ ├── sysconfig.py │ │ │ │ │ └── tarfile.py │ │ │ │ ├── compat.py │ │ │ │ ├── database.py │ │ │ │ ├── index.py │ │ │ │ ├── locators.py │ │ │ │ ├── manifest.py │ │ │ │ ├── markers.py │ │ │ │ ├── metadata.py │ │ │ │ ├── resources.py │ │ │ │ ├── scripts.py │ │ │ │ ├── util.py │ │ │ │ ├── version.py │ │ │ │ └── wheel.py │ │ │ ├── distro.py │ │ │ ├── html5lib/ │ │ │ │ ├── __init__.py │ │ │ │ ├── _ihatexml.py │ │ │ │ ├── _inputstream.py │ │ │ │ ├── _tokenizer.py │ │ │ │ ├── _trie/ │ │ │ │ │ ├── __init__.py │ │ │ │ │ ├── _base.py │ │ │ │ │ ├── datrie.py │ │ │ │ │ └── py.py │ │ │ │ ├── _utils.py │ │ │ │ ├── constants.py │ │ │ │ ├── filters/ │ │ │ │ │ ├── __init__.py │ │ │ │ │ ├── alphabeticalattributes.py │ │ │ │ │ ├── base.py │ │ │ │ │ ├── inject_meta_charset.py │ │ │ │ │ ├── lint.py │ │ │ │ │ ├── optionaltags.py │ │ │ │ │ ├── sanitizer.py │ │ │ │ │ └── whitespace.py │ │ │ │ ├── html5parser.py │ │ │ │ ├── serializer.py │ │ │ │ ├── treeadapters/ │ │ │ │ │ ├── __init__.py │ │ │ │ │ ├── genshi.py │ │ │ │ │ └── sax.py │ │ │ │ ├── treebuilders/ │ │ │ │ │ ├── __init__.py │ │ │ │ │ ├── base.py │ │ │ │ │ ├── dom.py │ │ │ │ │ ├── etree.py │ │ │ │ │ └── etree_lxml.py │ │ │ │ └── treewalkers/ │ │ │ │ ├── __init__.py │ │ │ │ ├── base.py │ │ │ │ ├── dom.py │ │ │ │ ├── etree.py │ │ │ │ ├── etree_lxml.py │ │ │ │ └── genshi.py │ │ │ ├── idna/ │ │ │ │ ├── __init__.py │ │ │ │ ├── codec.py │ │ │ │ ├── compat.py │ │ │ │ ├── core.py │ │ │ │ ├── idnadata.py │ │ │ │ ├── intranges.py │ │ │ │ ├── package_data.py │ │ │ │ └── uts46data.py │ │ │ ├── ipaddress.py │ │ │ ├── lockfile/ │ │ │ │ ├── __init__.py │ │ │ │ ├── linklockfile.py │ │ │ │ ├── mkdirlockfile.py │ │ │ │ ├── pidlockfile.py │ │ │ │ ├── sqlitelockfile.py │ │ │ │ └── symlinklockfile.py │ │ │ ├── msgpack/ │ │ │ │ ├── __init__.py │ │ │ │ ├── _version.py │ │ │ │ ├── exceptions.py │ │ │ │ └── fallback.py │ │ │ ├── packaging/ │ │ │ │ ├── __about__.py │ │ │ │ ├── __init__.py │ │ │ │ ├── _compat.py │ │ │ │ ├── _structures.py │ │ │ │ ├── markers.py │ │ │ │ ├── requirements.py │ │ │ │ ├── specifiers.py │ │ │ │ ├── utils.py │ │ │ │ └── version.py │ │ │ ├── pep517/ │ │ │ │ ├── __init__.py │ │ │ │ ├── _in_process.py │ │ │ │ ├── build.py │ │ │ │ ├── check.py │ │ │ │ ├── colorlog.py │ │ │ │ ├── compat.py │ │ │ │ ├── envbuild.py │ │ │ │ └── wrappers.py │ │ │ ├── pkg_resources/ │ │ │ │ ├── __init__.py │ │ │ │ └── py31compat.py │ │ │ ├── progress/ │ │ │ │ ├── __init__.py │ │ │ │ ├── bar.py │ │ │ │ ├── counter.py │ │ │ │ ├── helpers.py │ │ │ │ └── spinner.py │ │ │ ├── pyparsing.py │ │ │ ├── pytoml/ │ │ │ │ ├── __init__.py │ │ │ │ ├── core.py │ │ │ │ ├── parser.py │ │ │ │ ├── test.py │ │ │ │ ├── utils.py │ │ │ │ └── writer.py │ │ │ ├── requests/ │ │ │ │ ├── __init__.py │ │ │ │ ├── __version__.py │ │ │ │ ├── _internal_utils.py │ │ │ │ ├── adapters.py │ │ │ │ ├── api.py │ │ │ │ ├── auth.py │ │ │ │ ├── certs.py │ │ │ │ ├── compat.py │ │ │ │ ├── cookies.py │ │ │ │ ├── exceptions.py │ │ │ │ ├── help.py │ │ │ │ ├── hooks.py │ │ │ │ ├── models.py │ │ │ │ ├── packages.py │ │ │ │ ├── sessions.py │ │ │ │ ├── status_codes.py │ │ │ │ ├── structures.py │ │ │ │ └── utils.py │ │ │ ├── retrying.py │ │ │ ├── six.py │ │ │ ├── urllib3/ │ │ │ │ ├── __init__.py │ │ │ │ ├── _collections.py │ │ │ │ ├── connection.py │ │ │ │ ├── connectionpool.py │ │ │ │ ├── contrib/ │ │ │ │ │ ├── __init__.py │ │ │ │ │ ├── _appengine_environ.py │ │ │ │ │ ├── _securetransport/ │ │ │ │ │ │ ├── __init__.py │ │ │ │ │ │ ├── bindings.py │ │ │ │ │ │ └── low_level.py │ │ │ │ │ ├── appengine.py │ │ │ │ │ ├── ntlmpool.py │ │ │ │ │ ├── pyopenssl.py │ │ │ │ │ ├── securetransport.py │ │ │ │ │ └── socks.py │ │ │ │ ├── exceptions.py │ │ │ │ ├── fields.py │ │ │ │ ├── filepost.py │ │ │ │ ├── packages/ │ │ │ │ │ ├── __init__.py │ │ │ │ │ ├── backports/ │ │ │ │ │ │ ├── __init__.py │ │ │ │ │ │ └── makefile.py │ │ │ │ │ ├── six.py │ │ │ │ │ └── ssl_match_hostname/ │ │ │ │ │ ├── __init__.py │ │ │ │ │ └── _implementation.py │ │ │ │ ├── poolmanager.py │ │ │ │ ├── request.py │ │ │ │ ├── response.py │ │ │ │ └── util/ │ │ │ │ ├── __init__.py │ │ │ │ ├── connection.py │ │ │ │ ├── queue.py │ │ │ │ ├── request.py │ │ │ │ ├── response.py │ │ │ │ ├── retry.py │ │ │ │ ├── ssl_.py │ │ │ │ ├── timeout.py │ │ │ │ ├── url.py │ │ │ │ └── wait.py │ │ │ └── webencodings/ │ │ │ ├── __init__.py │ │ │ ├── labels.py │ │ │ ├── mklabels.py │ │ │ ├── tests.py │ │ │ └── x_user_defined.py │ │ ├── pyOpenSSL-19.0.0.dist-info/ │ │ │ ├── INSTALLER │ │ │ ├── LICENSE │ │ │ ├── METADATA │ │ │ ├── RECORD │ │ │ ├── WHEEL │ │ │ └── top_level.txt │ │ ├── pyasn1/ │ │ │ ├── __init__.py │ │ │ ├── codec/ │ │ │ │ ├── __init__.py │ │ │ │ ├── ber/ │ │ │ │ │ ├── __init__.py │ │ │ │ │ ├── decoder.py │ │ │ │ │ ├── encoder.py │ │ │ │ │ └── eoo.py │ │ │ │ ├── cer/ │ │ │ │ │ ├── __init__.py │ │ │ │ │ ├── decoder.py │ │ │ │ │ └── encoder.py │ │ │ │ ├── der/ │ │ │ │ │ ├── __init__.py │ │ │ │ │ ├── decoder.py │ │ │ │ │ └── encoder.py │ │ │ │ └── native/ │ │ │ │ ├── __init__.py │ │ │ │ ├── decoder.py │ │ │ │ └── encoder.py │ │ │ ├── compat/ │ │ │ │ ├── __init__.py │ │ │ │ ├── binary.py │ │ │ │ ├── calling.py │ │ │ │ ├── dateandtime.py │ │ │ │ ├── integer.py │ │ │ │ ├── octets.py │ │ │ │ └── string.py │ │ │ ├── debug.py │ │ │ ├── error.py │ │ │ └── type/ │ │ │ ├── __init__.py │ │ │ ├── base.py │ │ │ ├── char.py │ │ │ ├── constraint.py │ │ │ ├── error.py │ │ │ ├── namedtype.py │ │ │ ├── namedval.py │ │ │ ├── opentype.py │ │ │ ├── tag.py │ │ │ ├── tagmap.py │ │ │ ├── univ.py │ │ │ └── useful.py │ │ ├── pyasn1-0.4.7.dist-info/ │ │ │ ├── INSTALLER │ │ │ ├── LICENSE.rst │ │ │ ├── METADATA │ │ │ ├── RECORD │ │ │ ├── WHEEL │ │ │ ├── top_level.txt │ │ │ └── zip-safe │ │ ├── pyasn1_modules/ │ │ │ ├── __init__.py │ │ │ ├── pem.py │ │ │ ├── rfc1155.py │ │ │ ├── rfc1157.py │ │ │ ├── rfc1901.py │ │ │ ├── rfc1902.py │ │ │ ├── rfc1905.py │ │ │ ├── rfc2251.py │ │ │ ├── rfc2314.py │ │ │ ├── rfc2315.py │ │ │ ├── rfc2437.py │ │ │ ├── rfc2459.py │ │ │ ├── rfc2511.py │ │ │ ├── rfc2560.py │ │ │ ├── rfc2634.py │ │ │ ├── rfc2985.py │ │ │ ├── rfc2986.py │ │ │ ├── rfc3161.py │ │ │ ├── rfc3274.py │ │ │ ├── rfc3279.py │ │ │ ├── rfc3280.py │ │ │ ├── rfc3281.py │ │ │ ├── rfc3412.py │ │ │ ├── rfc3414.py │ │ │ ├── rfc3447.py │ │ │ ├── rfc3560.py │ │ │ ├── rfc3565.py │ │ │ ├── rfc3709.py │ │ │ ├── rfc3770.py │ │ │ ├── rfc3779.py │ │ │ ├── rfc3852.py │ │ │ ├── rfc4055.py │ │ │ ├── rfc4073.py │ │ │ ├── rfc4108.py │ │ │ ├── rfc4210.py │ │ │ ├── rfc4211.py │ │ │ ├── rfc5035.py │ │ │ ├── rfc5083.py │ │ │ ├── rfc5084.py │ │ │ ├── rfc5208.py │ │ │ ├── rfc5280.py │ │ │ ├── rfc5480.py │ │ │ ├── rfc5649.py │ │ │ ├── rfc5652.py │ │ │ ├── rfc5751.py │ │ │ ├── rfc5914.py │ │ │ ├── rfc5915.py │ │ │ ├── rfc5934.py │ │ │ ├── rfc5940.py │ │ │ ├── rfc5958.py │ │ │ ├── rfc5990.py │ │ │ ├── rfc6010.py │ │ │ ├── rfc6019.py │ │ │ ├── rfc6031.py │ │ │ ├── rfc6032.py │ │ │ ├── rfc6210.py │ │ │ ├── rfc6211.py │ │ │ ├── rfc6402.py │ │ │ ├── rfc7030.py │ │ │ ├── rfc7191.py │ │ │ ├── rfc7292.py │ │ │ ├── rfc7296.py │ │ │ ├── rfc7773.py │ │ │ ├── rfc7894.py │ │ │ ├── rfc7906.py │ │ │ ├── rfc7914.py │ │ │ ├── rfc8017.py │ │ │ ├── rfc8018.py │ │ │ ├── rfc8103.py │ │ │ ├── rfc8209.py │ │ │ ├── rfc8226.py │ │ │ ├── rfc8358.py │ │ │ ├── rfc8360.py │ │ │ ├── rfc8398.py │ │ │ ├── rfc8410.py │ │ │ ├── rfc8418.py │ │ │ ├── rfc8419.py │ │ │ ├── rfc8479.py │ │ │ ├── rfc8494.py │ │ │ ├── rfc8520.py │ │ │ ├── rfc8619.py │ │ │ └── rfc8649.py │ │ ├── pyasn1_modules-0.2.7.dist-info/ │ │ │ ├── DESCRIPTION.rst │ │ │ ├── INSTALLER │ │ │ ├── LICENSE.txt │ │ │ ├── METADATA │ │ │ ├── RECORD │ │ │ ├── WHEEL │ │ │ ├── metadata.json │ │ │ ├── top_level.txt │ │ │ └── zip-safe │ │ ├── pycparser/ │ │ │ ├── __init__.py │ │ │ ├── _ast_gen.py │ │ │ ├── _build_tables.py │ │ │ ├── _c_ast.cfg │ │ │ ├── ast_transforms.py │ │ │ ├── c_ast.py │ │ │ ├── c_generator.py │ │ │ ├── c_lexer.py │ │ │ ├── c_parser.py │ │ │ ├── lextab.py │ │ │ ├── ply/ │ │ │ │ ├── __init__.py │ │ │ │ ├── cpp.py │ │ │ │ ├── ctokens.py │ │ │ │ ├── lex.py │ │ │ │ ├── yacc.py │ │ │ │ └── ygen.py │ │ │ ├── plyparser.py │ │ │ └── yacctab.py │ │ ├── pycparser-2.19-py3.6.egg-info/ │ │ │ ├── PKG-INFO │ │ │ ├── SOURCES.txt │ │ │ ├── dependency_links.txt │ │ │ ├── installed-files.txt │ │ │ └── top_level.txt │ │ ├── pydispatch/ │ │ │ ├── __init__.py │ │ │ ├── dispatcher.py │ │ │ ├── errors.py │ │ │ ├── robust.py │ │ │ ├── robustapply.py │ │ │ └── saferef.py │ │ ├── pymongo/ │ │ │ ├── __init__.py │ │ │ ├── aggregation.py │ │ │ ├── auth.py │ │ │ ├── bulk.py │ │ │ ├── change_stream.py │ │ │ ├── client_options.py │ │ │ ├── client_session.py │ │ │ ├── collation.py │ │ │ ├── collection.py │ │ │ ├── command_cursor.py │ │ │ ├── common.py │ │ │ ├── compression_support.py │ │ │ ├── cursor.py │ │ │ ├── cursor_manager.py │ │ │ ├── database.py │ │ │ ├── driver_info.py │ │ │ ├── encryption.py │ │ │ ├── encryption_options.py │ │ │ ├── errors.py │ │ │ ├── helpers.py │ │ │ ├── ismaster.py │ │ │ ├── max_staleness_selectors.py │ │ │ ├── message.py │ │ │ ├── mongo_client.py │ │ │ ├── mongo_replica_set_client.py │ │ │ ├── monitor.py │ │ │ ├── monitoring.py │ │ │ ├── monotonic.py │ │ │ ├── network.py │ │ │ ├── operations.py │ │ │ ├── periodic_executor.py │ │ │ ├── pool.py │ │ │ ├── read_concern.py │ │ │ ├── read_preferences.py │ │ │ ├── response.py │ │ │ ├── results.py │ │ │ ├── saslprep.py │ │ │ ├── server.py │ │ │ ├── server_description.py │ │ │ ├── server_selectors.py │ │ │ ├── server_type.py │ │ │ ├── settings.py │ │ │ ├── son_manipulator.py │ │ │ ├── srv_resolver.py │ │ │ ├── ssl_context.py │ │ │ ├── ssl_match_hostname.py │ │ │ ├── ssl_support.py │ │ │ ├── thread_util.py │ │ │ ├── topology.py │ │ │ ├── topology_description.py │ │ │ ├── uri_parser.py │ │ │ └── write_concern.py │ │ ├── pymongo-3.9.0.dist-info/ │ │ │ ├── INSTALLER │ │ │ ├── METADATA │ │ │ ├── RECORD │ │ │ ├── WHEEL │ │ │ └── top_level.txt │ │ ├── queuelib/ │ │ │ ├── __init__.py │ │ │ ├── pqueue.py │ │ │ ├── queue.py │ │ │ ├── rrqueue.py │ │ │ └── tests/ │ │ │ ├── __init__.py │ │ │ ├── test_pqueue.py │ │ │ ├── test_queue.py │ │ │ └── test_rrqueue.py │ │ ├── queuelib-1.5.0.dist-info/ │ │ │ ├── DESCRIPTION.rst │ │ │ ├── INSTALLER │ │ │ ├── METADATA │ │ │ ├── RECORD │ │ │ ├── WHEEL │ │ │ ├── metadata.json │ │ │ └── top_level.txt │ │ ├── redis/ │ │ │ ├── __init__.py │ │ │ ├── _compat.py │ │ │ ├── client.py │ │ │ ├── connection.py │ │ │ ├── exceptions.py │ │ │ ├── lock.py │ │ │ ├── sentinel.py │ │ │ └── utils.py │ │ ├── redis-3.3.11.dist-info/ │ │ │ ├── INSTALLER │ │ │ ├── LICENSE │ │ │ ├── METADATA │ │ │ ├── RECORD │ │ │ ├── WHEEL │ │ │ └── top_level.txt │ │ ├── scrapy/ │ │ │ ├── VERSION │ │ │ ├── __init__.py │ │ │ ├── __main__.py │ │ │ ├── _monkeypatches.py │ │ │ ├── cmdline.py │ │ │ ├── commands/ │ │ │ │ ├── __init__.py │ │ │ │ ├── bench.py │ │ │ │ ├── check.py │ │ │ │ ├── crawl.py │ │ │ │ ├── edit.py │ │ │ │ ├── fetch.py │ │ │ │ ├── genspider.py │ │ │ │ ├── list.py │ │ │ │ ├── parse.py │ │ │ │ ├── runspider.py │ │ │ │ ├── settings.py │ │ │ │ ├── shell.py │ │ │ │ ├── startproject.py │ │ │ │ ├── version.py │ │ │ │ └── view.py │ │ │ ├── contracts/ │ │ │ │ ├── __init__.py │ │ │ │ └── default.py │ │ │ ├── core/ │ │ │ │ ├── __init__.py │ │ │ │ ├── downloader/ │ │ │ │ │ ├── __init__.py │ │ │ │ │ ├── contextfactory.py │ │ │ │ │ ├── handlers/ │ │ │ │ │ │ ├── __init__.py │ │ │ │ │ │ ├── datauri.py │ │ │ │ │ │ ├── file.py │ │ │ │ │ │ ├── ftp.py │ │ │ │ │ │ ├── http.py │ │ │ │ │ │ ├── http10.py │ │ │ │ │ │ ├── http11.py │ │ │ │ │ │ └── s3.py │ │ │ │ │ ├── middleware.py │ │ │ │ │ ├── tls.py │ │ │ │ │ └── webclient.py │ │ │ │ ├── engine.py │ │ │ │ ├── scheduler.py │ │ │ │ ├── scraper.py │ │ │ │ └── spidermw.py │ │ │ ├── crawler.py │ │ │ ├── downloadermiddlewares/ │ │ │ │ ├── __init__.py │ │ │ │ ├── ajaxcrawl.py │ │ │ │ ├── chunked.py │ │ │ │ ├── cookies.py │ │ │ │ ├── decompression.py │ │ │ │ ├── defaultheaders.py │ │ │ │ ├── downloadtimeout.py │ │ │ │ ├── httpauth.py │ │ │ │ ├── httpcache.py │ │ │ │ ├── httpcompression.py │ │ │ │ ├── httpproxy.py │ │ │ │ ├── redirect.py │ │ │ │ ├── retry.py │ │ │ │ ├── robotstxt.py │ │ │ │ ├── stats.py │ │ │ │ └── useragent.py │ │ │ ├── dupefilters.py │ │ │ ├── exceptions.py │ │ │ ├── exporters.py │ │ │ ├── extension.py │ │ │ ├── extensions/ │ │ │ │ ├── __init__.py │ │ │ │ ├── closespider.py │ │ │ │ ├── corestats.py │ │ │ │ ├── debug.py │ │ │ │ ├── feedexport.py │ │ │ │ ├── httpcache.py │ │ │ │ ├── logstats.py │ │ │ │ ├── memdebug.py │ │ │ │ ├── memusage.py │ │ │ │ ├── spiderstate.py │ │ │ │ ├── statsmailer.py │ │ │ │ ├── telnet.py │ │ │ │ └── throttle.py │ │ │ ├── http/ │ │ │ │ ├── __init__.py │ │ │ │ ├── common.py │ │ │ │ ├── cookies.py │ │ │ │ ├── headers.py │ │ │ │ ├── request/ │ │ │ │ │ ├── __init__.py │ │ │ │ │ ├── form.py │ │ │ │ │ ├── json_request.py │ │ │ │ │ └── rpc.py │ │ │ │ └── response/ │ │ │ │ ├── __init__.py │ │ │ │ ├── html.py │ │ │ │ ├── text.py │ │ │ │ └── xml.py │ │ │ ├── interfaces.py │ │ │ ├── item.py │ │ │ ├── link.py │ │ │ ├── linkextractors/ │ │ │ │ ├── __init__.py │ │ │ │ ├── htmlparser.py │ │ │ │ ├── lxmlhtml.py │ │ │ │ ├── regex.py │ │ │ │ └── sgml.py │ │ │ ├── loader/ │ │ │ │ ├── __init__.py │ │ │ │ ├── common.py │ │ │ │ └── processors.py │ │ │ ├── logformatter.py │ │ │ ├── mail.py │ │ │ ├── middleware.py │ │ │ ├── mime.types │ │ │ ├── pipelines/ │ │ │ │ ├── __init__.py │ │ │ │ ├── files.py │ │ │ │ ├── images.py │ │ │ │ └── media.py │ │ │ ├── pqueues.py │ │ │ ├── resolver.py │ │ │ ├── responsetypes.py │ │ │ ├── selector/ │ │ │ │ ├── __init__.py │ │ │ │ └── unified.py │ │ │ ├── settings/ │ │ │ │ ├── __init__.py │ │ │ │ ├── default_settings.py │ │ │ │ └── deprecated.py │ │ │ ├── shell.py │ │ │ ├── signalmanager.py │ │ │ ├── signals.py │ │ │ ├── spiderloader.py │ │ │ ├── spidermiddlewares/ │ │ │ │ ├── __init__.py │ │ │ │ ├── depth.py │ │ │ │ ├── httperror.py │ │ │ │ ├── offsite.py │ │ │ │ ├── referer.py │ │ │ │ └── urllength.py │ │ │ ├── spiders/ │ │ │ │ ├── __init__.py │ │ │ │ ├── crawl.py │ │ │ │ ├── feed.py │ │ │ │ ├── init.py │ │ │ │ └── sitemap.py │ │ │ ├── squeues.py │ │ │ ├── statscollectors.py │ │ │ ├── templates/ │ │ │ │ ├── project/ │ │ │ │ │ ├── module/ │ │ │ │ │ │ ├── __init__.py │ │ │ │ │ │ ├── items.py.tmpl │ │ │ │ │ │ ├── middlewares.py.tmpl │ │ │ │ │ │ ├── pipelines.py.tmpl │ │ │ │ │ │ ├── settings.py.tmpl │ │ │ │ │ │ └── spiders/ │ │ │ │ │ │ └── __init__.py │ │ │ │ │ └── scrapy.cfg │ │ │ │ └── spiders/ │ │ │ │ ├── basic.tmpl │ │ │ │ ├── crawl.tmpl │ │ │ │ ├── csvfeed.tmpl │ │ │ │ └── xmlfeed.tmpl │ │ │ ├── utils/ │ │ │ │ ├── __init__.py │ │ │ │ ├── benchserver.py │ │ │ │ ├── boto.py │ │ │ │ ├── conf.py │ │ │ │ ├── console.py │ │ │ │ ├── datatypes.py │ │ │ │ ├── decorators.py │ │ │ │ ├── defer.py │ │ │ │ ├── deprecate.py │ │ │ │ ├── display.py │ │ │ │ ├── engine.py │ │ │ │ ├── ftp.py │ │ │ │ ├── gz.py │ │ │ │ ├── http.py │ │ │ │ ├── httpobj.py │ │ │ │ ├── iterators.py │ │ │ │ ├── job.py │ │ │ │ ├── log.py │ │ │ │ ├── markup.py │ │ │ │ ├── misc.py │ │ │ │ ├── multipart.py │ │ │ │ ├── ossignal.py │ │ │ │ ├── project.py │ │ │ │ ├── python.py │ │ │ │ ├── reactor.py │ │ │ │ ├── reqser.py │ │ │ │ ├── request.py │ │ │ │ ├── response.py │ │ │ │ ├── serialize.py │ │ │ │ ├── signal.py │ │ │ │ ├── sitemap.py │ │ │ │ ├── spider.py │ │ │ │ ├── template.py │ │ │ │ ├── test.py │ │ │ │ ├── testproc.py │ │ │ │ ├── testsite.py │ │ │ │ ├── trackref.py │ │ │ │ ├── url.py │ │ │ │ └── versions.py │ │ │ └── xlib/ │ │ │ ├── __init__.py │ │ │ ├── pydispatch.py │ │ │ └── tx.py │ │ ├── scrapy_redis/ │ │ │ ├── __init__.py │ │ │ ├── connection.py │ │ │ ├── defaults.py │ │ │ ├── dupefilter.py │ │ │ ├── picklecompat.py │ │ │ ├── pipelines.py │ │ │ ├── queue.py │ │ │ ├── scheduler.py │ │ │ ├── spiders.py │ │ │ └── utils.py │ │ ├── scrapy_redis-0.6.8.dist-info/ │ │ │ ├── DESCRIPTION.rst │ │ │ ├── INSTALLER │ │ │ ├── METADATA │ │ │ ├── RECORD │ │ │ ├── WHEEL │ │ │ ├── metadata.json │ │ │ └── top_level.txt │ │ ├── service_identity/ │ │ │ ├── __init__.py │ │ │ ├── _common.py │ │ │ ├── _compat.py │ │ │ ├── cryptography.py │ │ │ ├── exceptions.py │ │ │ └── pyopenssl.py │ │ ├── service_identity-18.1.0.dist-info/ │ │ │ ├── INSTALLER │ │ │ ├── LICENSE │ │ │ ├── METADATA │ │ │ ├── RECORD │ │ │ ├── WHEEL │ │ │ └── top_level.txt │ │ ├── setuptools-40.8.0-py3.6.egg │ │ ├── setuptools.pth │ │ ├── six-1.12.0.dist-info/ │ │ │ ├── INSTALLER │ │ │ ├── LICENSE │ │ │ ├── METADATA │ │ │ ├── RECORD │ │ │ ├── WHEEL │ │ │ └── top_level.txt │ │ ├── six.py │ │ ├── twisted/ │ │ │ ├── __init__.py │ │ │ ├── __main__.py │ │ │ ├── _threads/ │ │ │ │ ├── __init__.py │ │ │ │ ├── _convenience.py │ │ │ │ ├── _ithreads.py │ │ │ │ ├── _memory.py │ │ │ │ ├── _pool.py │ │ │ │ ├── _team.py │ │ │ │ ├── _threadworker.py │ │ │ │ └── test/ │ │ │ │ ├── __init__.py │ │ │ │ ├── test_convenience.py │ │ │ │ ├── test_memory.py │ │ │ │ ├── test_team.py │ │ │ │ └── test_threadworker.py │ │ │ ├── _version.py │ │ │ ├── application/ │ │ │ │ ├── __init__.py │ │ │ │ ├── app.py │ │ │ │ ├── internet.py │ │ │ │ ├── reactors.py │ │ │ │ ├── runner/ │ │ │ │ │ ├── __init__.py │ │ │ │ │ ├── _exit.py │ │ │ │ │ ├── _pidfile.py │ │ │ │ │ ├── _runner.py │ │ │ │ │ └── test/ │ │ │ │ │ ├── __init__.py │ │ │ │ │ ├── test_exit.py │ │ │ │ │ ├── test_pidfile.py │ │ │ │ │ └── test_runner.py │ │ │ │ ├── service.py │ │ │ │ ├── strports.py │ │ │ │ ├── test/ │ │ │ │ │ ├── __init__.py │ │ │ │ │ ├── test_internet.py │ │ │ │ │ └── test_service.py │ │ │ │ └── twist/ │ │ │ │ ├── __init__.py │ │ │ │ ├── _options.py │ │ │ │ ├── _twist.py │ │ │ │ └── test/ │ │ │ │ ├── __init__.py │ │ │ │ ├── test_options.py │ │ │ │ └── test_twist.py │ │ │ ├── conch/ │ │ │ │ ├── __init__.py │ │ │ │ ├── avatar.py │ │ │ │ ├── checkers.py │ │ │ │ ├── client/ │ │ │ │ │ ├── __init__.py │ │ │ │ │ ├── agent.py │ │ │ │ │ ├── connect.py │ │ │ │ │ ├── default.py │ │ │ │ │ ├── direct.py │ │ │ │ │ ├── knownhosts.py │ │ │ │ │ └── options.py │ │ │ │ ├── endpoints.py │ │ │ │ ├── error.py │ │ │ │ ├── insults/ │ │ │ │ │ ├── __init__.py │ │ │ │ │ ├── helper.py │ │ │ │ │ ├── insults.py │ │ │ │ │ ├── text.py │ │ │ │ │ └── window.py │ │ │ │ ├── interfaces.py │ │ │ │ ├── ls.py │ │ │ │ ├── manhole.py │ │ │ │ ├── manhole_ssh.py │ │ │ │ ├── manhole_tap.py │ │ │ │ ├── mixin.py │ │ │ │ ├── openssh_compat/ │ │ │ │ │ ├── __init__.py │ │ │ │ │ ├── factory.py │ │ │ │ │ └── primes.py │ │ │ │ ├── recvline.py │ │ │ │ ├── scripts/ │ │ │ │ │ ├── __init__.py │ │ │ │ │ ├── cftp.py │ │ │ │ │ ├── ckeygen.py │ │ │ │ │ ├── conch.py │ │ │ │ │ └── tkconch.py │ │ │ │ ├── ssh/ │ │ │ │ │ ├── __init__.py │ │ │ │ │ ├── _kex.py │ │ │ │ │ ├── address.py │ │ │ │ │ ├── agent.py │ │ │ │ │ ├── channel.py │ │ │ │ │ ├── common.py │ │ │ │ │ ├── connection.py │ │ │ │ │ ├── factory.py │ │ │ │ │ ├── filetransfer.py │ │ │ │ │ ├── forwarding.py │ │ │ │ │ ├── keys.py │ │ │ │ │ ├── service.py │ │ │ │ │ ├── session.py │ │ │ │ │ ├── sexpy.py │ │ │ │ │ ├── transport.py │ │ │ │ │ └── userauth.py │ │ │ │ ├── stdio.py │ │ │ │ ├── tap.py │ │ │ │ ├── telnet.py │ │ │ │ ├── test/ │ │ │ │ │ ├── __init__.py │ │ │ │ │ ├── keydata.py │ │ │ │ │ ├── loopback.py │ │ │ │ │ ├── test_address.py │ │ │ │ │ ├── test_agent.py │ │ │ │ │ ├── test_cftp.py │ │ │ │ │ ├── test_channel.py │ │ │ │ │ ├── test_checkers.py │ │ │ │ │ ├── test_ckeygen.py │ │ │ │ │ ├── test_conch.py │ │ │ │ │ ├── test_connection.py │ │ │ │ │ ├── test_default.py │ │ │ │ │ ├── test_endpoints.py │ │ │ │ │ ├── test_filetransfer.py │ │ │ │ │ ├── test_forwarding.py │ │ │ │ │ ├── test_helper.py │ │ │ │ │ ├── test_insults.py │ │ │ │ │ ├── test_keys.py │ │ │ │ │ ├── test_knownhosts.py │ │ │ │ │ ├── test_manhole.py │ │ │ │ │ ├── test_manhole_tap.py │ │ │ │ │ ├── test_mixin.py │ │ │ │ │ ├── test_openssh_compat.py │ │ │ │ │ ├── test_recvline.py │ │ │ │ │ ├── test_scripts.py │ │ │ │ │ ├── test_session.py │ │ │ │ │ ├── test_ssh.py │ │ │ │ │ ├── test_tap.py │ │ │ │ │ ├── test_telnet.py │ │ │ │ │ ├── test_text.py │ │ │ │ │ ├── test_transport.py │ │ │ │ │ ├── test_unix.py │ │ │ │ │ ├── test_userauth.py │ │ │ │ │ └── test_window.py │ │ │ │ ├── ttymodes.py │ │ │ │ ├── ui/ │ │ │ │ │ ├── __init__.py │ │ │ │ │ ├── ansi.py │ │ │ │ │ └── tkvt100.py │ │ │ │ └── unix.py │ │ │ ├── copyright.py │ │ │ ├── cred/ │ │ │ │ ├── __init__.py │ │ │ │ ├── _digest.py │ │ │ │ ├── checkers.py │ │ │ │ ├── credentials.py │ │ │ │ ├── error.py │ │ │ │ ├── portal.py │ │ │ │ ├── strcred.py │ │ │ │ └── test/ │ │ │ │ ├── __init__.py │ │ │ │ ├── test_cramauth.py │ │ │ │ ├── test_cred.py │ │ │ │ ├── test_digestauth.py │ │ │ │ ├── test_simpleauth.py │ │ │ │ └── test_strcred.py │ │ │ ├── enterprise/ │ │ │ │ ├── __init__.py │ │ │ │ └── adbapi.py │ │ │ ├── internet/ │ │ │ │ ├── __init__.py │ │ │ │ ├── _baseprocess.py │ │ │ │ ├── _dumbwin32proc.py │ │ │ │ ├── _glibbase.py │ │ │ │ ├── _idna.py │ │ │ │ ├── _newtls.py │ │ │ │ ├── _pollingfile.py │ │ │ │ ├── _posixserialport.py │ │ │ │ ├── _posixstdio.py │ │ │ │ ├── _producer_helpers.py │ │ │ │ ├── _resolver.py │ │ │ │ ├── _signals.py │ │ │ │ ├── _sslverify.py │ │ │ │ ├── _threadedselect.py │ │ │ │ ├── _win32serialport.py │ │ │ │ ├── _win32stdio.py │ │ │ │ ├── abstract.py │ │ │ │ ├── address.py │ │ │ │ ├── asyncioreactor.py │ │ │ │ ├── base.py │ │ │ │ ├── cfreactor.py │ │ │ │ ├── default.py │ │ │ │ ├── defer.py │ │ │ │ ├── endpoints.py │ │ │ │ ├── epollreactor.py │ │ │ │ ├── error.py │ │ │ │ ├── fdesc.py │ │ │ │ ├── gireactor.py │ │ │ │ ├── glib2reactor.py │ │ │ │ ├── gtk2reactor.py │ │ │ │ ├── gtk3reactor.py │ │ │ │ ├── inotify.py │ │ │ │ ├── interfaces.py │ │ │ │ ├── iocpreactor/ │ │ │ │ │ ├── __init__.py │ │ │ │ │ ├── abstract.py │ │ │ │ │ ├── const.py │ │ │ │ │ ├── interfaces.py │ │ │ │ │ ├── notes.txt │ │ │ │ │ ├── reactor.py │ │ │ │ │ ├── setup.py │ │ │ │ │ ├── tcp.py │ │ │ │ │ └── udp.py │ │ │ │ ├── kqreactor.py │ │ │ │ ├── main.py │ │ │ │ ├── pollreactor.py │ │ │ │ ├── posixbase.py │ │ │ │ ├── process.py │ │ │ │ ├── protocol.py │ │ │ │ ├── pyuisupport.py │ │ │ │ ├── reactor.py │ │ │ │ ├── selectreactor.py │ │ │ │ ├── serialport.py │ │ │ │ ├── ssl.py │ │ │ │ ├── stdio.py │ │ │ │ ├── task.py │ │ │ │ ├── tcp.py │ │ │ │ ├── test/ │ │ │ │ │ ├── __init__.py │ │ │ │ │ ├── _awaittests.py.3only │ │ │ │ │ ├── _posixifaces.py │ │ │ │ │ ├── _win32ifaces.py │ │ │ │ │ ├── _yieldfromtests.py.3only │ │ │ │ │ ├── connectionmixins.py │ │ │ │ │ ├── fake_CAs/ │ │ │ │ │ │ ├── chain.pem │ │ │ │ │ │ ├── not-a-certificate │ │ │ │ │ │ ├── thing1.pem │ │ │ │ │ │ ├── thing2-duplicate.pem │ │ │ │ │ │ └── thing2.pem │ │ │ │ │ ├── fakeendpoint.py │ │ │ │ │ ├── modulehelpers.py │ │ │ │ │ ├── process_cli.py │ │ │ │ │ ├── process_connectionlost.py │ │ │ │ │ ├── process_gireactornocompat.py │ │ │ │ │ ├── process_helper.py │ │ │ │ │ ├── reactormixins.py │ │ │ │ │ ├── test_abstract.py │ │ │ │ │ ├── test_address.py │ │ │ │ │ ├── test_asyncioreactor.py │ │ │ │ │ ├── test_base.py │ │ │ │ │ ├── test_baseprocess.py │ │ │ │ │ ├── test_core.py │ │ │ │ │ ├── test_coroutines.py │ │ │ │ │ ├── test_default.py │ │ │ │ │ ├── test_endpoints.py │ │ │ │ │ ├── test_epollreactor.py │ │ │ │ │ ├── test_error.py │ │ │ │ │ ├── test_fdset.py │ │ │ │ │ ├── test_filedescriptor.py │ │ │ │ │ ├── test_gireactor.py │ │ │ │ │ ├── test_glibbase.py │ │ │ │ │ ├── test_inlinecb.py │ │ │ │ │ ├── test_inotify.py │ │ │ │ │ ├── test_iocp.py │ │ │ │ │ ├── test_kqueuereactor.py │ │ │ │ │ ├── test_main.py │ │ │ │ │ ├── test_newtls.py │ │ │ │ │ ├── test_pollingfile.py │ │ │ │ │ ├── test_posixbase.py │ │ │ │ │ ├── test_posixprocess.py │ │ │ │ │ ├── test_process.py │ │ │ │ │ ├── test_protocol.py │ │ │ │ │ ├── test_resolver.py │ │ │ │ │ ├── test_serialport.py │ │ │ │ │ ├── test_sigchld.py │ │ │ │ │ ├── test_socket.py │ │ │ │ │ ├── test_stdio.py │ │ │ │ │ ├── test_tcp.py │ │ │ │ │ ├── test_testing.py │ │ │ │ │ ├── test_threads.py │ │ │ │ │ ├── test_time.py │ │ │ │ │ ├── test_tls.py │ │ │ │ │ ├── test_udp.py │ │ │ │ │ ├── test_udp_internals.py │ │ │ │ │ ├── test_unix.py │ │ │ │ │ ├── test_win32events.py │ │ │ │ │ └── test_win32serialport.py │ │ │ │ ├── testing.py │ │ │ │ ├── threads.py │ │ │ │ ├── tksupport.py │ │ │ │ ├── udp.py │ │ │ │ ├── unix.py │ │ │ │ ├── utils.py │ │ │ │ ├── win32eventreactor.py │ │ │ │ ├── wxreactor.py │ │ │ │ └── wxsupport.py │ │ │ ├── logger/ │ │ │ │ ├── __init__.py │ │ │ │ ├── _buffer.py │ │ │ │ ├── _capture.py │ │ │ │ ├── _file.py │ │ │ │ ├── _filter.py │ │ │ │ ├── _flatten.py │ │ │ │ ├── _format.py │ │ │ │ ├── _global.py │ │ │ │ ├── _io.py │ │ │ │ ├── _json.py │ │ │ │ ├── _legacy.py │ │ │ │ ├── _levels.py │ │ │ │ ├── _logger.py │ │ │ │ ├── _observer.py │ │ │ │ ├── _stdlib.py │ │ │ │ ├── _util.py │ │ │ │ └── test/ │ │ │ │ ├── __init__.py │ │ │ │ ├── test_buffer.py │ │ │ │ ├── test_capture.py │ │ │ │ ├── test_file.py │ │ │ │ ├── test_filter.py │ │ │ │ ├── test_flatten.py │ │ │ │ ├── test_format.py │ │ │ │ ├── test_global.py │ │ │ │ ├── test_io.py │ │ │ │ ├── test_json.py │ │ │ │ ├── test_legacy.py │ │ │ │ ├── test_levels.py │ │ │ │ ├── test_logger.py │ │ │ │ ├── test_observer.py │ │ │ │ ├── test_stdlib.py │ │ │ │ └── test_util.py │ │ │ ├── mail/ │ │ │ │ ├── __init__.py │ │ │ │ ├── _cred.py │ │ │ │ ├── _except.py │ │ │ │ ├── imap4.py │ │ │ │ ├── interfaces.py │ │ │ │ ├── pop3.py │ │ │ │ ├── pop3client.py │ │ │ │ ├── protocols.py │ │ │ │ ├── relay.py │ │ │ │ ├── scripts/ │ │ │ │ │ └── mailmail.py │ │ │ │ ├── smtp.py │ │ │ │ └── test/ │ │ │ │ ├── __init__.py │ │ │ │ ├── pop3testserver.py │ │ │ │ ├── rfc822.message │ │ │ │ ├── test_imap.py │ │ │ │ ├── test_mailmail.py │ │ │ │ ├── test_pop3.py │ │ │ │ ├── test_pop3client.py │ │ │ │ └── test_smtp.py │ │ │ ├── names/ │ │ │ │ ├── __init__.py │ │ │ │ ├── _rfc1982.py │ │ │ │ ├── authority.py │ │ │ │ ├── cache.py │ │ │ │ ├── client.py │ │ │ │ ├── common.py │ │ │ │ ├── dns.py │ │ │ │ ├── error.py │ │ │ │ ├── hosts.py │ │ │ │ ├── resolve.py │ │ │ │ ├── root.py │ │ │ │ ├── secondary.py │ │ │ │ ├── server.py │ │ │ │ ├── srvconnect.py │ │ │ │ ├── tap.py │ │ │ │ └── test/ │ │ │ │ ├── __init__.py │ │ │ │ ├── test_cache.py │ │ │ │ ├── test_client.py │ │ │ │ ├── test_common.py │ │ │ │ ├── test_dns.py │ │ │ │ ├── test_examples.py │ │ │ │ ├── test_hosts.py │ │ │ │ ├── test_names.py │ │ │ │ ├── test_resolve.py │ │ │ │ ├── test_rfc1982.py │ │ │ │ ├── test_rootresolve.py │ │ │ │ ├── test_server.py │ │ │ │ ├── test_srvconnect.py │ │ │ │ ├── test_tap.py │ │ │ │ └── test_util.py │ │ │ ├── pair/ │ │ │ │ ├── __init__.py │ │ │ │ ├── ethernet.py │ │ │ │ ├── ip.py │ │ │ │ ├── raw.py │ │ │ │ ├── rawudp.py │ │ │ │ ├── test/ │ │ │ │ │ ├── __init__.py │ │ │ │ │ ├── test_ethernet.py │ │ │ │ │ ├── test_ip.py │ │ │ │ │ ├── test_rawudp.py │ │ │ │ │ └── test_tuntap.py │ │ │ │ ├── testing.py │ │ │ │ └── tuntap.py │ │ │ ├── persisted/ │ │ │ │ ├── __init__.py │ │ │ │ ├── aot.py │ │ │ │ ├── crefutil.py │ │ │ │ ├── dirdbm.py │ │ │ │ ├── sob.py │ │ │ │ ├── styles.py │ │ │ │ └── test/ │ │ │ │ ├── __init__.py │ │ │ │ └── test_styles.py │ │ │ ├── plugin.py │ │ │ ├── plugins/ │ │ │ │ ├── __init__.py │ │ │ │ ├── cred_anonymous.py │ │ │ │ ├── cred_file.py │ │ │ │ ├── cred_memory.py │ │ │ │ ├── cred_sshkeys.py │ │ │ │ ├── cred_unix.py │ │ │ │ ├── twisted_conch.py │ │ │ │ ├── twisted_core.py │ │ │ │ ├── twisted_ftp.py │ │ │ │ ├── twisted_inet.py │ │ │ │ ├── twisted_names.py │ │ │ │ ├── twisted_portforward.py │ │ │ │ ├── twisted_reactors.py │ │ │ │ ├── twisted_runner.py │ │ │ │ ├── twisted_socks.py │ │ │ │ ├── twisted_trial.py │ │ │ │ ├── twisted_web.py │ │ │ │ └── twisted_words.py │ │ │ ├── positioning/ │ │ │ │ ├── __init__.py │ │ │ │ ├── _sentence.py │ │ │ │ ├── base.py │ │ │ │ ├── ipositioning.py │ │ │ │ ├── nmea.py │ │ │ │ └── test/ │ │ │ │ ├── __init__.py │ │ │ │ ├── receiver.py │ │ │ │ ├── test_base.py │ │ │ │ ├── test_nmea.py │ │ │ │ └── test_sentence.py │ │ │ ├── protocols/ │ │ │ │ ├── __init__.py │ │ │ │ ├── amp.py │ │ │ │ ├── basic.py │ │ │ │ ├── dict.py │ │ │ │ ├── finger.py │ │ │ │ ├── ftp.py │ │ │ │ ├── haproxy/ │ │ │ │ │ ├── __init__.py │ │ │ │ │ ├── _exceptions.py │ │ │ │ │ ├── _info.py │ │ │ │ │ ├── _interfaces.py │ │ │ │ │ ├── _parser.py │ │ │ │ │ ├── _v1parser.py │ │ │ │ │ ├── _v2parser.py │ │ │ │ │ ├── _wrapper.py │ │ │ │ │ └── test/ │ │ │ │ │ ├── __init__.py │ │ │ │ │ ├── test_parser.py │ │ │ │ │ ├── test_v1parser.py │ │ │ │ │ ├── test_v2parser.py │ │ │ │ │ └── test_wrapper.py │ │ │ │ ├── htb.py │ │ │ │ ├── ident.py │ │ │ │ ├── loopback.py │ │ │ │ ├── memcache.py │ │ │ │ ├── pcp.py │ │ │ │ ├── policies.py │ │ │ │ ├── portforward.py │ │ │ │ ├── postfix.py │ │ │ │ ├── sip.py │ │ │ │ ├── socks.py │ │ │ │ ├── stateful.py │ │ │ │ ├── test/ │ │ │ │ │ ├── __init__.py │ │ │ │ │ ├── test_basic.py │ │ │ │ │ └── test_tls.py │ │ │ │ ├── tls.py │ │ │ │ └── wire.py │ │ │ ├── python/ │ │ │ │ ├── __init__.py │ │ │ │ ├── _appdirs.py │ │ │ │ ├── _inotify.py │ │ │ │ ├── _oldstyle.py │ │ │ │ ├── _pydoctortemplates/ │ │ │ │ │ ├── common.html │ │ │ │ │ ├── index.html │ │ │ │ │ └── summary.html │ │ │ │ ├── _release.py │ │ │ │ ├── _setup.py │ │ │ │ ├── _shellcomp.py │ │ │ │ ├── _textattributes.py │ │ │ │ ├── _tzhelper.py │ │ │ │ ├── _url.py │ │ │ │ ├── compat.py │ │ │ │ ├── components.py │ │ │ │ ├── constants.py │ │ │ │ ├── context.py │ │ │ │ ├── deprecate.py │ │ │ │ ├── failure.py │ │ │ │ ├── fakepwd.py │ │ │ │ ├── filepath.py │ │ │ │ ├── formmethod.py │ │ │ │ ├── htmlizer.py │ │ │ │ ├── lockfile.py │ │ │ │ ├── log.py │ │ │ │ ├── logfile.py │ │ │ │ ├── modules.py │ │ │ │ ├── monkey.py │ │ │ │ ├── procutils.py │ │ │ │ ├── randbytes.py │ │ │ │ ├── rebuild.py │ │ │ │ ├── reflect.py │ │ │ │ ├── release.py │ │ │ │ ├── roots.py │ │ │ │ ├── runtime.py │ │ │ │ ├── sendmsg.py │ │ │ │ ├── shortcut.py │ │ │ │ ├── syslog.py │ │ │ │ ├── systemd.py │ │ │ │ ├── test/ │ │ │ │ │ ├── __init__.py │ │ │ │ │ ├── _deprecatetests.py.3only │ │ │ │ │ ├── deprecatedattributes.py │ │ │ │ │ ├── modules_helpers.py │ │ │ │ │ ├── pullpipe.py │ │ │ │ │ ├── test_appdirs.py │ │ │ │ │ ├── test_components.py │ │ │ │ │ ├── test_constants.py │ │ │ │ │ ├── test_deprecate.py │ │ │ │ │ ├── test_dist3.py │ │ │ │ │ ├── test_fakepwd.py │ │ │ │ │ ├── test_htmlizer.py │ │ │ │ │ ├── test_inotify.py │ │ │ │ │ ├── test_release.py │ │ │ │ │ ├── test_runtime.py │ │ │ │ │ ├── test_sendmsg.py │ │ │ │ │ ├── test_setup.py │ │ │ │ │ ├── test_shellcomp.py │ │ │ │ │ ├── test_syslog.py │ │ │ │ │ ├── test_systemd.py │ │ │ │ │ ├── test_textattributes.py │ │ │ │ │ ├── test_tzhelper.py │ │ │ │ │ ├── test_url.py │ │ │ │ │ ├── test_urlpath.py │ │ │ │ │ ├── test_util.py │ │ │ │ │ ├── test_versions.py │ │ │ │ │ ├── test_zippath.py │ │ │ │ │ └── test_zipstream.py │ │ │ │ ├── text.py │ │ │ │ ├── threadable.py │ │ │ │ ├── threadpool.py │ │ │ │ ├── twisted-completion.zsh │ │ │ │ ├── url.py │ │ │ │ ├── urlpath.py │ │ │ │ ├── usage.py │ │ │ │ ├── util.py │ │ │ │ ├── versions.py │ │ │ │ ├── win32.py │ │ │ │ ├── zippath.py │ │ │ │ └── zipstream.py │ │ │ ├── runner/ │ │ │ │ ├── __init__.py │ │ │ │ ├── inetd.py │ │ │ │ ├── inetdconf.py │ │ │ │ ├── inetdtap.py │ │ │ │ ├── procmon.py │ │ │ │ ├── procmontap.py │ │ │ │ └── test/ │ │ │ │ ├── __init__.py │ │ │ │ ├── test_inetdconf.py │ │ │ │ ├── test_procmon.py │ │ │ │ └── test_procmontap.py │ │ │ ├── scripts/ │ │ │ │ ├── __init__.py │ │ │ │ ├── _twistd_unix.py │ │ │ │ ├── _twistw.py │ │ │ │ ├── htmlizer.py │ │ │ │ ├── test/ │ │ │ │ │ ├── __init__.py │ │ │ │ │ └── test_scripts.py │ │ │ │ ├── trial.py │ │ │ │ └── twistd.py │ │ │ ├── spread/ │ │ │ │ ├── __init__.py │ │ │ │ ├── banana.py │ │ │ │ ├── flavors.py │ │ │ │ ├── interfaces.py │ │ │ │ ├── jelly.py │ │ │ │ ├── pb.py │ │ │ │ ├── publish.py │ │ │ │ ├── test/ │ │ │ │ │ ├── __init__.py │ │ │ │ │ ├── test_banana.py │ │ │ │ │ ├── test_jelly.py │ │ │ │ │ ├── test_pb.py │ │ │ │ │ └── test_pbfailure.py │ │ │ │ └── util.py │ │ │ ├── tap/ │ │ │ │ ├── __init__.py │ │ │ │ ├── ftp.py │ │ │ │ ├── portforward.py │ │ │ │ └── socks.py │ │ │ ├── test/ │ │ │ │ ├── __init__.py │ │ │ │ ├── cert.pem.no_trailing_newline │ │ │ │ ├── crash_test_dummy.py │ │ │ │ ├── iosim.py │ │ │ │ ├── key.pem.no_trailing_newline │ │ │ │ ├── mock_win32process.py │ │ │ │ ├── myrebuilder1.py │ │ │ │ ├── myrebuilder2.py │ │ │ │ ├── plugin_basic.py │ │ │ │ ├── plugin_extra1.py │ │ │ │ ├── plugin_extra2.py │ │ │ │ ├── process_cmdline.py │ │ │ │ ├── process_echoer.py │ │ │ │ ├── process_fds.py │ │ │ │ ├── process_getargv.py │ │ │ │ ├── process_getenv.py │ │ │ │ ├── process_linger.py │ │ │ │ ├── process_reader.py │ │ │ │ ├── process_signal.py │ │ │ │ ├── process_stdinreader.py │ │ │ │ ├── process_tester.py │ │ │ │ ├── process_tty.py │ │ │ │ ├── process_twisted.py │ │ │ │ ├── proto_helpers.py │ │ │ │ ├── reflect_helper_IE.py │ │ │ │ ├── reflect_helper_VE.py │ │ │ │ ├── reflect_helper_ZDE.py │ │ │ │ ├── server.pem │ │ │ │ ├── ssl_helpers.py │ │ │ │ ├── stdio_test_consumer.py │ │ │ │ ├── stdio_test_halfclose.py │ │ │ │ ├── stdio_test_hostpeer.py │ │ │ │ ├── stdio_test_lastwrite.py │ │ │ │ ├── stdio_test_loseconn.py │ │ │ │ ├── stdio_test_producer.py │ │ │ │ ├── stdio_test_write.py │ │ │ │ ├── stdio_test_writeseq.py │ │ │ │ ├── test_abstract.py │ │ │ │ ├── test_adbapi.py │ │ │ │ ├── test_amp.py │ │ │ │ ├── test_application.py │ │ │ │ ├── test_compat.py │ │ │ │ ├── test_context.py │ │ │ │ ├── test_cooperator.py │ │ │ │ ├── test_defer.py │ │ │ │ ├── test_defer.py.3only │ │ │ │ ├── test_defgen.py │ │ │ │ ├── test_dict.py │ │ │ │ ├── test_dirdbm.py │ │ │ │ ├── test_error.py │ │ │ │ ├── test_factories.py │ │ │ │ ├── test_failure.py │ │ │ │ ├── test_fdesc.py │ │ │ │ ├── test_finger.py │ │ │ │ ├── test_formmethod.py │ │ │ │ ├── test_ftp.py │ │ │ │ ├── test_ftp_options.py │ │ │ │ ├── test_htb.py │ │ │ │ ├── test_ident.py │ │ │ │ ├── test_internet.py │ │ │ │ ├── test_iosim.py │ │ │ │ ├── test_iutils.py │ │ │ │ ├── test_lockfile.py │ │ │ │ ├── test_log.py │ │ │ │ ├── test_logfile.py │ │ │ │ ├── test_loopback.py │ │ │ │ ├── test_main.py │ │ │ │ ├── test_memcache.py │ │ │ │ ├── test_modules.py │ │ │ │ ├── test_monkey.py │ │ │ │ ├── test_nooldstyle.py │ │ │ │ ├── test_paths.py │ │ │ │ ├── test_pcp.py │ │ │ │ ├── test_persisted.py │ │ │ │ ├── test_plugin.py │ │ │ │ ├── test_policies.py │ │ │ │ ├── test_postfix.py │ │ │ │ ├── test_process.py │ │ │ │ ├── test_protocols.py │ │ │ │ ├── test_randbytes.py │ │ │ │ ├── test_rebuild.py │ │ │ │ ├── test_reflect.py │ │ │ │ ├── test_roots.py │ │ │ │ ├── test_shortcut.py │ │ │ │ ├── test_sip.py │ │ │ │ ├── test_sob.py │ │ │ │ ├── test_socks.py │ │ │ │ ├── test_ssl.py │ │ │ │ ├── test_sslverify.py │ │ │ │ ├── test_stateful.py │ │ │ │ ├── test_stdio.py │ │ │ │ ├── test_strerror.py │ │ │ │ ├── test_strports.py │ │ │ │ ├── test_task.py │ │ │ │ ├── test_tcp.py │ │ │ │ ├── test_tcp_internals.py │ │ │ │ ├── test_text.py │ │ │ │ ├── test_threadable.py │ │ │ │ ├── test_threadpool.py │ │ │ │ ├── test_threads.py │ │ │ │ ├── test_tpfile.py │ │ │ │ ├── test_twistd.py │ │ │ │ ├── test_twisted.py │ │ │ │ ├── test_udp.py │ │ │ │ ├── test_unix.py │ │ │ │ ├── test_usage.py │ │ │ │ └── testutils.py │ │ │ ├── trial/ │ │ │ │ ├── __init__.py │ │ │ │ ├── __main__.py │ │ │ │ ├── _asyncrunner.py │ │ │ │ ├── _asynctest.py │ │ │ │ ├── _dist/ │ │ │ │ │ ├── __init__.py │ │ │ │ │ ├── distreporter.py │ │ │ │ │ ├── disttrial.py │ │ │ │ │ ├── managercommands.py │ │ │ │ │ ├── options.py │ │ │ │ │ ├── test/ │ │ │ │ │ │ ├── __init__.py │ │ │ │ │ │ ├── test_distreporter.py │ │ │ │ │ │ ├── test_disttrial.py │ │ │ │ │ │ ├── test_options.py │ │ │ │ │ │ ├── test_worker.py │ │ │ │ │ │ ├── test_workerreporter.py │ │ │ │ │ │ └── test_workertrial.py │ │ │ │ │ ├── worker.py │ │ │ │ │ ├── workercommands.py │ │ │ │ │ ├── workerreporter.py │ │ │ │ │ └── workertrial.py │ │ │ │ ├── _synctest.py │ │ │ │ ├── itrial.py │ │ │ │ ├── reporter.py │ │ │ │ ├── runner.py │ │ │ │ ├── test/ │ │ │ │ │ ├── __init__.py │ │ │ │ │ ├── detests.py │ │ │ │ │ ├── erroneous.py │ │ │ │ │ ├── mockcustomsuite.py │ │ │ │ │ ├── mockcustomsuite2.py │ │ │ │ │ ├── mockcustomsuite3.py │ │ │ │ │ ├── mockdoctest.py │ │ │ │ │ ├── moduleself.py │ │ │ │ │ ├── moduletest.py │ │ │ │ │ ├── novars.py │ │ │ │ │ ├── ordertests.py │ │ │ │ │ ├── packages.py │ │ │ │ │ ├── sample.py │ │ │ │ │ ├── scripttest.py │ │ │ │ │ ├── skipping.py │ │ │ │ │ ├── suppression.py │ │ │ │ │ ├── test_assertions.py │ │ │ │ │ ├── test_asyncassertions.py │ │ │ │ │ ├── test_deferred.py │ │ │ │ │ ├── test_doctest.py │ │ │ │ │ ├── test_keyboard.py │ │ │ │ │ ├── test_loader.py │ │ │ │ │ ├── test_log.py │ │ │ │ │ ├── test_output.py │ │ │ │ │ ├── test_plugins.py │ │ │ │ │ ├── test_pyunitcompat.py │ │ │ │ │ ├── test_reporter.py │ │ │ │ │ ├── test_runner.py │ │ │ │ │ ├── test_script.py │ │ │ │ │ ├── test_suppression.py │ │ │ │ │ ├── test_testcase.py │ │ │ │ │ ├── test_tests.py │ │ │ │ │ ├── test_util.py │ │ │ │ │ ├── test_warning.py │ │ │ │ │ └── weird.py │ │ │ │ ├── unittest.py │ │ │ │ └── util.py │ │ │ ├── web/ │ │ │ │ ├── __init__.py │ │ │ │ ├── _auth/ │ │ │ │ │ ├── __init__.py │ │ │ │ │ ├── basic.py │ │ │ │ │ ├── digest.py │ │ │ │ │ └── wrapper.py │ │ │ │ ├── _element.py │ │ │ │ ├── _flatten.py │ │ │ │ ├── _http2.py │ │ │ │ ├── _newclient.py │ │ │ │ ├── _responses.py │ │ │ │ ├── _stan.py │ │ │ │ ├── client.py │ │ │ │ ├── demo.py │ │ │ │ ├── distrib.py │ │ │ │ ├── domhelpers.py │ │ │ │ ├── error.py │ │ │ │ ├── guard.py │ │ │ │ ├── html.py │ │ │ │ ├── http.py │ │ │ │ ├── http_headers.py │ │ │ │ ├── iweb.py │ │ │ │ ├── microdom.py │ │ │ │ ├── proxy.py │ │ │ │ ├── resource.py │ │ │ │ ├── rewrite.py │ │ │ │ ├── script.py │ │ │ │ ├── server.py │ │ │ │ ├── static.py │ │ │ │ ├── sux.py │ │ │ │ ├── tap.py │ │ │ │ ├── template.py │ │ │ │ ├── test/ │ │ │ │ │ ├── __init__.py │ │ │ │ │ ├── _util.py │ │ │ │ │ ├── injectionhelpers.py │ │ │ │ │ ├── requesthelper.py │ │ │ │ │ ├── test_agent.py │ │ │ │ │ ├── test_cgi.py │ │ │ │ │ ├── test_client.py │ │ │ │ │ ├── test_distrib.py │ │ │ │ │ ├── test_domhelpers.py │ │ │ │ │ ├── test_error.py │ │ │ │ │ ├── test_flatten.py │ │ │ │ │ ├── test_html.py │ │ │ │ │ ├── test_http.py │ │ │ │ │ ├── test_http2.py │ │ │ │ │ ├── test_http_headers.py │ │ │ │ │ ├── test_httpauth.py │ │ │ │ │ ├── test_newclient.py │ │ │ │ │ ├── test_proxy.py │ │ │ │ │ ├── test_resource.py │ │ │ │ │ ├── test_script.py │ │ │ │ │ ├── test_stan.py │ │ │ │ │ ├── test_static.py │ │ │ │ │ ├── test_tap.py │ │ │ │ │ ├── test_template.py │ │ │ │ │ ├── test_util.py │ │ │ │ │ ├── test_vhost.py │ │ │ │ │ ├── test_web.py │ │ │ │ │ ├── test_web__responses.py │ │ │ │ │ ├── test_webclient.py │ │ │ │ │ ├── test_wsgi.py │ │ │ │ │ ├── test_xml.py │ │ │ │ │ └── test_xmlrpc.py │ │ │ │ ├── twcgi.py │ │ │ │ ├── util.py │ │ │ │ ├── vhost.py │ │ │ │ ├── wsgi.py │ │ │ │ └── xmlrpc.py │ │ │ └── words/ │ │ │ ├── __init__.py │ │ │ ├── ewords.py │ │ │ ├── im/ │ │ │ │ ├── __init__.py │ │ │ │ ├── baseaccount.py │ │ │ │ ├── basechat.py │ │ │ │ ├── basesupport.py │ │ │ │ ├── instancemessenger.glade │ │ │ │ ├── interfaces.py │ │ │ │ ├── ircsupport.py │ │ │ │ ├── locals.py │ │ │ │ └── pbsupport.py │ │ │ ├── iwords.py │ │ │ ├── protocols/ │ │ │ │ ├── __init__.py │ │ │ │ ├── irc.py │ │ │ │ └── jabber/ │ │ │ │ ├── __init__.py │ │ │ │ ├── client.py │ │ │ │ ├── component.py │ │ │ │ ├── error.py │ │ │ │ ├── ijabber.py │ │ │ │ ├── jid.py │ │ │ │ ├── jstrports.py │ │ │ │ ├── sasl.py │ │ │ │ ├── sasl_mechanisms.py │ │ │ │ ├── xmlstream.py │ │ │ │ └── xmpp_stringprep.py │ │ │ ├── service.py │ │ │ ├── tap.py │ │ │ ├── test/ │ │ │ │ ├── __init__.py │ │ │ │ ├── test_basechat.py │ │ │ │ ├── test_basesupport.py │ │ │ │ ├── test_domish.py │ │ │ │ ├── test_irc.py │ │ │ │ ├── test_irc_service.py │ │ │ │ ├── test_ircsupport.py │ │ │ │ ├── test_jabberclient.py │ │ │ │ ├── test_jabbercomponent.py │ │ │ │ ├── test_jabbererror.py │ │ │ │ ├── test_jabberjid.py │ │ │ │ ├── test_jabberjstrports.py │ │ │ │ ├── test_jabbersasl.py │ │ │ │ ├── test_jabbersaslmechanisms.py │ │ │ │ ├── test_jabberxmlstream.py │ │ │ │ ├── test_jabberxmppstringprep.py │ │ │ │ ├── test_service.py │ │ │ │ ├── test_tap.py │ │ │ │ ├── test_xishutil.py │ │ │ │ ├── test_xmlstream.py │ │ │ │ ├── test_xmpproutertap.py │ │ │ │ └── test_xpath.py │ │ │ ├── xish/ │ │ │ │ ├── __init__.py │ │ │ │ ├── domish.py │ │ │ │ ├── utility.py │ │ │ │ ├── xmlstream.py │ │ │ │ ├── xpath.py │ │ │ │ ├── xpathparser.g │ │ │ │ └── xpathparser.py │ │ │ └── xmpproutertap.py │ │ ├── w3lib/ │ │ │ ├── __init__.py │ │ │ ├── encoding.py │ │ │ ├── form.py │ │ │ ├── html.py │ │ │ ├── http.py │ │ │ ├── url.py │ │ │ └── util.py │ │ ├── w3lib-1.21.0.dist-info/ │ │ │ ├── INSTALLER │ │ │ ├── LICENSE │ │ │ ├── METADATA │ │ │ ├── RECORD │ │ │ ├── WHEEL │ │ │ └── top_level.txt │ │ ├── zope/ │ │ │ └── interface/ │ │ │ ├── __init__.py │ │ │ ├── _compat.py │ │ │ ├── _flatten.py │ │ │ ├── _zope_interface_coptimizations.c │ │ │ ├── adapter.py │ │ │ ├── advice.py │ │ │ ├── common/ │ │ │ │ ├── __init__.py │ │ │ │ ├── idatetime.py │ │ │ │ ├── interfaces.py │ │ │ │ ├── mapping.py │ │ │ │ ├── sequence.py │ │ │ │ └── tests/ │ │ │ │ ├── __init__.py │ │ │ │ ├── basemapping.py │ │ │ │ ├── test_idatetime.py │ │ │ │ └── test_import_interfaces.py │ │ │ ├── declarations.py │ │ │ ├── document.py │ │ │ ├── exceptions.py │ │ │ ├── interface.py │ │ │ ├── interfaces.py │ │ │ ├── registry.py │ │ │ ├── ro.py │ │ │ ├── tests/ │ │ │ │ ├── __init__.py │ │ │ │ ├── advisory_testing.py │ │ │ │ ├── dummy.py │ │ │ │ ├── idummy.py │ │ │ │ ├── ifoo.py │ │ │ │ ├── ifoo_other.py │ │ │ │ ├── m1.py │ │ │ │ ├── m2.py │ │ │ │ ├── odd.py │ │ │ │ ├── test_adapter.py │ │ │ │ ├── test_advice.py │ │ │ │ ├── test_declarations.py │ │ │ │ ├── test_document.py │ │ │ │ ├── test_element.py │ │ │ │ ├── test_exceptions.py │ │ │ │ ├── test_interface.py │ │ │ │ ├── test_interfaces.py │ │ │ │ ├── test_odd_declarations.py │ │ │ │ ├── test_registry.py │ │ │ │ ├── test_ro.py │ │ │ │ ├── test_sorting.py │ │ │ │ └── test_verify.py │ │ │ └── verify.py │ │ ├── zope.interface-4.6.0-py3.6-nspkg.pth │ │ └── zope.interface-4.6.0.dist-info/ │ │ ├── INSTALLER │ │ ├── LICENSE.txt │ │ ├── METADATA │ │ ├── RECORD │ │ ├── WHEEL │ │ ├── namespace_packages.txt │ │ └── top_level.txt │ └── pyvenv.cfg ├── wechat_moment.py └── wechat_public_account.py ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitattributes ================================================ *.js linguist-language=python *.css linguist-language=python *.html linguist-language=python ================================================ FILE: CloudCreat ================================================ # coding: utf-8 from wordcloud import WordCloud import cv2 import jieba import matplotlib.pyplot as plt with open('test.txt', 'r') as f: text = f.read() cut_text = " ".join(jieba.cut(text)) color_mask = cv2.imread('back.jpeg') cloud = WordCloud( # 设置字体,不指定就会出现乱码 font_path="/Users/caichenyang/Desktop/爬虫尝试/Baoli.ttc", # font_path=path.join(d,'simsun.ttc'), # 设置背景色 background_color='white', # 词云形状 mask=color_mask, # 允许最大词汇 max_words=120, # 最大号字体 max_font_size=2000 ) wCloud = cloud.generate(cut_text) wCloud.to_file('cloud.jpg') plt.imshow(wCloud, interpolation='bilinear') plt.axis('off') plt.show() ================================================ FILE: GaoKao_Score/2006-2016浙江高考录取分数线.html ================================================ Awesome-pyecharts
================================================ FILE: GaoKao_Score/2006-2016海南高考录取分数线.html ================================================ Awesome-pyecharts
================================================ FILE: GaoKao_Score/2006-2017上海高考录取分数线.html ================================================ Awesome-pyecharts
================================================ FILE: GaoKao_Score/2006-2017安徽高考录取分数线.html ================================================ Awesome-pyecharts
================================================ FILE: GaoKao_Score/2006-2017山东高考录取分数线.html ================================================ Awesome-pyecharts
================================================ FILE: GaoKao_Score/2006-2017山西高考录取分数线.html ================================================ Awesome-pyecharts
================================================ FILE: GaoKao_Score/2006-2017新疆高考录取分数线.html ================================================ Awesome-pyecharts
================================================ FILE: GaoKao_Score/2006-2017河南高考录取分数线.html ================================================ Awesome-pyecharts
================================================ FILE: GaoKao_Score/2006-2017福建高考录取分数线.html ================================================ Awesome-pyecharts
================================================ FILE: GaoKao_Score/2006-2017重庆高考录取分数线.html ================================================ Awesome-pyecharts
================================================ FILE: GaoKao_Score/2006-2017黑龙江高考录取分数线.html ================================================ Awesome-pyecharts
================================================ FILE: GaoKao_Score/2006-2018云南高考录取分数线.html ================================================ Awesome-pyecharts
================================================ FILE: GaoKao_Score/2006-2018内蒙古高考录取分数线.html ================================================ Awesome-pyecharts
================================================ FILE: GaoKao_Score/2006-2018北京高考录取分数线.html ================================================ Awesome-pyecharts
================================================ FILE: GaoKao_Score/2006-2018吉林高考录取分数线.html ================================================ Awesome-pyecharts
================================================ FILE: GaoKao_Score/2006-2018四川高考录取分数线.html ================================================ Awesome-pyecharts
================================================ FILE: GaoKao_Score/2006-2018天津高考录取分数线.html ================================================ Awesome-pyecharts
================================================ FILE: GaoKao_Score/2006-2018宁夏高考录取分数线.html ================================================ Awesome-pyecharts
================================================ FILE: GaoKao_Score/2006-2018广东高考录取分数线.html ================================================ Awesome-pyecharts
================================================ FILE: GaoKao_Score/2006-2018广西高考录取分数线.html ================================================ Awesome-pyecharts
================================================ FILE: GaoKao_Score/2006-2018江西高考分数线.html ================================================ Awesome-pyecharts
================================================ FILE: GaoKao_Score/2006-2018河北高考录取分数线.html ================================================ Awesome-pyecharts
================================================ FILE: GaoKao_Score/2006-2018湖北高考录取分数线.html ================================================ Awesome-pyecharts
================================================ FILE: GaoKao_Score/2006-2018湖南高考录取分数线.html ================================================ Awesome-pyecharts
================================================ FILE: GaoKao_Score/2006-2018甘肃高考录取分数线.html ================================================ Awesome-pyecharts
================================================ FILE: GaoKao_Score/2006-2018西藏高考录取分数线.html ================================================ Awesome-pyecharts
================================================ FILE: GaoKao_Score/2006-2018贵州高考录取分数线.html ================================================ Awesome-pyecharts
================================================ FILE: GaoKao_Score/2006-2018辽宁高考录取分数线.html ================================================ Awesome-pyecharts
================================================ FILE: GaoKao_Score/2006-2018陕西高考录取分数线.html ================================================ Awesome-pyecharts
================================================ FILE: GaoKao_Score/2006-2018青海高考录取分数线.html ================================================ Awesome-pyecharts
================================================ FILE: GaoKao_Score/2010-2017江苏高考录取分数线.html ================================================ Awesome-pyecharts
================================================ FILE: GaoKao_Score/文科(一本)全国高考录取分数平均值比较.html ================================================ Awesome-pyecharts
================================================ FILE: GaoKao_Score/理科(一本)全国高考录取分数平均值比较.html ================================================ Awesome-pyecharts
================================================ FILE: LICENSE ================================================ MIT License Copyright (c) 2019 wistbean Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: README.md ================================================ # learn_python3_spider 接下来就是,学习python的正确姿势! [等下,阿里云服务器/2核2G/3M/40g,99元/年???](https://t.aliyun.com/U/DYTxRF) peace. # 我开发的小程序「要克制」 帮你戒色: ![要克制小程序](https://github.com/wistbean/learn_python3_spider/blob/master/ykz.png) # python爬虫教程从0到1 ## 爬虫负基础 - [python爬虫系列教程-1 | 不会代码也想爬数据?这就教你!](https://mp.weixin.qq.com/s?__biz=MzkyNTExNzY4NA==&mid=2247484935&idx=1&sn=ad9f68845455ca35c08c0e11f92aa4a6&chksm=c1ca3b9cf6bdb28a8647bc911079221b790780611e019e628613657ebfbc38e1e317f53ab00f&token=1453775207&lang=zh_CN#rd) ## python爬虫前,抓包 - [python爬虫系列教程00 | 什么是爬虫,怎么玩爬虫?](http://mp.weixin.qq.com/s?__biz=Mzg2NzYyNjg2Nw==&mid=2247489892&idx=1&sn=40f3f6b70d467ca72b838939aa63d720&chksm=ceb9e378f9ce6a6e089459fad40e2ef8bdce9f46a0a7b9e8332cdbe6d2bc09a47879dc99dd4c&scene=27#wechat_redirect) - [python爬虫系列教程01 | 教你在 Chrome 浏览器轻松抓包](http://mp.weixin.qq.com/s?__biz=Mzg2NzYyNjg2Nw==&mid=2247489893&idx=1&sn=32cc4fe30066a148485f40629aff598a&chksm=ceb9e379f9ce6a6f609b95a729d01ff1745c101c14fe005fd2ed73e32dec08e1ed4d102bc9c9&scene=27#wechat_redirect) - [python爬虫系列教程02 | 教你通过 Fiddler 进行手机抓包?](https://mp.weixin.qq.com/s?__biz=Mzg2NzYyNjg2Nw==&mid=2247489894&idx=1&sn=d620c16bf3fcb4657c8c44152d936fc7&chksm=ceb9e37af9ce6a6c3017158256b06afd5fb1945a4cd05f9db7e27c31606626ee73d0cc44a074&scene=27#wechat_redirect) ## python爬虫库的使用 - [python爬虫系列教程03 | 那个叫做 Urllib 的库让我们的 python 假装是浏览器](http://mp.weixin.qq.com/s?__biz=Mzg2NzYyNjg2Nw==&mid=2247489895&idx=1&sn=9cddfab13d7d251ab3f7e81a882961ce&chksm=ceb9e37bf9ce6a6d1014e00a7d4730249dc1e9104a8fd70ebc34211714a136bc003a962853b8&scene=27#wechat_redirect) - [python爬虫系列教程04 | 长江后浪推前浪,Requests库把urllib库拍在沙滩上](http://mp.weixin.qq.com/s?__biz=Mzg2NzYyNjg2Nw==&mid=2247489896&idx=1&sn=a4686a0cefb12a9bc5d41b062327f545&chksm=ceb9e374f9ce6a622723e99c8e6c04dc25b268d474f259f85ec8da73d755f0de562bb584c63c&scene=27#wechat_redirect) - [python爬虫系列教程05 | 年轻人,不会正则表达式你睡得着觉?有点出息没有?](https://vip.fxxkpython.com/?p=1928) - [python爬虫系列教程06 | 你的第一个爬虫,爬取当当网 Top 500 本五星好评书籍](https://vip.fxxkpython.com/?p=1903) - [python爬虫系列教程07 | 有了 BeautifulSoup ,妈妈再也不用担心我的正则表达式了](https://vip.fxxkpython.com/?p=1891) - [python爬虫系列教程08 | 你的第二个爬虫,要过年了,爬取豆瓣最受欢迎的250部电影慢慢看](https://vip.fxxkpython.com/?p=1871) - [python爬虫系列教程09 | 上来,自己动 !这就是 selenium 的牛逼之处](https://vip.fxxkpython.com/?p=1854) - [python爬虫系列教程10 | 这次,将带你使用 selenium+ phantomJS 爬取b站上的NBA形象大使蔡徐坤和他的球友们](https://vip.fxxkpython.com/?p=4699) - [python爬虫系列教程11 | python爬虫的时候对Json数据的解析](https://vip.fxxkpython.com/?p=4723) - [python爬虫系列教程12 | 秒爬,python爬虫中的多线程,多进程,协程](https://vip.fxxkpython.com/?p=4736) - [python爬虫系列教程13 | 就这么说吧,如果你不懂python多线程和线程池,那就去河边摸鱼!](https://vip.fxxkpython.com/?p=4756) - [python爬虫系列教程14 | 害羞,用多线程秒爬那些万恶的妹纸们,纸巾呢?](https://vip.fxxkpython.com/?p=5293) - [python爬虫系列教程15 | 你,快去试试用多进程的方式重新去爬取豆瓣上的电影](https://vip.fxxkpython.com/?p=4793) - [python爬虫系列教程16 | 听说你又被封 ip 了,你要学会伪装好自己,这次说说伪装你的头部](https://vip.fxxkpython.com/?p=4803) - [python爬虫系列教程17 | 就算你被封了也能继续爬,使用IP代理池伪装你的IP地址,让IP飘一会](https://vip.fxxkpython.com/?p=4818) - [海外评比第一的代理 IP 提供商,代理抓取成功率 99%。](https://get.brightdata.com/k47ir0cpnkh2) - [python爬虫系列教程18 | 遇到需要的登录的网站怎么办?用这3招轻松搞定!](https://vip.fxxkpython.com/?p=4833) - [python爬虫系列教程19 | 小帅b教你如何识别图片验证码](https://vip.fxxkpython.com/?p=4848) - [python爬虫系列教程20 | 对于b站这样的滑动验证码,不好意思,照样自动识别](https://vip.fxxkpython.com/?p=4878) - [python爬虫系列教程21 | 以后我再讲「模拟登录」我就是狗](https://vip.fxxkpython.com/?p=4919) - [python爬虫系列教程22 | 手机,这次要让你上来自己动了。这就是 Appium+Python 的牛x之处](https://vip.fxxkpython.com/?p=4929) - [python爬虫系列教程23 | 搞事情了,用 Appium 爬取你的微信朋友圈。](https://vip.fxxkpython.com/?p=4950) - [python爬虫系列教程24 |爬取下来的数据怎么保存? CSV 了解一下](https://vip.fxxkpython.com/?p=4975) - [python爬虫系列教程25 | 把数据爬取下来之后就存储到你的MySQL数据库。](https://vip.fxxkpython.com/?p=4990) - [python爬虫系列教程26 | 当Python遇到MongoDB的时候,存储av女优的数据变得如此顺滑爽~](https://vip.fxxkpython.com/?p=5005) - [python爬虫系列教程27 | 你爬下的数据不分析一波可就亏了啊,使用python进行数据可视化](https://vip.fxxkpython.com/?p=5020) - [python爬虫系列教程28 | 使用scrapy爬取糗事百科的例子,告诉你它有多厉害!](https://vip.fxxkpython.com/?p=5038) - [python爬虫系列教程30 | scrapy后续,把「糗事百科」的段子爬下来然后存到数据库中](https://vip.fxxkpython.com/?p=5059) - [mitmproxy | 那个站在中间的男人,使用Python就能直接操控你的上网请求](https://mp.weixin.qq.com/s?__biz=MzU2ODYzNTkwMg==&mid=2247485104&idx=1&sn=5ee4a04e6ce2854e5507cd320517fd0d&chksm=fc8bbe21cbfc373738d926e0ca3250f44079449a85c1fe88f307805e28a3cc4ada07d9e322bb&token=2085568099&lang=zh_CN#rd) - [mitmproxy | 如何使用 mitmproxy 监控你的手机](https://mp.weixin.qq.com/s?__biz=Mzg2NzYyNjg2Nw==&mid=2247490016&idx=1&sn=4749ad1707fd33be167118d5f3aadeab&source=41#wechat_redirect) ## python爬虫进阶:python爬虫反爬 - [python爬虫反爬 | 对方是如何丧心病狂的通过 css 加密让你爬不到数据的](http://mp.weixin.qq.com/s?__biz=MzU2ODYzNTkwMg==&mid=2247484810&idx=1&sn=ed3297773c1eeb741bdabfb31c3ea00e&chksm=fc8bbd1bcbfc340d6ae0166e035dd8c8e106afae8adc5fc32162a17b68916b69383b0ab67265&scene=27#wechat_redirect) - [python爬虫反反爬 | 看完这篇,你几乎可以横扫大部分 css 字体加密的网站!](http://mp.weixin.qq.com/s?__biz=MzU2ODYzNTkwMg==&mid=2247484921&idx=1&sn=72a707c5bc67eede144947829cab4dc6&chksm=fc8bbd68cbfc347eca6727ff90f85ef58a4fdd7c2f75a962aee3ccd5e9c4266dbe5f4e6e2262&scene=27#wechat_redirect) - [python爬虫反反爬 | 像有道词典这样的 JS 混淆加密应该怎么破](http://mp.weixin.qq.com/s?__biz=MzU2ODYzNTkwMg==&mid=2247484997&idx=1&sn=b304304aacb3cba31f5f7a6c6bb1ba69&chksm=fc8bbed4cbfc37c29db631c187295757c164ae75ff3e0381dbbf685a9f3d1410098e5b751e33&scene=27#wechat_redirect) - [你想逆向我的 js 代码?呵呵,先过了我的反 debug 再说吧!](https://mp.weixin.qq.com/s?__biz=MzU2ODYzNTkwMg==&mid=2247485338&idx=1&sn=5b4d6ed34a27ed5e81a3e5d8ccf8bee9&scene=19&token=464856977&lang=zh_CN#wechat_redirect) - [js 逆向分析,代码扣取](https://mp.weixin.qq.com/s?__biz=MzU2ODYzNTkwMg==&mid=2247488874&idx=1&sn=709dc1b0005bb3e39b59a90d75cccfa7&chksm=fc8badfbcbfc24ede7a35f6b0d6b1becddb5ca57ab9efe2b394d962581e84804c05208c94f79&token=1628227326&lang=zh_CN#rd) - [Python 逆向抓取 APP 数据](https://mp.weixin.qq.com/s?__biz=MzU2ODYzNTkwMg==&mid=2247488910&idx=1&sn=2b5cc2571220086b9ac3e2c95fd41cde&chksm=fc8bad1fcbfc24090c06a86da2725e506d17993bddf0dfa57330d3069a003a5f0d66fb602d11&token=1628227326&lang=zh_CN#rd) - [这次有点骚了,破解安卓某 APP 低层加密](https://mp.weixin.qq.com/s?__biz=MzU2ODYzNTkwMg==&mid=2247489255&idx=1&sn=4abbd544ff0a63f4d24eb06a0f954df1&chksm=fc8bae76cbfc2760a71267cca2cade5f6847a7291fa4adc0abf37743c878bfbda65a496f2305&scene=178&cur_album_id=1321044729160859650#rd) - [当你通过 Python 请求网站得到一堆无厘头的 JS 时...](https://mp.weixin.qq.com/s?__biz=MzU2ODYzNTkwMg==&mid=2247489477&idx=1&sn=891944cbceab3eb77966055604645457&chksm=fc8baf54cbfc2642a171cf8851c20f8a05f3eb2b844e8d0b1a6e7539590ce7c69ffae21f10f5&scene=178&cur_album_id=1321044729160859650#rd) ## Python websocket 爬虫: - [哇靠,这些数据疯狂变化,该怎么爬取?](https://mp.weixin.qq.com/s?__biz=MzU2ODYzNTkwMg==&mid=2247485466&idx=1&sn=1e4db96f3ca1d3a263dd7e075cbd7600&scene=19&token=464856977&lang=zh_CN#wechat_redirect) ## Python 分布式爬虫 - [说说分布式爬虫](https://mp.weixin.qq.com/s?__biz=MzU2ODYzNTkwMg==&mid=2247485718&idx=1&sn=2d42d1c7408b14781ef4c1e97fbac8f6&scene=19&token=464856977&lang=zh_CN#wechat_redirect) - [我整来了几台服务器,就是为了给你演示一下分布式爬虫的整个过程](https://mp.weixin.qq.com/s?__biz=MzU2ODYzNTkwMg==&mid=2247485863&idx=1&sn=34f9fb196c77dffdcce4a610b622270d&scene=19&token=464856977&lang=zh_CN#wechat_redirect) ## 爬虫实战教程 - [python爬取 20w 表情包之后,从此你就成为了微信斗图届的高手](https://fxxkpython.com/python-pa-qu-biao-qing-bao.html) - [python爬取你喜欢的公众号的所有原创文章,然后搞成PDF慢慢看](http://mp.weixin.qq.com/s?__biz=MzU2ODYzNTkwMg==&mid=2247484657&idx=1&sn=998bfcce6cd22b7fedff29e68a46fe3f&chksm=fc8bbc60cbfc3576f117d3566fbea8a042ee573d840bbe6a3d4ec9bffef815c691b7f9a59711&scene=27#wechat_redirect) - [当 python 遇到你的微信的时候,你才发现原来你的微信好友是这样的](http://mp.weixin.qq.com/s?__biz=MzU2ODYzNTkwMg==&mid=2247484710&idx=1&sn=cf17f2e87405ebffb20edd0ca0a7315b&chksm=fc8bbdb7cbfc34a1389e17d4485b677d5ada497a404dc8f14107914e50382c640e7bd3cb93a4&scene=27#wechat_redirect) - [高考要来了,扒一扒历年高考录取分数来压压惊](http://mp.weixin.qq.com/s?__biz=MzU2ODYzNTkwMg==&mid=2247484745&idx=1&sn=24362e73605d30e06ebe05d1fe7225f2&chksm=fc8bbdd8cbfc34ce100b9461f46c8a1c0008172f101b34b38e146f56323bc40bbd373a127ee8&scene=27#wechat_redirect) - [随着身子的一阵颤抖,Python爬取抖音上的小姐姐突然变得索然无味](https://mp.weixin.qq.com/s?__biz=MzU2ODYzNTkwMg==&mid=2247485150&idx=1&sn=b813993925a1031d4e85eb8841ccdb37&scene=19#wechat_redirect) - [使用 scrapy 爬取 stackoverflow 上的所有 Python 问答](https://mp.weixin.qq.com/s?__biz=MzU2ODYzNTkwMg==&mid=2247485754&idx=1&sn=3e52aa0ac13f3a23c6dee2b75424f0f5&scene=19&token=464856977&lang=zh_CN#wechat_redirect) - [爬取周杰伦新歌《说好不哭》的所有评论,然后生成词云图](https://mp.weixin.qq.com/s?__biz=MzU2ODYzNTkwMg==&mid=2247485571&idx=1&sn=094517114b22a4684988008aecab2639&scene=19&token=464856977&lang=zh_CN#wechat_redirect) - [我整来了几台服务器,就是为了给你演示一下分布式爬虫的整个过程](https://mp.weixin.qq.com/s?__biz=MzU2ODYzNTkwMg==&mid=2247485863&idx=1&sn=34f9fb196c77dffdcce4a610b622270d&scene=19&token=464856977&lang=zh_CN#wechat_redirect) ## 爬虫实例源代码 图文教程 | 相关源码 ---- | --- [1、爬取当当网 Top 500 本五星好评书籍](https://mp.weixin.qq.com/s?__biz=MzU2ODYzNTkwMg==&mid=2247484142&idx=1&sn=d4893c734e44a16db871f7904910bdcb&scene=19#wechat_redirect) | [源码](https://github.com/wistbean/learn_python3_spider/blob/master/dangdang_top_500.py) [2、爬取豆瓣最受欢迎的250部电影慢慢看](https://mp.weixin.qq.com/s?__biz=MzU2ODYzNTkwMg==&mid=2247484156&idx=1&sn=dc732b380d162f39ff63d55cac5a0dd6&scene=19#wechat_redirect) | [源码](https://github.com/wistbean/learn_python3_spider/blob/master/douban_top_250_books.py) [3、爬取b站上的NBA形象大使蔡徐坤和他的球友们](https://mp.weixin.qq.com/s?__biz=MzU2ODYzNTkwMg==&mid=2247484182&idx=1&sn=1b1c0058e402a9dc559d16ab37a30e98&scene=19#wechat_redirect) | [源码](https://github.com/wistbean/learn_python3_spider/blob/master/ikun_basketball.py) [4、用多线程秒爬那些万恶的妹纸们,纸巾呢?](https://mp.weixin.qq.com/s?__biz=MzU2ODYzNTkwMg==&mid=2247484225&idx=1&sn=077fba66aaa1d806193403ce51e75279&scene=19#wechat_redirect) | [源码](https://github.com/wistbean/learn_python3_spider/blob/master/meizitu.py) [5、自动识别b站滑动验证码](https://mp.weixin.qq.com/s?__biz=MzU2ODYzNTkwMg==&mid=2247484321&idx=1&sn=4bc73324acfacda7d3bc82120b19d11a&scene=19#wechat_redirect) | [源码](https://github.com/wistbean/learn_python3_spider/blob/master/fuck_bilibili_captcha.py) [6、搞事情了,用 Appium 爬取你的微信朋友圈](https://mp.weixin.qq.com/s?__biz=MzU2ODYzNTkwMg==&mid=2247484386&idx=1&sn=7f0545f27f095f20d69deedfa9f606a1&scene=19#wechat_redirect) | [源码](https://github.com/wistbean/learn_python3_spider/blob/master/wechat_moment.py) [7、scrapy爬取糗事百科段子到MongoDB(上)](https://fxxkpython.com/python3-web-fxxkpython-spider-tutorial-29.html)、[scrapy爬取糗事百科段子到MongoDB(下)](https://fxxkpython.com/python3-web-fxxkpython-spider-tutorial-30.html) | [源码](https://github.com/wistbean/learn_python3_spider/tree/master/qiushibaike) [8、python爬取 20w 表情包之后,从此你就成为了微信斗图届的高手](https://fxxkpython.com/python-pa-qu-biao-qing-bao.html) | [源码](https://github.com/wistbean/learn_python3_spider/tree/master/biaoqingbao) [9、python爬取你喜欢的公众号的所有原创文章,然后搞成PDF慢慢看](https://mp.weixin.qq.com/s?__biz=MzU2ODYzNTkwMg==&mid=2247484657&idx=1&sn=998bfcce6cd22b7fedff29e68a46fe3f&scene=19&token=464856977&lang=zh_CN#wechat_redirect) | [源码](https://github.com/wistbean/learn_python3_spider/blob/master/wechat_public_account.py) [10、当 python 遇到你的微信的时候,你才发现原来你的微信好友是这样的](https://mp.weixin.qq.com/s?__biz=MzU2ODYzNTkwMg==&mid=2247484710&idx=1&sn=cf17f2e87405ebffb20edd0ca0a7315b&scene=19&token=464856977&lang=zh_CN#wechat_redirect) | [--](https://wistbean.github.io) > 未完待续... ## 爬虫技巧 - [给你们说几点鲜有人知的爬虫技巧](https://mp.weixin.qq.com/s?__biz=MzU2ODYzNTkwMg==&mid=2247485129&idx=1&sn=56a9aecafa73162c639a873b5bbdf534&chksm=fc8bbe58cbfc374e5c033a37a82b94e8391855d85f1db26975579ddb3cf0882f1157e37f224c&token=2111372640&lang=zh_CN#rd) ## python爬虫段子 - [网站维护人员:真的求求你们了,不要再来爬取了!!](https://vip.fxxkpython.com/?p=4679) ## python相关 - [python如何赚钱? python爬虫如何进阶? python就业? 如何快速入门python? .....](http://mp.weixin.qq.com/s?__biz=MzU2ODYzNTkwMg==&mid=2247484770&idx=1&sn=16427865c7b2785594acfbcf4505e26f&chksm=fc8bbdf3cbfc34e5856dd36dd825f9b89b05a4ab3def08dac48b760771e4ee0454fdf9ddee72&scene=27#wechat_redirect) - [ 如何自学 Python 高效一些](http://mp.weixin.qq.com/s?__biz=MzU2ODYzNTkwMg==&mid=2247484608&idx=1&sn=0ebde7cbfea6e42e9e8e316bbec35b2b&chksm=fc8bbc51cbfc35475daa15a026c44727bc7954bd722b24870eab567ef937a8f175369c546962&scene=27#wechat_redirect) - [python教程资源](https://wistbean.github.io/categories/python/) - [吐血分享这两个爬虫用到的 Chrome 牛逼插件](http://mp.weixin.qq.com/s?__biz=MzU2ODYzNTkwMg==&mid=2247484859&idx=1&sn=b5f91ab1dc027d06e34dea1b37091b34&chksm=fc8bbd2acbfc343ce3123fb3e3aec1fa1e34c96b15e998a34e01a75f4ca90b0089e1692f5a31&scene=27#wechat_redirect) ## 公众号获取 Python 相关帅书 微信搜索id:fxxkpython 名称:帅彬老仙 *进去发送「帅书」即可领取。* ## Python 技巧视频教程 [那些被低估了的 Python 技巧](https://www.bilibili.com/video/BV1P5411S7B6/?vd_source=ed99ef1bdeb96f04c35ccaea6eba97a8) ================================================ FILE: biaoqingbao/biaoqingbao.py ================================================ #-*- coding:UTF-8 -*- import os from time import time import requests from bs4 import BeautifulSoup from queue import Queue from threading import Thread class DownloadBiaoqingbao(Thread): def __init__(self, queue, path): Thread.__init__(self) self.queue = queue self.path = '/home/wistbean/biaoqingbao/' if not os.path.exists(path): os.makedirs(path) def run(self): while True: url = self.queue.get() try: # print(url) download_biaoqingbaos(url, self.path) finally: self.queue.task_done() def download_biaoqingbaos(url, path): response = requests.get(url) soup = BeautifulSoup(response.content, 'lxml') img_list = soup.find_all('img', class_='ui image lazy') for img in img_list: image = img.get('data-original') title = img.get('title') print('下载图片: ', title) try: with open(path + title + os.path.splitext(image)[-1], 'wb') as f: img = requests.get(image).content f.write(img) except OSError: print('length failed') break if __name__ == '__main__': start = time() # 构建所有的链接 _url = 'https://fabiaoqing.com/biaoqing/lists/page/{page}.html' urls = [_url.format(page=page) for page in range(1, 4328+1)] queue = Queue() path = '/home/wistbean/biaoqingbao/' # 创建线程 for x in range(10): worker = DownloadBiaoqingbao(queue, path) worker.daemon = True worker.start() # 加入队列 for url in urls: queue.put(url) queue.join() print('下载完毕耗时: ', time()-start) ================================================ FILE: biaoqingbao/search.py ================================================ #-*- coding:UTF-8 -*- import glob import time import itchat from itchat.content import TEXT, PICTURE imgs = [] def searchImage(text): print('收到关键词: ', text) for name in glob.glob('/home/wistbean/biaoqingbao/*'+text+'*.jpg'): imgs.append(name) @itchat.msg_register([PICTURE, TEXT]) def text_reply(msg): searchImage(msg.text) for img in imgs[:6]: msg.user.send_image(img) time.sleep(0.3) print('开始发送表情: ', img) imgs.clear() itchat.auto_login(hotReload=True) itchat.run() ================================================ FILE: dangdang_top_500.py ================================================ import requests import re import json def request_dandan(url): try: response = requests.get(url) if response.status_code == 200: return response.text except requests.RequestException as e: print(e) return None def parse_result(html): pattern = re.compile( '.*?.*?class="star">.*?class="tuijian">(.*?).*?class="publisher_info">.*?target="_blank">(.*?).*?class="biaosheng">.*?(.*?).*?

(.*?).*?', re.S) items = re.findall(pattern, html) for item in items: yield { 'range': item[0], 'image': item[1], 'title': item[2], 'recommend': item[3], 'author': item[4], 'times': item[5], 'price': item[6] } def write_item_to_file(item): print('开始写入数据 ====> ' + str(item)) with open('book.txt', 'a', encoding='UTF-8') as f: f.write(json.dumps(item, ensure_ascii=False) + '\n') def main(page): url = 'http://bang.dangdang.com/books/fivestars/01.00.00.00.00.00-recent30-0-0-1-' + str(page) html = request_dandan(url) items = parse_result(html) # 解析过滤我们想要的信息 for item in items: write_item_to_file(item) if __name__ == "__main__": for i in range(1, 26): main(i) ================================================ FILE: douban_top_250_books.py ================================================ import requests from bs4 import BeautifulSoup import xlwt def request_douban(url): headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) ' 'Chrome/88.0.4324.146 Safari/537.36', } try: response = requests.get(url=url, headers=headers) if response.status_code == 200: return response.text except requests.RequestException: return None book = xlwt.Workbook(encoding='utf-8', style_compression=0) sheet = book.add_sheet('豆瓣电影Top250', cell_overwrite_ok=True) sheet.write(0, 0, '名称') sheet.write(0, 1, '图片') sheet.write(0, 2, '排名') sheet.write(0, 3, '评分') sheet.write(0, 4, '作者') sheet.write(0, 5, '简介') n = 1 def save_to_excel(soup): list = soup.find(class_='grid_view').find_all('li') for item in list: item_name = item.find(class_='title').string item_img = item.find('a').find('img').get('src') item_index = item.find(class_='').string item_score = item.find(class_='rating_num').string item_author = item.find('p').text if item.find(class_='inq') is not None: item_intr = item.find(class_='inq').string else: item_intr = 'NOT AVAILABLE' # print('爬取电影:' + item_index + ' | ' + item_name +' | ' + item_img +' | ' + item_score +' | ' + item_author +' | ' + item_intr ) print('爬取电影:' + item_index + ' | ' + item_name + ' | ' + item_score + ' | ' + item_intr) global n sheet.write(n, 0, item_name) sheet.write(n, 1, item_img) sheet.write(n, 2, item_index) sheet.write(n, 3, item_score) sheet.write(n, 4, item_author) sheet.write(n, 5, item_intr) n = n + 1 def main(page): url = 'https://movie.douban.com/top250?start=' + str(page * 25) + '&filter=' html = request_douban(url) soup = BeautifulSoup(html, 'lxml') save_to_excel(soup) if __name__ == '__main__': for i in range(0, 10): main(i) book.save(u'豆瓣最受欢迎的250部电影.xlsx') ================================================ FILE: douban_top_250_books_mul_process.py ================================================ import requests from bs4 import BeautifulSoup import xlwt import multiprocessing import time import sys def request_douban(url): try: response = requests.get(url,headers={'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)'}) if response.status_code == 200: return response.text except requests.RequestException: return None def main(url): sys.setrecursionlimit(1000000) data = [] html = request_douban(url) # soup = BeautifulSoup(html, 'lxml') soup = BeautifulSoup(html, 'html.parser') list = soup.find(class_='grid_view').find_all('li') for item in list: item_name = item.find(class_='title').string item_img = item.find('a').find('img').get('src') item_index = item.find(class_='').string item_score = item.find(class_='rating_num').string item_author = item.find('p').text item_intr = '' if (item.find(class_='inq') != None): item_intr = item.find(class_='inq').string print('爬取电影:' + item_index + ' | ' + item_name + ' | ' + item_score + ' | ' + item_intr) item = { 'item_index': item_index, 'item_name': item_name, 'item_score': item_score, 'item_intr': item_intr, 'item_img': item_img, 'item_author': item_author } data.append(item) return data if __name__ == '__main__': startTime = time.time() data = [] urls = [] pool = multiprocessing.Pool(multiprocessing.cpu_count()-1) for i in range(0, 10): url = 'https://movie.douban.com/top250?start=' + str(i * 25) + '&filter=' urls.append(url) pool.map(main, urls) for pageItem in pool.map(main, urls): data.extend(pageItem) book = xlwt.Workbook(encoding='utf-8', style_compression=0) sheet = book.add_sheet('豆瓣电影Top250-test', cell_overwrite_ok=True) sheet.write(0, 0, '名称') sheet.write(0, 1, '图片') sheet.write(0, 2, '排名') sheet.write(0, 3, '评分') sheet.write(0, 4, '作者') sheet.write(0, 5, '简介') for index,item in enumerate(data): sheet.write(index+1, 0, item['item_name']) sheet.write(index+1, 1, item['item_img']) sheet.write(index+1, 2, item['item_index']) sheet.write(index+1, 3, item['item_score']) sheet.write(index+1, 4, item['item_author']) sheet.write(index+1, 5, item['item_intr']) book.save(u'豆瓣最受欢迎的250部电影-mul.xlsx') endTime = time.time() dtime = endTime - startTime print("程序运行时间:%s s" % dtime) # 4.036666631698608 s ================================================ FILE: fuck_bilibili_captcha.py ================================================ import time import requests from PIL import Image from selenium import webdriver from selenium.webdriver import ActionChains from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from bs4 import BeautifulSoup import re from io import BytesIO driver = webdriver.Chrome('/usr/lib/chromium-browser/chromedriver') WAIT = WebDriverWait(driver, 10) url = 'https://passport.bilibili.com/login' def mergy_Image(image_file, location_list): """ 将原始图片进行合成 :param image_file: 图片文件 :param location_list: 图片位置 :return: 合成新的图片 """ # 存放上下部分的各个小块 upper_half_list = [] down_half_list = [] image = Image.open(image_file) # 通过 y 的位置来判断是上半部分还是下半部分,然后切割 for location in location_list: if location['y'] == -58: # 间距为10,y:58-116 im = image.crop((abs(location['x']), 58, abs(location['x'])+10, 116)) upper_half_list.append(im) if location['y'] == 0: # 间距为10,y:0-58 im = image.crop((abs(location['x']), 0, abs(location['x']) + 10, 58)) down_half_list.append(im) # 创建一张大小一样的图片 new_image = Image.new('RGB', (260, 116)) # 粘贴好上半部分 y坐标是从上到下(0-116) offset = 0 for im in upper_half_list: new_image.paste(im, (offset, 0)) offset += 10 # 粘贴好下半部分 offset = 0 for im in down_half_list: new_image.paste(im, (offset, 58)) offset += 10 return new_image def get_distance(bg_Image, fullbg_Image): # 阈值 threshold = 200 print(bg_Image.size[0]) print(bg_Image.size[1]) for i in range(60, bg_Image.size[0]): for j in range(bg_Image.size[1]): bg_pix = bg_Image.getpixel((i, j)) fullbg_pix = fullbg_Image.getpixel((i, j)) r = abs(bg_pix[0] - fullbg_pix[0]) g = abs(bg_pix[1] - fullbg_pix[1]) b = abs(bg_pix[2] - fullbg_pix[2]) if r + g + b > threshold: return i def get_path(distance): result = [] current = 0 mid = distance * 4 / 5 t = 0.2 v = 0 while current < (distance - 10): if current < mid: a = 2 else: a = -3 v0 = v v = v0 + a * t s = v0 * t + 0.5 * a * t * t current += s result.append(round(s)) return result def start_drag(driver, distance): # 被妖怪吃掉了 # knob = WAIT.until(EC.presence_of_element_located((By.CSS_SELECTOR, "#gc-box > div > div.gt_slider > div.gt_slider_knob.gt_show"))) # ActionChains(driver).click_and_hold(knob).perform() # ActionChains(driver).move_by_offset(xoffset=distance, yoffset=0.1).perform() # time.sleep(0.5) # ActionChains(driver).release(knob).perform() # 被妖怪吃掉了 # ActionChains(driver).drag_and_drop_by_offset(knob, distance-10, 0).perform() knob = WAIT.until(EC.presence_of_element_located((By.CSS_SELECTOR, "#gc-box > div > div.gt_slider > div.gt_slider_knob.gt_show"))) result = get_path(distance) ActionChains(driver).click_and_hold(knob).perform() for x in result: ActionChains(driver).move_by_offset(xoffset=x, yoffset=0).perform() time.sleep(0.5) ActionChains(driver).release(knob).perform() def recognize_code(driver): """ 识别滑动验证码 :param driver: selenium驱动 :return: """ bs = BeautifulSoup(driver.page_source,'lxml') # 找到背景图片和缺口图片的div bg_div = bs.find_all(class_='gt_cut_bg_slice') fullbg_div = bs.find_all(class_='gt_cut_fullbg_slice') # 获取缺口背景图片url bg_url = re.findall('background-image:\surl\("(.*?)"\)',bg_div[0].get('style')) # 获取背景图片url fullbg_url = re.findall('background-image:\surl\("(.*?)"\)',fullbg_div[0].get('style')) # 存放每个合成缺口背景图片的位置 bg_location_list = [] # 存放每个合成背景图片的位置 fullbg_location_list = [] for bg in bg_div: location = {} location['x'] = int(re.findall('background-position:\s(.*?)px\s(.*?)px;', bg.get('style'))[0][0]) location['y'] = int(re.findall('background-position:\s(.*?)px\s(.*?)px;', bg.get('style'))[0][1]) bg_location_list.append(location) for fullbg in fullbg_div: location = {} location['x'] = int(re.findall('background-position:\s(.*?)px\s(.*?)px;', fullbg.get('style'))[0][0]) location['y'] = int(re.findall('background-position:\s(.*?)px\s(.*?)px;', fullbg.get('style'))[0][1]) fullbg_location_list.append(location) print(bg_location_list) print(fullbg_location_list) # 将图片格式存为 jpg 格式 bg_url = bg_url[0].replace('webp', 'jpg') fullbg_url = fullbg_url[0].replace('webp', 'jpg') # print(bg_url) # print(fullbg_url) # 下载图片 bg_image = requests.get(bg_url).content fullbg_image = requests.get(fullbg_url).content print('完成图片下载') # 写入图片 bg_image_file = BytesIO(bg_image) fullbg_image_file = BytesIO(fullbg_image) # 合成图片 bg_Image = mergy_Image(bg_image_file, bg_location_list) fullbg_Image = mergy_Image(fullbg_image_file, fullbg_location_list) # bg_Image.show() # fullbg_Image.show() # 计算缺口偏移距离 distance = get_distance(bg_Image, fullbg_Image) print('得到距离:%s' % str(distance)) start_drag(driver, distance) if __name__ == '__main__': # 获取滑块按钮 driver.get(url) slider = WAIT.until(EC.element_to_be_clickable( (By.CSS_SELECTOR, "#gc-box > div > div.gt_slider > div.gt_slider_knob.gt_show"))) recognize_code(driver) # driver.close() ================================================ FILE: ikun_basketball.py ================================================ # coding=utf-8 # 最新版的selenium(4.x.x)已经不支持PhantomJS。如要用PhantomJS,可用旧版本selenium。如pip install selenium==3.8.0。 from selenium import webdriver from selenium.common.exceptions import TimeoutException from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from bs4 import BeautifulSoup import xlwt # browser = webdriver.PhantomJS() browser = webdriver.Chrome() WAIT = WebDriverWait(browser, 10) browser.set_window_size(1400, 900) book = xlwt.Workbook(encoding='utf-8', style_compression=0) sheet = book.add_sheet('蔡徐坤篮球', cell_overwrite_ok=True) sheet.write(0, 0, '名称') sheet.write(0, 1, '地址') sheet.write(0, 2, '描述') sheet.write(0, 3, '观看次数') sheet.write(0, 4, '弹幕数') sheet.write(0, 5, '发布时间') n = 1 def search(): try: print('开始访问b站....') browser.get("https://www.bilibili.com/") # 被那个破登录遮住了 # index = WAIT.until(EC.element_to_be_clickable((By.CSS_SELECTOR, "#primary_menu > ul > li.home > a"))) # index.click() input = WAIT.until(EC.presence_of_element_located((By.CSS_SELECTOR, "#nav_searchform > input"))) submit = WAIT.until(EC.element_to_be_clickable( (By.XPATH, '/html/body/div[2]/div/div[1]/div[1]/div/div[2]/div/form/div/button'))) input.send_keys('蔡徐坤 篮球') submit.click() # 跳转到新的窗口 print('跳转到新窗口') all_h = browser.window_handles browser.switch_to.window(all_h[1]) get_source() total = WAIT.until(EC.presence_of_element_located((By.CSS_SELECTOR, "#all-list > div.flow-loader > div.page-wrap > div > ul > li.page-item.last > button"))) return int(total.text) except TimeoutException: return search() def next_page(page_num): try: print('获取下一页数据') next_btn = WAIT.until(EC.element_to_be_clickable((By.CSS_SELECTOR, '#all-list > div.flow-loader > div.page-wrap > div > ul > li.page-item.next > button'))) next_btn.click() WAIT.until(EC.text_to_be_present_in_element((By.CSS_SELECTOR, '#all-list > div.flow-loader > div.page-wrap > div > ul > li.page-item.active > button'), str(page_num))) get_source() except TimeoutException: browser.refresh() return next_page(page_num) def save_to_excel(soup): list = soup.find(class_='video-list clearfix').find_all(class_='video-item matrix') for item in list: item_title = item.find('a').get('title') item_link = item.find('a').get('href') item_dec = item.find(class_='des hide').text item_view = item.find(class_='so-icon watch-num').text item_biubiu = item.find(class_='so-icon hide').text item_date = item.find(class_='so-icon time').text print('爬取:' + item_title) global n sheet.write(n, 0, item_title) sheet.write(n, 1, item_link) sheet.write(n, 2, item_dec) sheet.write(n, 3, item_view) sheet.write(n, 4, item_biubiu) sheet.write(n, 5, item_date) n = n + 1 def get_source(): WAIT.until(EC.presence_of_element_located( (By.CSS_SELECTOR, '#all-list > div.flow-loader > div.filter-wrap'))) html = browser.page_source soup = BeautifulSoup(html, 'lxml') print('到这') save_to_excel(soup) def main(): try: total = search() print(total) for i in range(2, int(total + 1)): next_page(i) finally: browser.close() if __name__ == '__main__': main() book.save('蔡徐坤篮球.xlsx') ================================================ FILE: meizitu.py ================================================ # encoding = utf-8 import concurrent import os from concurrent.futures import ThreadPoolExecutor import requests from bs4 import BeautifulSoup def header(referer): headers = { 'Host': 'i.meizitu.net', 'Pragma': 'no-cache', 'Accept-Encoding': 'gzip, deflate', 'Accept-Language': 'zh-CN,zh;q=0.8,en;q=0.6', 'Cache-Control': 'no-cache', 'Connection': 'keep-alive', 'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36', 'Accept': 'image/webp,image/apng,image/*,*/*;q=0.8', 'Referer': '{}'.format(referer), } return headers def request_page(url): try: response = requests.get(url) if response.status_code == 200: return response.text except requests.RequestException: return None def get_page_urls(): for i in range(1, 2): baseurl = 'https://www.mzitu.com/page/{}'.format(i) html = request_page(baseurl) soup = BeautifulSoup(html, 'lxml') elements = soup.find(class_='postlist').find_all('li') urls = [] for item in elements: url = item.find('span').find('a').get('href') print('页面链接:%s' % url) urls.append(url) return urls def download_Pic(title, image_list): # 新建文件夹 os.mkdir(title) j = 1 # 下载图片 for item in image_list: filename = '%s/%s.jpg' % (title, str(j)) print('downloading....%s : NO.%s' % (title, str(j))) with open(filename, 'wb') as f: img = requests.get(item, headers=header(item)).content f.write(img) j += 1 def download(url): html = request_page(url) soup = BeautifulSoup(html, 'lxml') total = soup.find(class_='pagenavi').find_all('a')[-2].find('span').string title = soup.find('h2').string image_list = [] for i in range(int(total)): html = request_page(url + '/%s' % (i + 1)) soup = BeautifulSoup(html, 'lxml') img_url = soup.find('img').get('src') image_list.append(img_url) download_Pic(title, image_list) def download_all_images(list_page_urls): # 获取每一个详情妹纸 # works = len(list_page_urls) with concurrent.futures.ProcessPoolExecutor(max_workers=5) as exector: for url in list_page_urls: exector.submit(download, url) if __name__ == '__main__': # 获取每一页的链接和名称 list_page_urls = get_page_urls() download_all_images(list_page_urls) ================================================ FILE: qiushibaike/qiushibaike/__init__.py ================================================ ================================================ FILE: qiushibaike/qiushibaike/items.py ================================================ # -*- coding: utf-8 -*- # Define here the models for your scraped items # # See documentation in: # https://doc.scrapy.org/en/latest/topics/items.html import scrapy class QiushibaikeItem(scrapy.Item): # define the fields for your item here like: # name = scrapy.Field() author = scrapy.Field() content = scrapy.Field() _id = scrapy.Field() ================================================ FILE: qiushibaike/qiushibaike/middlewares.py ================================================ # -*- coding: utf-8 -*- # Define here the models for your spider middleware # # See documentation in: # https://doc.scrapy.org/en/latest/topics/spider-middleware.html from scrapy import signals class QiushibaikeSpiderMiddleware(object): # Not all methods need to be defined. If a method is not defined, # scrapy acts as if the spider middleware does not modify the # passed objects. @classmethod def from_crawler(cls, crawler): # This method is used by Scrapy to create your spiders. s = cls() crawler.signals.connect(s.spider_opened, signal=signals.spider_opened) return s def process_spider_input(self, response, spider): # Called for each response that goes through the spider # middleware and into the spider. # Should return None or raise an exception. return None def process_spider_output(self, response, result, spider): # Called with the results returned from the Spider, after # it has processed the response. # Must return an iterable of Request, dict or Item objects. for i in result: yield i def process_spider_exception(self, response, exception, spider): # Called when a spider or process_spider_input() method # (from other spider middleware) raises an exception. # Should return either None or an iterable of Response, dict # or Item objects. pass def process_start_requests(self, start_requests, spider): # Called with the start requests of the spider, and works # similarly to the process_spider_output() method, except # that it doesn’t have a response associated. # Must return only requests (not items). for r in start_requests: yield r def spider_opened(self, spider): spider.logger.info('Spider opened: %s' % spider.name) class QiushibaikeDownloaderMiddleware(object): # Not all methods need to be defined. If a method is not defined, # scrapy acts as if the downloader middleware does not modify the # passed objects. @classmethod def from_crawler(cls, crawler): # This method is used by Scrapy to create your spiders. s = cls() crawler.signals.connect(s.spider_opened, signal=signals.spider_opened) return s def process_request(self, request, spider): # Called for each request that goes through the downloader # middleware. # Must either: # - return None: continue processing this request # - or return a Response object # - or return a Request object # - or raise IgnoreRequest: process_exception() methods of # installed downloader middleware will be called return None def process_response(self, request, response, spider): # Called with the response returned from the downloader. # Must either; # - return a Response object # - return a Request object # - or raise IgnoreRequest return response def process_exception(self, request, exception, spider): # Called when a download handler or a process_request() # (from other downloader middleware) raises an exception. # Must either: # - return None: continue processing this exception # - return a Response object: stops process_exception() chain # - return a Request object: stops process_exception() chain pass def spider_opened(self, spider): spider.logger.info('Spider opened: %s' % spider.name) ================================================ FILE: qiushibaike/qiushibaike/pipelines.py ================================================ # -*- coding: utf-8 -*- # Define your item pipelines here # # Don't forget to add your pipeline to the ITEM_PIPELINES setting # See: https://doc.scrapy.org/en/latest/topics/item-pipeline.html import pymongo class QiushibaikePipeline(object): def __init__(self): self.connection = pymongo.MongoClient('localhost', 27017) self.db = self.connection.scrapy self.collection = self.db.qiushibaike def process_item(self, item, spider): if not self.connection or not item: return self.collection.save(item) def __del__(self): if self.connection: self.connection.close() ================================================ FILE: qiushibaike/qiushibaike/settings.py ================================================ # -*- coding: utf-8 -*- # Scrapy settings for qiushibaike project # # For simplicity, this file contains only settings considered important or # commonly used. You can find more settings consulting the documentation: # # https://doc.scrapy.org/en/latest/topics/settings.html # https://doc.scrapy.org/en/latest/topics/downloader-middleware.html # https://doc.scrapy.org/en/latest/topics/spider-middleware.html BOT_NAME = 'qiushibaike' SPIDER_MODULES = ['qiushibaike.spiders'] NEWSPIDER_MODULE = 'qiushibaike.spiders' FEED_EXPORT_ENCODING = 'utf-8' # Crawl responsibly by identifying yourself (and your website) on the user-agent USER_AGENT = 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Ubuntu Chromium/73.0.3683.86 Chrome/73.0.3683.86 Safari/537.36' # Obey robots.txt rules ROBOTSTXT_OBEY = True # Configure maximum concurrent requests performed by Scrapy (default: 16) #CONCURRENT_REQUESTS = 32 # Configure a delay for requests for the same website (default: 0) # See https://doc.scrapy.org/en/latest/topics/settings.html#download-delay # See also autothrottle settings and docs #DOWNLOAD_DELAY = 3 # The download delay setting will honor only one of: #CONCURRENT_REQUESTS_PER_DOMAIN = 16 #CONCURRENT_REQUESTS_PER_IP = 16 # Disable cookies (enabled by default) #COOKIES_ENABLED = False # Disable Telnet Console (enabled by default) #TELNETCONSOLE_ENABLED = False # Override the default request headers: #DEFAULT_REQUEST_HEADERS = { # 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', # 'Accept-Language': 'en', #} # Enable or disable spider middlewares # See https://doc.scrapy.org/en/latest/topics/spider-middleware.html #SPIDER_MIDDLEWARES = { # 'qiushibaike.middlewares.QiushibaikeSpiderMiddleware': 543, #} # Enable or disable downloader middlewares # See https://doc.scrapy.org/en/latest/topics/downloader-middleware.html #DOWNLOADER_MIDDLEWARES = { # 'qiushibaike.middlewares.QiushibaikeDownloaderMiddleware': 543, #} # Enable or disable extensions # See https://doc.scrapy.org/en/latest/topics/extensions.html #EXTENSIONS = { # 'scrapy.extensions.telnet.TelnetConsole': None, #} # Configure item pipelines # See https://doc.scrapy.org/en/latest/topics/item-pipeline.html ITEM_PIPELINES = { 'qiushibaike.pipelines.QiushibaikePipeline': 300, } # Enable and configure the AutoThrottle extension (disabled by default) # See https://doc.scrapy.org/en/latest/topics/autothrottle.html #AUTOTHROTTLE_ENABLED = True # The initial download delay #AUTOTHROTTLE_START_DELAY = 5 # The maximum download delay to be set in case of high latencies #AUTOTHROTTLE_MAX_DELAY = 60 # The average number of requests Scrapy should be sending in parallel to # each remote server #AUTOTHROTTLE_TARGET_CONCURRENCY = 1.0 # Enable showing throttling stats for every response received: #AUTOTHROTTLE_DEBUG = False # Enable and configure HTTP caching (disabled by default) # See https://doc.scrapy.org/en/latest/topics/downloader-middleware.html#httpcache-middleware-settings #HTTPCACHE_ENABLED = True #HTTPCACHE_EXPIRATION_SECS = 0 #HTTPCACHE_DIR = 'httpcache' #HTTPCACHE_IGNORE_HTTP_CODES = [] #HTTPCACHE_STORAGE = 'scrapy.extensions.httpcache.FilesystemCacheStorage' ================================================ FILE: qiushibaike/qiushibaike/spiders/__init__.py ================================================ # This package will contain the spiders of your Scrapy project # # Please refer to the documentation for information on how to create and manage # your spiders. ================================================ FILE: qiushibaike/qiushibaike/spiders/qiushibaike_spider.py ================================================ # -*- coding: utf-8 -*- import random import scrapy from qiushibaike.items import QiushibaikeItem class QiushiSpider(scrapy.Spider): # 这里定义一个唯一的名称,用来标识糗事的爬虫,在项目中不能和别的爬虫名称一样,等会会用到这个名称 name = "qiushibaike" def start_requests(self): urls = [ 'https://www.qiushibaike.com/text/page/1/', ] for url in urls: yield scrapy.Request(url=url, callback=self.parse) def parse(self, response): content_left_div = response.xpath('//*[@id="content-left"]') content_list_div = content_left_div.xpath('./div') for content_div in content_list_div: item = QiushibaikeItem() item['author'] = content_div.xpath('./div/a[2]/h2/text()').get() item['content'] = content_div.xpath('./a/div/span/text()').getall() item['_id'] = content_div.attrib['id'] yield item next_page = response.xpath('//*[@id="content-left"]/ul/li[last()]/a').attrib['href'] if next_page is not None: yield response.follow(next_page, callback=self.parse) ================================================ FILE: qiushibaike/scrapy.cfg ================================================ # Automatically created by: scrapy startproject # # For more information about the [deploy] section see: # https://scrapyd.readthedocs.io/en/latest/deploy.html [settings] default = qiushibaike.settings [deploy] #url = http://localhost:6800/ project = qiushibaike ================================================ FILE: stackoverflow/.idea/inspectionProfiles/profiles_settings.xml ================================================ ================================================ FILE: stackoverflow/.idea/misc.xml ================================================ ================================================ FILE: stackoverflow/.idea/modules.xml ================================================ ================================================ FILE: stackoverflow/.idea/stackoverflow.iml ================================================ ================================================ FILE: stackoverflow/.idea/vcs.xml ================================================ ================================================ FILE: stackoverflow/.idea/workspace.xml ================================================ 1571212815240 ================================================ FILE: stackoverflow/scrapy.cfg ================================================ # Automatically created by: scrapy startproject # # For more information about the [deploy] section see: # https://scrapyd.readthedocs.io/en/latest/deploy.html [settings] default = stackoverflow.settings [deploy] #url = http://localhost:6800/ project = stackoverflow ================================================ FILE: stackoverflow/stackoverflow/__init__.py ================================================ ================================================ FILE: stackoverflow/stackoverflow/items.py ================================================ # -*- coding: utf-8 -*- # Define here the models for your scraped items # # See documentation in: # https://doc.scrapy.org/en/latest/topics/items.html import scrapy class StackoverflowPythonItem(scrapy.Item): _id = scrapy.Field() questions = scrapy.Field() votes = scrapy.Field() answers = scrapy.Field() views = scrapy.Field() links = scrapy.Field() ================================================ FILE: stackoverflow/stackoverflow/middlewares/StackoverflowDownloaderMiddleware.py ================================================ from scrapy.downloadermiddlewares.httpproxy import HttpProxyMiddleware class HttpProxy(HttpProxyMiddleware): @staticmethod def proxy_shadowsocks(): proxy = "http://127.0.0.1:1080" return proxy ================================================ FILE: stackoverflow/stackoverflow/middlewares/__init__.py ================================================ ================================================ FILE: stackoverflow/stackoverflow/middlewares.py ================================================ # -*- coding: utf-8 -*- # Define here the models for your spider middleware # # See documentation in: # https://doc.scrapy.org/en/latest/topics/spider-middleware.html from scrapy import signals class StackoverflowSpiderMiddleware(object): # Not all methods need to be defined. If a method is not defined, # scrapy acts as if the spider middleware does not modify the # passed objects. @classmethod def from_crawler(cls, crawler): # This method is used by Scrapy to create your spiders. s = cls() crawler.signals.connect(s.spider_opened, signal=signals.spider_opened) return s def process_spider_input(self, response, spider): # Called for each response that goes through the spider # middleware and into the spider. # Should return None or raise an exception. return None def process_spider_output(self, response, result, spider): # Called with the results returned from the Spider, after # it has processed the response. # Must return an iterable of Request, dict or Item objects. for i in result: yield i def process_spider_exception(self, response, exception, spider): # Called when a spider or process_spider_input() method # (from other spider middleware) raises an exception. # Should return either None or an iterable of Response, dict # or Item objects. pass def process_start_requests(self, start_requests, spider): # Called with the start requests of the spider, and works # similarly to the process_spider_output() method, except # that it doesn’t have a response associated. # Must return only requests (not items). for r in start_requests: yield r def spider_opened(self, spider): spider.logger.info('Spider opened: %s' % spider.name) class StackoverflowDownloaderMiddleware(object): # Not all methods need to be defined. If a method is not defined, # scrapy acts as if the downloader middleware does not modify the # passed objects. @classmethod def from_crawler(cls, crawler): # This method is used by Scrapy to create your spiders. s = cls() crawler.signals.connect(s.spider_opened, signal=signals.spider_opened) return s def process_request(self, request, spider): # Called for each request that goes through the downloader # middleware. # Must either: # - return None: continue processing this request # - or return a Response object # - or return a Request object # - or raise IgnoreRequest: process_exception() methods of # installed downloader middleware will be called return None def process_response(self, request, response, spider): # Called with the response returned from the downloader. # Must either; # - return a Response object # - return a Request object # - or raise IgnoreRequest return response def process_exception(self, request, exception, spider): # Called when a download handler or a process_request() # (from other downloader middleware) raises an exception. # Must either: # - return None: continue processing this exception # - return a Response object: stops process_exception() chain # - return a Request object: stops process_exception() chain pass def spider_opened(self, spider): spider.logger.info('Spider opened: %s' % spider.name) ================================================ FILE: stackoverflow/stackoverflow/pipelines.py ================================================ # -*- coding: utf-8 -*- # Define your item pipelines here # # Don't forget to add your pipeline to the ITEM_PIPELINES setting # See: https://doc.scrapy.org/en/latest/topics/item-pipeline.html import pymongo class StackoverflowPipeline(object): def __init__(self): self.connection = pymongo.MongoClient('68.183.180.71', 27017) self.db = self.connection.scrapy self.collection = self.db.stackoverflow def process_item(self, item, spider): if not self.connection or not item: return self.collection.save(item) def __del__(self): if self.connection: self.connection.close() ================================================ FILE: stackoverflow/stackoverflow/requirement.txt ================================================ pymongo==3.9.0 redis==3.3.11 Scrapy==1.7.4 scrapy-redis==0.6.8 lxml==4.4.1 parsel==1.5.2 ================================================ FILE: stackoverflow/stackoverflow/settings.py ================================================ # -*- coding: utf-8 -*- # Scrapy settings for stackoverflow project # # For simplicity, this file contains only settings considered important or # commonly used. You can find more settings consulting the documentation: # # https://doc.scrapy.org/en/latest/topics/settings.html # https://doc.scrapy.org/en/latest/topics/downloader-middleware.html # https://doc.scrapy.org/en/latest/topics/spider-middleware.html BOT_NAME = 'stackoverflow' SPIDER_MODULES = ['stackoverflow.spiders'] NEWSPIDER_MODULE = 'stackoverflow.spiders' # Crawl responsibly by identifying yourself (and your website) on the user-agent USER_AGENT = 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Ubuntu Chromium/73.0.3683.86 Chrome/73.0.3683.86 Safari/537.36' # Obey robots.txt rules ROBOTSTXT_OBEY = True # Configure maximum concurrent requests performed by Scrapy (default: 16) #CONCURRENT_REQUESTS = 32 # Configure a delay for requests for the same website (default: 0) # See https://doc.scrapy.org/en/latest/topics/settings.html#download-delay # See also autothrottle settings and docs DOWNLOAD_DELAY = 1 # The download delay setting will honor only one of: #CONCURRENT_REQUESTS_PER_DOMAIN = 16 #CONCURRENT_REQUESTS_PER_IP = 16 # Disable cookies (enabled by default) #COOKIES_ENABLED = False # Disable Telnet Console (enabled by default) #TELNETCONSOLE_ENABLED = False # Override the default request headers: #DEFAULT_REQUEST_HEADERS = { # 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', # 'Accept-Language': 'en', #} # Enable or disable spider middlewares # See https://doc.scrapy.org/en/latest/topics/spider-middleware.html #SPIDER_MIDDLEWARES = { # 'stackoverflow.middlewares.StackoverflowSpiderMiddleware': 543, #} # Enable or disable downloader middlewares # See https://doc.scrapy.org/en/latest/topics/downloader-middleware.html DOWNLOADER_MIDDLEWARES = { 'stackoverflow.middlewares.StackoverflowDownloaderMiddleware.HttpProxy': 543, } # Enable or disable extensions # See https://doc.scrapy.org/en/latest/topics/extensions.html #EXTENSIONS = { # 'scrapy.extensions.telnet.TelnetConsole': None, #} # Configure item pipelines # See https://doc.scrapy.org/en/latest/topics/item-pipeline.html ITEM_PIPELINES = { 'stackoverflow.pipelines.StackoverflowPipeline': 300, } # Enable and configure the AutoThrottle extension (disabled by default) # See https://doc.scrapy.org/en/latest/topics/autothrottle.html #AUTOTHROTTLE_ENABLED = True # The initial download delay #AUTOTHROTTLE_START_DELAY = 5 # The maximum download delay to be set in case of high latencies #AUTOTHROTTLE_MAX_DELAY = 60 # The average number of requests Scrapy should be sending in parallel to # each remote server #AUTOTHROTTLE_TARGET_CONCURRENCY = 1.0 # Enable showing throttling stats for every response received: #AUTOTHROTTLE_DEBUG = False # Enable and configure HTTP caching (disabled by default) # See https://doc.scrapy.org/en/latest/topics/downloader-middleware.html#httpcache-middleware-settings #HTTPCACHE_ENABLED = True #HTTPCACHE_EXPIRATION_SECS = 0 #HTTPCACHE_DIR = 'httpcache' #HTTPCACHE_IGNORE_HTTP_CODES = [] #HTTPCACHE_STORAGE = 'scrapy.extensions.httpcache.FilesystemCacheStorage' # 调度器改为 scrapy_redis SCHEDULER = 'scrapy_redis.scheduler.Scheduler' # redis 去重 DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter" # redis服务器地址 REDIS_HOST = '68.183.180.0' REDIS_PORT = 6379 ================================================ FILE: stackoverflow/stackoverflow/spiders/__init__.py ================================================ # This package will contain the spiders of your Scrapy project # # Please refer to the documentation for information on how to create and manage # your spiders. ================================================ FILE: stackoverflow/stackoverflow/spiders/stackoverflow-python-spider.py ================================================ import scrapy from stackoverflow.items import StackoverflowPythonItem class StackoverflowPythonSpider(scrapy.Spider): name = "stackoverflow-python" def start_requests(self): urls = [] _url = 'https://stackoverflow.com/questions/tagged/python?tab=votes&page={}&pagesize=15' for page in range(1, 84322): urls.append(_url.format(page)) for url in urls: yield scrapy.Request(url=url, callback=self.parse) def parse(self, response): question_list = response.xpath('//*[@id="questions"]') for question in question_list.xpath('./div'): item = StackoverflowPythonItem() item['_id'] = question.attrib['id'] item['questions'] = question.xpath('div[2]/h3/a/text()').extract() item['votes'] = question.xpath( 'div[1]/div[1]/div[1]/div[1]/span/strong/text()').extract() item['answers'] = question.xpath( 'div[1]/div[1]/div[2]/strong/text()').extract() item['views'] = question.xpath('div[1]/div[2]/@title').extract() item['links'] = question.xpath('div[2]/h3/a/@href').extract() yield item ================================================ FILE: stackoverflow/venv/bin/activate ================================================ # This file must be used with "source bin/activate" *from bash* # you cannot run it directly deactivate () { # reset old environment variables if [ -n "${_OLD_VIRTUAL_PATH:-}" ] ; then PATH="${_OLD_VIRTUAL_PATH:-}" export PATH unset _OLD_VIRTUAL_PATH fi if [ -n "${_OLD_VIRTUAL_PYTHONHOME:-}" ] ; then PYTHONHOME="${_OLD_VIRTUAL_PYTHONHOME:-}" export PYTHONHOME unset _OLD_VIRTUAL_PYTHONHOME fi # This should detect bash and zsh, which have a hash command that must # be called to get it to forget past commands. Without forgetting # past commands the $PATH changes we made may not be respected if [ -n "${BASH:-}" -o -n "${ZSH_VERSION:-}" ] ; then hash -r fi if [ -n "${_OLD_VIRTUAL_PS1:-}" ] ; then PS1="${_OLD_VIRTUAL_PS1:-}" export PS1 unset _OLD_VIRTUAL_PS1 fi unset VIRTUAL_ENV if [ ! "$1" = "nondestructive" ] ; then # Self destruct! unset -f deactivate fi } # unset irrelevant variables deactivate nondestructive VIRTUAL_ENV="/home/wistbean/githubproject/learn_python3_spider/stackoverflow/venv" export VIRTUAL_ENV _OLD_VIRTUAL_PATH="$PATH" PATH="$VIRTUAL_ENV/bin:$PATH" export PATH # unset PYTHONHOME if set # this will fail if PYTHONHOME is set to the empty string (which is bad anyway) # could use `if (set -u; : $PYTHONHOME) ;` in bash if [ -n "${PYTHONHOME:-}" ] ; then _OLD_VIRTUAL_PYTHONHOME="${PYTHONHOME:-}" unset PYTHONHOME fi if [ -z "${VIRTUAL_ENV_DISABLE_PROMPT:-}" ] ; then _OLD_VIRTUAL_PS1="${PS1:-}" if [ "x(venv) " != x ] ; then PS1="(venv) ${PS1:-}" else if [ "`basename \"$VIRTUAL_ENV\"`" = "__" ] ; then # special case for Aspen magic directories # see http://www.zetadev.com/software/aspen/ PS1="[`basename \`dirname \"$VIRTUAL_ENV\"\``] $PS1" else PS1="(`basename \"$VIRTUAL_ENV\"`)$PS1" fi fi export PS1 fi # This should detect bash and zsh, which have a hash command that must # be called to get it to forget past commands. Without forgetting # past commands the $PATH changes we made may not be respected if [ -n "${BASH:-}" -o -n "${ZSH_VERSION:-}" ] ; then hash -r fi ================================================ FILE: stackoverflow/venv/bin/activate.csh ================================================ # This file must be used with "source bin/activate.csh" *from csh*. # You cannot run it directly. # Created by Davide Di Blasi . # Ported to Python 3.3 venv by Andrew Svetlov alias deactivate 'test $?_OLD_VIRTUAL_PATH != 0 && setenv PATH "$_OLD_VIRTUAL_PATH" && unset _OLD_VIRTUAL_PATH; rehash; test $?_OLD_VIRTUAL_PROMPT != 0 && set prompt="$_OLD_VIRTUAL_PROMPT" && unset _OLD_VIRTUAL_PROMPT; unsetenv VIRTUAL_ENV; test "\!:*" != "nondestructive" && unalias deactivate' # Unset irrelevant variables. deactivate nondestructive setenv VIRTUAL_ENV "/home/wistbean/githubproject/learn_python3_spider/stackoverflow/venv" set _OLD_VIRTUAL_PATH="$PATH" setenv PATH "$VIRTUAL_ENV/bin:$PATH" set _OLD_VIRTUAL_PROMPT="$prompt" if (! "$?VIRTUAL_ENV_DISABLE_PROMPT") then if ("venv" != "") then set env_name = "venv" else if (`basename "VIRTUAL_ENV"` == "__") then # special case for Aspen magic directories # see http://www.zetadev.com/software/aspen/ set env_name = `basename \`dirname "$VIRTUAL_ENV"\`` else set env_name = `basename "$VIRTUAL_ENV"` endif endif set prompt = "[$env_name] $prompt" unset env_name endif alias pydoc python -m pydoc rehash ================================================ FILE: stackoverflow/venv/bin/activate.fish ================================================ # This file must be used with ". bin/activate.fish" *from fish* (http://fishshell.org) # you cannot run it directly function deactivate -d "Exit virtualenv and return to normal shell environment" # reset old environment variables if test -n "$_OLD_VIRTUAL_PATH" set -gx PATH $_OLD_VIRTUAL_PATH set -e _OLD_VIRTUAL_PATH end if test -n "$_OLD_VIRTUAL_PYTHONHOME" set -gx PYTHONHOME $_OLD_VIRTUAL_PYTHONHOME set -e _OLD_VIRTUAL_PYTHONHOME end if test -n "$_OLD_FISH_PROMPT_OVERRIDE" functions -e fish_prompt set -e _OLD_FISH_PROMPT_OVERRIDE functions -c _old_fish_prompt fish_prompt functions -e _old_fish_prompt end set -e VIRTUAL_ENV if test "$argv[1]" != "nondestructive" # Self destruct! functions -e deactivate end end # unset irrelevant variables deactivate nondestructive set -gx VIRTUAL_ENV "/home/wistbean/githubproject/learn_python3_spider/stackoverflow/venv" set -gx _OLD_VIRTUAL_PATH $PATH set -gx PATH "$VIRTUAL_ENV/bin" $PATH # unset PYTHONHOME if set if set -q PYTHONHOME set -gx _OLD_VIRTUAL_PYTHONHOME $PYTHONHOME set -e PYTHONHOME end if test -z "$VIRTUAL_ENV_DISABLE_PROMPT" # fish uses a function instead of an env var to generate the prompt. # save the current fish_prompt function as the function _old_fish_prompt functions -c fish_prompt _old_fish_prompt # with the original prompt function renamed, we can override with our own. function fish_prompt # Save the return status of the last command set -l old_status $status # Prompt override? if test -n "(venv) " printf "%s%s" "(venv) " (set_color normal) else # ...Otherwise, prepend env set -l _checkbase (basename "$VIRTUAL_ENV") if test $_checkbase = "__" # special case for Aspen magic directories # see http://www.zetadev.com/software/aspen/ printf "%s[%s]%s " (set_color -b blue white) (basename (dirname "$VIRTUAL_ENV")) (set_color normal) else printf "%s(%s)%s" (set_color -b blue white) (basename "$VIRTUAL_ENV") (set_color normal) end end # Restore the return status of the previous command. echo "exit $old_status" | . _old_fish_prompt end set -gx _OLD_FISH_PROMPT_OVERRIDE "$VIRTUAL_ENV" end ================================================ FILE: stackoverflow/venv/bin/automat-visualize ================================================ #!/home/wistbean/githubproject/learn_python3_spider/stackoverflow/venv/bin/python # -*- coding: utf-8 -*- import re import sys from automat._visualize import tool if __name__ == '__main__': sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0]) sys.exit(tool()) ================================================ FILE: stackoverflow/venv/bin/cftp ================================================ #!/home/wistbean/githubproject/learn_python3_spider/stackoverflow/venv/bin/python # -*- coding: utf-8 -*- import re import sys from twisted.conch.scripts.cftp import run if __name__ == '__main__': sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0]) sys.exit(run()) ================================================ FILE: stackoverflow/venv/bin/ckeygen ================================================ #!/home/wistbean/githubproject/learn_python3_spider/stackoverflow/venv/bin/python # -*- coding: utf-8 -*- import re import sys from twisted.conch.scripts.ckeygen import run if __name__ == '__main__': sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0]) sys.exit(run()) ================================================ FILE: stackoverflow/venv/bin/conch ================================================ #!/home/wistbean/githubproject/learn_python3_spider/stackoverflow/venv/bin/python # -*- coding: utf-8 -*- import re import sys from twisted.conch.scripts.conch import run if __name__ == '__main__': sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0]) sys.exit(run()) ================================================ FILE: stackoverflow/venv/bin/easy_install ================================================ #!/home/wistbean/githubproject/learn_python3_spider/stackoverflow/venv/bin/python # EASY-INSTALL-ENTRY-SCRIPT: 'setuptools==40.8.0','console_scripts','easy_install' __requires__ = 'setuptools==40.8.0' import re import sys from pkg_resources import load_entry_point if __name__ == '__main__': sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0]) sys.exit( load_entry_point('setuptools==40.8.0', 'console_scripts', 'easy_install')() ) ================================================ FILE: stackoverflow/venv/bin/easy_install-3.6 ================================================ #!/home/wistbean/githubproject/learn_python3_spider/stackoverflow/venv/bin/python # EASY-INSTALL-ENTRY-SCRIPT: 'setuptools==40.8.0','console_scripts','easy_install-3.6' __requires__ = 'setuptools==40.8.0' import re import sys from pkg_resources import load_entry_point if __name__ == '__main__': sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0]) sys.exit( load_entry_point('setuptools==40.8.0', 'console_scripts', 'easy_install-3.6')() ) ================================================ FILE: stackoverflow/venv/bin/mailmail ================================================ #!/home/wistbean/githubproject/learn_python3_spider/stackoverflow/venv/bin/python # -*- coding: utf-8 -*- import re import sys from twisted.mail.scripts.mailmail import run if __name__ == '__main__': sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0]) sys.exit(run()) ================================================ FILE: stackoverflow/venv/bin/pip ================================================ #!/home/wistbean/githubproject/learn_python3_spider/stackoverflow/venv/bin/python # EASY-INSTALL-ENTRY-SCRIPT: 'pip==19.0.3','console_scripts','pip' __requires__ = 'pip==19.0.3' import re import sys from pkg_resources import load_entry_point if __name__ == '__main__': sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0]) sys.exit( load_entry_point('pip==19.0.3', 'console_scripts', 'pip')() ) ================================================ FILE: stackoverflow/venv/bin/pip3 ================================================ #!/home/wistbean/githubproject/learn_python3_spider/stackoverflow/venv/bin/python # EASY-INSTALL-ENTRY-SCRIPT: 'pip==19.0.3','console_scripts','pip3' __requires__ = 'pip==19.0.3' import re import sys from pkg_resources import load_entry_point if __name__ == '__main__': sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0]) sys.exit( load_entry_point('pip==19.0.3', 'console_scripts', 'pip3')() ) ================================================ FILE: stackoverflow/venv/bin/pip3.6 ================================================ #!/home/wistbean/githubproject/learn_python3_spider/stackoverflow/venv/bin/python # EASY-INSTALL-ENTRY-SCRIPT: 'pip==19.0.3','console_scripts','pip3.6' __requires__ = 'pip==19.0.3' import re import sys from pkg_resources import load_entry_point if __name__ == '__main__': sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0]) sys.exit( load_entry_point('pip==19.0.3', 'console_scripts', 'pip3.6')() ) ================================================ FILE: stackoverflow/venv/bin/pyhtmlizer ================================================ #!/home/wistbean/githubproject/learn_python3_spider/stackoverflow/venv/bin/python # -*- coding: utf-8 -*- import re import sys from twisted.scripts.htmlizer import run if __name__ == '__main__': sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0]) sys.exit(run()) ================================================ FILE: stackoverflow/venv/bin/scrapy ================================================ #!/home/wistbean/githubproject/learn_python3_spider/stackoverflow/venv/bin/python # -*- coding: utf-8 -*- import re import sys from scrapy.cmdline import execute if __name__ == '__main__': sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0]) sys.exit(execute()) ================================================ FILE: stackoverflow/venv/bin/tkconch ================================================ #!/home/wistbean/githubproject/learn_python3_spider/stackoverflow/venv/bin/python # -*- coding: utf-8 -*- import re import sys from twisted.conch.scripts.tkconch import run if __name__ == '__main__': sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0]) sys.exit(run()) ================================================ FILE: stackoverflow/venv/bin/trial ================================================ #!/home/wistbean/githubproject/learn_python3_spider/stackoverflow/venv/bin/python # -*- coding: utf-8 -*- import re import sys from twisted.scripts.trial import run if __name__ == '__main__': sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0]) sys.exit(run()) ================================================ FILE: stackoverflow/venv/bin/twist ================================================ #!/home/wistbean/githubproject/learn_python3_spider/stackoverflow/venv/bin/python # -*- coding: utf-8 -*- import re import sys from twisted.application.twist._twist import Twist if __name__ == '__main__': sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0]) sys.exit(Twist.main()) ================================================ FILE: stackoverflow/venv/bin/twistd ================================================ #!/home/wistbean/githubproject/learn_python3_spider/stackoverflow/venv/bin/python # -*- coding: utf-8 -*- import re import sys from twisted.scripts.twistd import run if __name__ == '__main__': sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0]) sys.exit(run()) ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/Automat-0.8.0.dist-info/INSTALLER ================================================ pip ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/Automat-0.8.0.dist-info/LICENSE ================================================ Copyright (c) 2014 Rackspace Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/Automat-0.8.0.dist-info/METADATA ================================================ Metadata-Version: 2.1 Name: Automat Version: 0.8.0 Summary: Self-service finite-state machines for the programmer on the go. Home-page: https://github.com/glyph/Automat Author: Glyph Author-email: glyph@twistedmatrix.com License: MIT Keywords: fsm finite state machine automata Platform: UNKNOWN Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: MIT License Classifier: Operating System :: OS Independent Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 2 Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: 3.5 Classifier: Programming Language :: Python :: 3.6 Classifier: Programming Language :: Python :: 3.7 Classifier: Programming Language :: Python :: 3.8 Requires-Dist: attrs (>=16.1.0) Requires-Dist: six Provides-Extra: visualize Requires-Dist: graphviz (>0.5.1) ; extra == 'visualize' Requires-Dist: Twisted (>=16.1.1) ; extra == 'visualize' Automat ======= .. image:: https://readthedocs.org/projects/automat/badge/?version=latest :target: http://automat.readthedocs.io/en/latest/ :alt: Documentation Status .. image:: https://travis-ci.org/glyph/automat.svg?branch=master :target: https://travis-ci.org/glyph/automat :alt: Build Status .. image:: https://coveralls.io/repos/glyph/automat/badge.png :target: https://coveralls.io/r/glyph/automat :alt: Coverage Status Self-service finite-state machines for the programmer on the go. ---------------------------------------------------------------- Automat is a library for concise, idiomatic Python expression of finite-state automata (particularly deterministic finite-state transducers). Read more here, or on `Read the Docs `_\ , or watch the following videos for an overview and presentation Overview and presentation by **Glyph Lefkowitz** at the first talk of the first Pyninsula meetup, on February 21st, 2017: .. image:: https://img.youtube.com/vi/0wOZBpD1VVk/0.jpg :target: https://www.youtube.com/watch?v=0wOZBpD1VVk :alt: Glyph Lefkowitz - Automat - Pyninsula #0 Presentation by **Clinton Roy** at PyCon Australia, on August 6th 2017: .. image:: https://img.youtube.com/vi/TedUKXhu9kE/0.jpg :target: https://www.youtube.com/watch?v=TedUKXhu9kE :alt: Clinton Roy - State Machines - Pycon Australia 2017 Why use state machines? ^^^^^^^^^^^^^^^^^^^^^^^ Sometimes you have to create an object whose behavior varies with its state, but still wishes to present a consistent interface to its callers. For example, let's say you're writing the software for a coffee machine. It has a lid that can be opened or closed, a chamber for water, a chamber for coffee beans, and a button for "brew". There are a number of possible states for the coffee machine. It might or might not have water. It might or might not have beans. The lid might be open or closed. The "brew" button should only actually attempt to brew coffee in one of these configurations, and the "open lid" button should only work if the coffee is not, in fact, brewing. With diligence and attention to detail, you can implement this correctly using a collection of attributes on an object; ``has_water``\ , ``has_beans``\ , ``is_lid_open`` and so on. However, you have to keep all these attributes consistent. As the coffee maker becomes more complex - perhaps you add an additional chamber for flavorings so you can make hazelnut coffee, for example - you have to keep adding more and more checks and more and more reasoning about which combinations of states are allowed. Rather than adding tedious 'if' checks to every single method to make sure that each of these flags are exactly what you expect, you can use a state machine to ensure that if your code runs at all, it will be run with all the required values initialized, because they have to be called in the order you declare them. You can read about state machines and their advantages for Python programmers in considerably more detail `in this excellent series of articles from ClusterHQ `_. What makes Automat different? ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ There are `dozens of libraries on PyPI implementing state machines `_. So it behooves me to say why yet another one would be a good idea. Automat is designed around this principle: while organizing your code around state machines is a good idea, your callers don't, and shouldn't have to, care that you've done so. In Python, the "input" to a stateful system is a method call; the "output" may be a method call, if you need to invoke a side effect, or a return value, if you are just performing a computation in memory. Most other state-machine libraries require you to explicitly create an input object, provide that object to a generic "input" method, and then receive results, sometimes in terms of that library's interfaces and sometimes in terms of classes you define yourself. For example, a snippet of the coffee-machine example above might be implemented as follows in naive Python: .. code-block:: python class CoffeeMachine(object): def brew_button(self): if self.has_water and self.has_beans and not self.is_lid_open: self.heat_the_heating_element() # ... With Automat, you'd create a class with a ``MethodicalMachine`` attribute: .. code-block:: python from automat import MethodicalMachine class CoffeeBrewer(object): _machine = MethodicalMachine() and then you would break the above logic into two pieces - the ``brew_button`` *input*\ , declared like so: .. code-block:: python @_machine.input() def brew_button(self): "The user pressed the 'brew' button." It wouldn't do any good to declare a method *body* on this, however, because input methods don't actually execute their bodies when called; doing actual work is the *output*\ 's job: .. code-block:: python @_machine.output() def _heat_the_heating_element(self): "Heat up the heating element, which should cause coffee to happen." self._heating_element.turn_on() As well as a couple of *states* - and for simplicity's sake let's say that the only two states are ``have_beans`` and ``dont_have_beans``\ : .. code-block:: python @_machine.state() def have_beans(self): "In this state, you have some beans." @_machine.state(initial=True) def dont_have_beans(self): "In this state, you don't have any beans." ``dont_have_beans`` is the ``initial`` state because ``CoffeeBrewer`` starts without beans in it. (And another input to put some beans in:) .. code-block:: python @_machine.input() def put_in_beans(self): "The user put in some beans." Finally, you hook everything together with the ``upon`` method of the functions decorated with ``_machine.state``\ : .. code-block:: python # When we don't have beans, upon putting in beans, we will then have beans # (and produce no output) dont_have_beans.upon(put_in_beans, enter=have_beans, outputs=[]) # When we have beans, upon pressing the brew button, we will then not have # beans any more (as they have been entered into the brewing chamber) and # our output will be heating the heating element. have_beans.upon(brew_button, enter=dont_have_beans, outputs=[_heat_the_heating_element]) To *users* of this coffee machine class though, it still looks like a POPO (Plain Old Python Object): .. code-block:: python >>> coffee_machine = CoffeeMachine() >>> coffee_machine.put_in_beans() >>> coffee_machine.brew_button() All of the *inputs* are provided by calling them like methods, all of the *outputs* are automatically invoked when they are produced according to the outputs specified to ``upon`` and all of the states are simply opaque tokens - although the fact that they're defined as methods like inputs and outputs allows you to put docstrings on them easily to document them. How do I get the current state of a state machine? -------------------------------------------------- Don't do that. One major reason for having a state machine is that you want the callers of the state machine to just provide the appropriate input to the machine at the appropriate time, and *not have to check themselves* what state the machine is in. So if you are tempted to write some code like this: .. code-block:: python if connection_state_machine.state == "CONNECTED": connection_state_machine.send_message() else: print("not connected") Instead, just make your calling code do this: .. code-block:: python connection_state_machine.send_message() and then change your state machine to look like this: .. code-block:: python @_machine.state() def connected(self): "connected" @_machine.state() def not_connected(self): "not connected" @_machine.input() def send_message(self): "send a message" @_machine.output() def _actually_send_message(self): self._transport.send(b"message") @_machine.output() def _report_sending_failure(self): print("not connected") connected.upon(send_message, enter=connected, [_actually_send_message]) not_connected.upon(send_message, enter=not_connected, [_report_sending_failure]) so that the responsibility for knowing which state the state machine is in remains within the state machine itself. Input for Inputs and Output for Outputs --------------------------------------- Quite often you want to be able to pass parameters to your methods, as well as inspecting their results. For example, when you brew the coffee, you might expect a cup of coffee to result, and you would like to see what kind of coffee it is. And if you were to put delicious hand-roasted small-batch artisanal beans into the machine, you would expect a *better* cup of coffee than if you were to use mass-produced beans. You would do this in plain old Python by adding a parameter, so that's how you do it in Automat as well. .. code-block:: python @_machine.input() def put_in_beans(self, beans): "The user put in some beans." However, one important difference here is that *we can't add any implementation code to the input method*. Inputs are purely a declaration of the interface; the behavior must all come from outputs. Therefore, the change in the state of the coffee machine must be represented as an output. We can add an output method like this: .. code-block:: python @_machine.output() def _save_beans(self, beans): "The beans are now in the machine; save them." self._beans = beans and then connect it to the ``put_in_beans`` by changing the transition from ``dont_have_beans`` to ``have_beans`` like so: .. code-block:: python dont_have_beans.upon(put_in_beans, enter=have_beans, outputs=[_save_beans]) Now, when you call: .. code-block:: python coffee_machine.put_in_beans("real good beans") the machine will remember the beans for later. So how do we get the beans back out again? One of our outputs needs to have a return value. It would make sense if our ``brew_button`` method returned the cup of coffee that it made, so we should add an output. So, in addition to heating the heating element, let's add a return value that describes the coffee. First a new output: .. code-block:: python @_machine.output() def _describe_coffee(self): return "A cup of coffee made with {}.".format(self._beans) Note that we don't need to check first whether ``self._beans`` exists or not, because we can only reach this output method if the state machine says we've gone through a set of states that sets this attribute. Now, we need to hook up ``_describe_coffee`` to the process of brewing, so change the brewing transition to: .. code-block:: python have_beans.upon(brew_button, enter=dont_have_beans, outputs=[_heat_the_heating_element, _describe_coffee]) Now, we can call it: .. code-block:: python >>> coffee_machine.brew_button() [None, 'A cup of coffee made with real good beans.'] Except... wait a second, what's that ``None`` doing there? Since every input can produce multiple outputs, in automat, the default return value from every input invocation is a ``list``. In this case, we have both ``_heat_the_heating_element`` and ``_describe_coffee`` outputs, so we're seeing both of their return values. However, this can be customized, with the ``collector`` argument to ``upon``\ ; the ``collector`` is a callable which takes an iterable of all the outputs' return values and "collects" a single return value to return to the caller of the state machine. In this case, we only care about the last output, so we can adjust the call to ``upon`` like this: .. code-block:: python have_beans.upon(brew_button, enter=dont_have_beans, outputs=[_heat_the_heating_element, _describe_coffee], collector=lambda iterable: list(iterable)[-1] ) And now, we'll get just the return value we want: .. code-block:: python >>> coffee_machine.brew_button() 'A cup of coffee made with real good beans.' If I can't get the state of the state machine, how can I save it to (a database, an API response, a file on disk...) -------------------------------------------------------------------------------------------------------------------- There are APIs for serializing the state machine. First, you have to decide on a persistent representation of each state, via the ``serialized=`` argument to the ``MethodicalMachine.state()`` decorator. Let's take this very simple "light switch" state machine, which can be on or off, and flipped to reverse its state: .. code-block:: python class LightSwitch(object): _machine = MethodicalMachine() @_machine.state(serialized="on") def on_state(self): "the switch is on" @_machine.state(serialized="off", initial=True) def off_state(self): "the switch is off" @_machine.input() def flip(self): "flip the switch" on_state.upon(flip, enter=off_state, outputs=[]) off_state.upon(flip, enter=on_state, outputs=[]) In this case, we've chosen a serialized representation for each state via the ``serialized`` argument. The on state is represented by the string ``"on"``\ , and the off state is represented by the string ``"off"``. Now, let's just add an input that lets us tell if the switch is on or not. .. code-block:: python @_machine.input() def query_power(self): "return True if powered, False otherwise" @_machine.output() def _is_powered(self): return True @_machine.output() def _not_powered(self): return False on_state.upon(query_power, enter=on_state, outputs=[_is_powered], collector=next) off_state.upon(query_power, enter=off_state, outputs=[_not_powered], collector=next) To save the state, we have the ``MethodicalMachine.serializer()`` method. A method decorated with ``@serializer()`` gets an extra argument injected at the beginning of its argument list: the serialized identifier for the state. In this case, either ``"on"`` or ``"off"``. Since state machine output methods can also affect other state on the object, a serializer method is expected to return *all* relevant state for serialization. For our simple light switch, such a method might look like this: .. code-block:: python @_machine.serializer() def save(self, state): return {"is-it-on": state} Serializers can be public methods, and they can return whatever you like. If necessary, you can have different serializers - just multiple methods decorated with ``@_machine.serializer()`` - for different formats; return one data-structure for JSON, one for XML, one for a database row, and so on. When it comes time to unserialize, though, you generally want a private method, because an unserializer has to take a not-fully-initialized instance and populate it with state. It is expected to *return* the serialized machine state token that was passed to the serializer, but it can take whatever arguments you like. Of course, in order to return that, it probably has to take it somewhere in its arguments, so it will generally take whatever a paired serializer has returned as an argument. So our unserializer would look like this: .. code-block:: python @_machine.unserializer() def _restore(self, blob): return blob["is-it-on"] Generally you will want a classmethod deserialization constructor which you write yourself to call this, so that you know how to create an instance of your own object, like so: .. code-block:: python @classmethod def from_blob(cls, blob): self = cls() self._restore(blob) return self Saving and loading our ``LightSwitch`` along with its state-machine state can now be accomplished as follows: .. code-block:: python >>> switch1 = LightSwitch() >>> switch1.query_power() False >>> switch1.flip() [] >>> switch1.query_power() True >>> blob = switch1.save() >>> switch2 = LightSwitch.from_blob(blob) >>> switch2.query_power() True More comprehensive (tested, working) examples are present in ``docs/examples``. Go forth and machine all the state! ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/Automat-0.8.0.dist-info/RECORD ================================================ ../../../bin/automat-visualize,sha256=VjaldkbEc5rfj7J6UEu5q63H4NX3pe_kve9ePk9txE0,283 Automat-0.8.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 Automat-0.8.0.dist-info/LICENSE,sha256=siATAWeNCpN9k4VDgnyhNgcS6zTiPejuPzv_-9TA43Y,1053 Automat-0.8.0.dist-info/METADATA,sha256=IMGy5LioGR1j8VhvNYvnWPCGalDNx0WlqYU0ShTjOMc,17919 Automat-0.8.0.dist-info/RECORD,, Automat-0.8.0.dist-info/WHEEL,sha256=8zNYZbwQSXoB9IfXOjPfeNwvAsALAjffgk27FqvCWbo,110 Automat-0.8.0.dist-info/entry_points.txt,sha256=i4tDM5qwy3v1KIN7ETS2XRVcHkThhkq7ZFTPuyP6BpA,63 Automat-0.8.0.dist-info/top_level.txt,sha256=vg4zAOyhP_3YCmpKZLNgFw1uMF3lC_b6TKsdz7jBSpI,8 automat/__init__.py,sha256=ec8PILBwt35xyzsstU9kx8p5ADi6KX9d1rBLZsocN_Y,169 automat/__pycache__/__init__.cpython-36.pyc,, automat/__pycache__/_core.cpython-36.pyc,, automat/__pycache__/_discover.cpython-36.pyc,, automat/__pycache__/_introspection.cpython-36.pyc,, automat/__pycache__/_methodical.cpython-36.pyc,, automat/__pycache__/_visualize.cpython-36.pyc,, automat/_core.py,sha256=IEtZHq3wsBZPX_VfMHMFy_uNjx1kfE11Qq-nmIXZe28,4819 automat/_discover.py,sha256=ye7NHLZkrwYsPmBpTIyJuJ-VRCmwkOUpA0is-A81z04,4367 automat/_introspection.py,sha256=i5UEGdj8lp2BnHnGeAyIwEyoN2gU1nXYg-ZPNX7oBbM,1274 automat/_methodical.py,sha256=AEWagTYaAF8PCXsYoQRYeRn07Jg5fdKDFuAlPvGYHUM,15932 automat/_test/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 automat/_test/__pycache__/__init__.cpython-36.pyc,, automat/_test/__pycache__/test_core.cpython-36.pyc,, automat/_test/__pycache__/test_discover.cpython-36.pyc,, automat/_test/__pycache__/test_methodical.cpython-36.pyc,, automat/_test/__pycache__/test_trace.cpython-36.pyc,, automat/_test/__pycache__/test_visualize.cpython-36.pyc,, automat/_test/test_core.py,sha256=CDmGBQNi9Pr7ZktfBcOhBvwI7wjLLYRtWZ0P5baXONY,2833 automat/_test/test_discover.py,sha256=O9ndAdRAC8uO0uDhioz3e45EsJCF19jQZESj0RBC7ZM,21846 automat/_test/test_methodical.py,sha256=t1CAKtT1fs-FoKMQxXl4ky6_6pgpG7lGDbyQrb_vIeo,18856 automat/_test/test_trace.py,sha256=Mx1B8QgaE7QFk6blTie2j-Vx95hTV-zySnlxLalt8ek,3279 automat/_test/test_visualize.py,sha256=8ErNYxovTiDyZkYkoP1BcyEazU_s0YQ3NHdfH9OihAg,13744 automat/_visualize.py,sha256=jY8HkzaGdMoXB7LavvaneW4GdtBN6PRShl7-4OXDvss,6335 ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/Automat-0.8.0.dist-info/WHEEL ================================================ Wheel-Version: 1.0 Generator: bdist_wheel (0.33.6) Root-Is-Purelib: true Tag: py2-none-any Tag: py3-none-any ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/Automat-0.8.0.dist-info/entry_points.txt ================================================ [console_scripts] automat-visualize = automat._visualize:tool ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/Automat-0.8.0.dist-info/top_level.txt ================================================ automat ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/OpenSSL/SSL.py ================================================ import os import socket from sys import platform from functools import wraps, partial from itertools import count, chain from weakref import WeakValueDictionary from errno import errorcode from cryptography.utils import deprecated from six import ( binary_type as _binary_type, integer_types as integer_types, int2byte, indexbytes) from OpenSSL._util import ( UNSPECIFIED as _UNSPECIFIED, exception_from_error_queue as _exception_from_error_queue, ffi as _ffi, lib as _lib, make_assert as _make_assert, native as _native, path_string as _path_string, text_to_bytes_and_warn as _text_to_bytes_and_warn, no_zero_allocator as _no_zero_allocator, ) from OpenSSL.crypto import ( FILETYPE_PEM, _PassphraseHelper, PKey, X509Name, X509, X509Store) __all__ = [ 'OPENSSL_VERSION_NUMBER', 'SSLEAY_VERSION', 'SSLEAY_CFLAGS', 'SSLEAY_PLATFORM', 'SSLEAY_DIR', 'SSLEAY_BUILT_ON', 'SENT_SHUTDOWN', 'RECEIVED_SHUTDOWN', 'SSLv2_METHOD', 'SSLv3_METHOD', 'SSLv23_METHOD', 'TLSv1_METHOD', 'TLSv1_1_METHOD', 'TLSv1_2_METHOD', 'OP_NO_SSLv2', 'OP_NO_SSLv3', 'OP_NO_TLSv1', 'OP_NO_TLSv1_1', 'OP_NO_TLSv1_2', 'MODE_RELEASE_BUFFERS', 'OP_SINGLE_DH_USE', 'OP_SINGLE_ECDH_USE', 'OP_EPHEMERAL_RSA', 'OP_MICROSOFT_SESS_ID_BUG', 'OP_NETSCAPE_CHALLENGE_BUG', 'OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG', 'OP_SSLREF2_REUSE_CERT_TYPE_BUG', 'OP_MICROSOFT_BIG_SSLV3_BUFFER', 'OP_MSIE_SSLV2_RSA_PADDING', 'OP_SSLEAY_080_CLIENT_DH_BUG', 'OP_TLS_D5_BUG', 'OP_TLS_BLOCK_PADDING_BUG', 'OP_DONT_INSERT_EMPTY_FRAGMENTS', 'OP_CIPHER_SERVER_PREFERENCE', 'OP_TLS_ROLLBACK_BUG', 'OP_PKCS1_CHECK_1', 'OP_PKCS1_CHECK_2', 'OP_NETSCAPE_CA_DN_BUG', 'OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG', 'OP_NO_COMPRESSION', 'OP_NO_QUERY_MTU', 'OP_COOKIE_EXCHANGE', 'OP_NO_TICKET', 'OP_ALL', 'VERIFY_PEER', 'VERIFY_FAIL_IF_NO_PEER_CERT', 'VERIFY_CLIENT_ONCE', 'VERIFY_NONE', 'SESS_CACHE_OFF', 'SESS_CACHE_CLIENT', 'SESS_CACHE_SERVER', 'SESS_CACHE_BOTH', 'SESS_CACHE_NO_AUTO_CLEAR', 'SESS_CACHE_NO_INTERNAL_LOOKUP', 'SESS_CACHE_NO_INTERNAL_STORE', 'SESS_CACHE_NO_INTERNAL', 'SSL_ST_CONNECT', 'SSL_ST_ACCEPT', 'SSL_ST_MASK', 'SSL_CB_LOOP', 'SSL_CB_EXIT', 'SSL_CB_READ', 'SSL_CB_WRITE', 'SSL_CB_ALERT', 'SSL_CB_READ_ALERT', 'SSL_CB_WRITE_ALERT', 'SSL_CB_ACCEPT_LOOP', 'SSL_CB_ACCEPT_EXIT', 'SSL_CB_CONNECT_LOOP', 'SSL_CB_CONNECT_EXIT', 'SSL_CB_HANDSHAKE_START', 'SSL_CB_HANDSHAKE_DONE', 'Error', 'WantReadError', 'WantWriteError', 'WantX509LookupError', 'ZeroReturnError', 'SysCallError', 'SSLeay_version', 'Session', 'Context', 'Connection' ] try: _buffer = buffer except NameError: class _buffer(object): pass OPENSSL_VERSION_NUMBER = _lib.OPENSSL_VERSION_NUMBER SSLEAY_VERSION = _lib.SSLEAY_VERSION SSLEAY_CFLAGS = _lib.SSLEAY_CFLAGS SSLEAY_PLATFORM = _lib.SSLEAY_PLATFORM SSLEAY_DIR = _lib.SSLEAY_DIR SSLEAY_BUILT_ON = _lib.SSLEAY_BUILT_ON SENT_SHUTDOWN = _lib.SSL_SENT_SHUTDOWN RECEIVED_SHUTDOWN = _lib.SSL_RECEIVED_SHUTDOWN SSLv2_METHOD = 1 SSLv3_METHOD = 2 SSLv23_METHOD = 3 TLSv1_METHOD = 4 TLSv1_1_METHOD = 5 TLSv1_2_METHOD = 6 OP_NO_SSLv2 = _lib.SSL_OP_NO_SSLv2 OP_NO_SSLv3 = _lib.SSL_OP_NO_SSLv3 OP_NO_TLSv1 = _lib.SSL_OP_NO_TLSv1 OP_NO_TLSv1_1 = _lib.SSL_OP_NO_TLSv1_1 OP_NO_TLSv1_2 = _lib.SSL_OP_NO_TLSv1_2 MODE_RELEASE_BUFFERS = _lib.SSL_MODE_RELEASE_BUFFERS OP_SINGLE_DH_USE = _lib.SSL_OP_SINGLE_DH_USE OP_SINGLE_ECDH_USE = _lib.SSL_OP_SINGLE_ECDH_USE OP_EPHEMERAL_RSA = _lib.SSL_OP_EPHEMERAL_RSA OP_MICROSOFT_SESS_ID_BUG = _lib.SSL_OP_MICROSOFT_SESS_ID_BUG OP_NETSCAPE_CHALLENGE_BUG = _lib.SSL_OP_NETSCAPE_CHALLENGE_BUG OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG = ( _lib.SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG ) OP_SSLREF2_REUSE_CERT_TYPE_BUG = _lib.SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG OP_MICROSOFT_BIG_SSLV3_BUFFER = _lib.SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER OP_MSIE_SSLV2_RSA_PADDING = _lib.SSL_OP_MSIE_SSLV2_RSA_PADDING OP_SSLEAY_080_CLIENT_DH_BUG = _lib.SSL_OP_SSLEAY_080_CLIENT_DH_BUG OP_TLS_D5_BUG = _lib.SSL_OP_TLS_D5_BUG OP_TLS_BLOCK_PADDING_BUG = _lib.SSL_OP_TLS_BLOCK_PADDING_BUG OP_DONT_INSERT_EMPTY_FRAGMENTS = _lib.SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS OP_CIPHER_SERVER_PREFERENCE = _lib.SSL_OP_CIPHER_SERVER_PREFERENCE OP_TLS_ROLLBACK_BUG = _lib.SSL_OP_TLS_ROLLBACK_BUG OP_PKCS1_CHECK_1 = _lib.SSL_OP_PKCS1_CHECK_1 OP_PKCS1_CHECK_2 = _lib.SSL_OP_PKCS1_CHECK_2 OP_NETSCAPE_CA_DN_BUG = _lib.SSL_OP_NETSCAPE_CA_DN_BUG OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG = ( _lib.SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG ) OP_NO_COMPRESSION = _lib.SSL_OP_NO_COMPRESSION OP_NO_QUERY_MTU = _lib.SSL_OP_NO_QUERY_MTU OP_COOKIE_EXCHANGE = _lib.SSL_OP_COOKIE_EXCHANGE OP_NO_TICKET = _lib.SSL_OP_NO_TICKET OP_ALL = _lib.SSL_OP_ALL VERIFY_PEER = _lib.SSL_VERIFY_PEER VERIFY_FAIL_IF_NO_PEER_CERT = _lib.SSL_VERIFY_FAIL_IF_NO_PEER_CERT VERIFY_CLIENT_ONCE = _lib.SSL_VERIFY_CLIENT_ONCE VERIFY_NONE = _lib.SSL_VERIFY_NONE SESS_CACHE_OFF = _lib.SSL_SESS_CACHE_OFF SESS_CACHE_CLIENT = _lib.SSL_SESS_CACHE_CLIENT SESS_CACHE_SERVER = _lib.SSL_SESS_CACHE_SERVER SESS_CACHE_BOTH = _lib.SSL_SESS_CACHE_BOTH SESS_CACHE_NO_AUTO_CLEAR = _lib.SSL_SESS_CACHE_NO_AUTO_CLEAR SESS_CACHE_NO_INTERNAL_LOOKUP = _lib.SSL_SESS_CACHE_NO_INTERNAL_LOOKUP SESS_CACHE_NO_INTERNAL_STORE = _lib.SSL_SESS_CACHE_NO_INTERNAL_STORE SESS_CACHE_NO_INTERNAL = _lib.SSL_SESS_CACHE_NO_INTERNAL SSL_ST_CONNECT = _lib.SSL_ST_CONNECT SSL_ST_ACCEPT = _lib.SSL_ST_ACCEPT SSL_ST_MASK = _lib.SSL_ST_MASK if _lib.Cryptography_HAS_SSL_ST: SSL_ST_INIT = _lib.SSL_ST_INIT SSL_ST_BEFORE = _lib.SSL_ST_BEFORE SSL_ST_OK = _lib.SSL_ST_OK SSL_ST_RENEGOTIATE = _lib.SSL_ST_RENEGOTIATE __all__.extend([ 'SSL_ST_INIT', 'SSL_ST_BEFORE', 'SSL_ST_OK', 'SSL_ST_RENEGOTIATE', ]) SSL_CB_LOOP = _lib.SSL_CB_LOOP SSL_CB_EXIT = _lib.SSL_CB_EXIT SSL_CB_READ = _lib.SSL_CB_READ SSL_CB_WRITE = _lib.SSL_CB_WRITE SSL_CB_ALERT = _lib.SSL_CB_ALERT SSL_CB_READ_ALERT = _lib.SSL_CB_READ_ALERT SSL_CB_WRITE_ALERT = _lib.SSL_CB_WRITE_ALERT SSL_CB_ACCEPT_LOOP = _lib.SSL_CB_ACCEPT_LOOP SSL_CB_ACCEPT_EXIT = _lib.SSL_CB_ACCEPT_EXIT SSL_CB_CONNECT_LOOP = _lib.SSL_CB_CONNECT_LOOP SSL_CB_CONNECT_EXIT = _lib.SSL_CB_CONNECT_EXIT SSL_CB_HANDSHAKE_START = _lib.SSL_CB_HANDSHAKE_START SSL_CB_HANDSHAKE_DONE = _lib.SSL_CB_HANDSHAKE_DONE # Taken from https://golang.org/src/crypto/x509/root_linux.go _CERTIFICATE_FILE_LOCATIONS = [ "/etc/ssl/certs/ca-certificates.crt", # Debian/Ubuntu/Gentoo etc. "/etc/pki/tls/certs/ca-bundle.crt", # Fedora/RHEL 6 "/etc/ssl/ca-bundle.pem", # OpenSUSE "/etc/pki/tls/cacert.pem", # OpenELEC "/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem", # CentOS/RHEL 7 ] _CERTIFICATE_PATH_LOCATIONS = [ "/etc/ssl/certs", # SLES10/SLES11 ] # These values are compared to output from cffi's ffi.string so they must be # byte strings. _CRYPTOGRAPHY_MANYLINUX1_CA_DIR = b"/opt/pyca/cryptography/openssl/certs" _CRYPTOGRAPHY_MANYLINUX1_CA_FILE = b"/opt/pyca/cryptography/openssl/cert.pem" class Error(Exception): """ An error occurred in an `OpenSSL.SSL` API. """ _raise_current_error = partial(_exception_from_error_queue, Error) _openssl_assert = _make_assert(Error) class WantReadError(Error): pass class WantWriteError(Error): pass class WantX509LookupError(Error): pass class ZeroReturnError(Error): pass class SysCallError(Error): pass class _CallbackExceptionHelper(object): """ A base class for wrapper classes that allow for intelligent exception handling in OpenSSL callbacks. :ivar list _problems: Any exceptions that occurred while executing in a context where they could not be raised in the normal way. Typically this is because OpenSSL has called into some Python code and requires a return value. The exceptions are saved to be raised later when it is possible to do so. """ def __init__(self): self._problems = [] def raise_if_problem(self): """ Raise an exception from the OpenSSL error queue or that was previously captured whe running a callback. """ if self._problems: try: _raise_current_error() except Error: pass raise self._problems.pop(0) class _VerifyHelper(_CallbackExceptionHelper): """ Wrap a callback such that it can be used as a certificate verification callback. """ def __init__(self, callback): _CallbackExceptionHelper.__init__(self) @wraps(callback) def wrapper(ok, store_ctx): x509 = _lib.X509_STORE_CTX_get_current_cert(store_ctx) _lib.X509_up_ref(x509) cert = X509._from_raw_x509_ptr(x509) error_number = _lib.X509_STORE_CTX_get_error(store_ctx) error_depth = _lib.X509_STORE_CTX_get_error_depth(store_ctx) index = _lib.SSL_get_ex_data_X509_STORE_CTX_idx() ssl = _lib.X509_STORE_CTX_get_ex_data(store_ctx, index) connection = Connection._reverse_mapping[ssl] try: result = callback( connection, cert, error_number, error_depth, ok ) except Exception as e: self._problems.append(e) return 0 else: if result: _lib.X509_STORE_CTX_set_error(store_ctx, _lib.X509_V_OK) return 1 else: return 0 self.callback = _ffi.callback( "int (*)(int, X509_STORE_CTX *)", wrapper) class _NpnAdvertiseHelper(_CallbackExceptionHelper): """ Wrap a callback such that it can be used as an NPN advertisement callback. """ def __init__(self, callback): _CallbackExceptionHelper.__init__(self) @wraps(callback) def wrapper(ssl, out, outlen, arg): try: conn = Connection._reverse_mapping[ssl] protos = callback(conn) # Join the protocols into a Python bytestring, length-prefixing # each element. protostr = b''.join( chain.from_iterable((int2byte(len(p)), p) for p in protos) ) # Save our callback arguments on the connection object. This is # done to make sure that they don't get freed before OpenSSL # uses them. Then, return them appropriately in the output # parameters. conn._npn_advertise_callback_args = [ _ffi.new("unsigned int *", len(protostr)), _ffi.new("unsigned char[]", protostr), ] outlen[0] = conn._npn_advertise_callback_args[0][0] out[0] = conn._npn_advertise_callback_args[1] return 0 except Exception as e: self._problems.append(e) return 2 # SSL_TLSEXT_ERR_ALERT_FATAL self.callback = _ffi.callback( "int (*)(SSL *, const unsigned char **, unsigned int *, void *)", wrapper ) class _NpnSelectHelper(_CallbackExceptionHelper): """ Wrap a callback such that it can be used as an NPN selection callback. """ def __init__(self, callback): _CallbackExceptionHelper.__init__(self) @wraps(callback) def wrapper(ssl, out, outlen, in_, inlen, arg): try: conn = Connection._reverse_mapping[ssl] # The string passed to us is actually made up of multiple # length-prefixed bytestrings. We need to split that into a # list. instr = _ffi.buffer(in_, inlen)[:] protolist = [] while instr: length = indexbytes(instr, 0) proto = instr[1:length + 1] protolist.append(proto) instr = instr[length + 1:] # Call the callback outstr = callback(conn, protolist) # Save our callback arguments on the connection object. This is # done to make sure that they don't get freed before OpenSSL # uses them. Then, return them appropriately in the output # parameters. conn._npn_select_callback_args = [ _ffi.new("unsigned char *", len(outstr)), _ffi.new("unsigned char[]", outstr), ] outlen[0] = conn._npn_select_callback_args[0][0] out[0] = conn._npn_select_callback_args[1] return 0 except Exception as e: self._problems.append(e) return 2 # SSL_TLSEXT_ERR_ALERT_FATAL self.callback = _ffi.callback( ("int (*)(SSL *, unsigned char **, unsigned char *, " "const unsigned char *, unsigned int, void *)"), wrapper ) class _ALPNSelectHelper(_CallbackExceptionHelper): """ Wrap a callback such that it can be used as an ALPN selection callback. """ def __init__(self, callback): _CallbackExceptionHelper.__init__(self) @wraps(callback) def wrapper(ssl, out, outlen, in_, inlen, arg): try: conn = Connection._reverse_mapping[ssl] # The string passed to us is made up of multiple # length-prefixed bytestrings. We need to split that into a # list. instr = _ffi.buffer(in_, inlen)[:] protolist = [] while instr: encoded_len = indexbytes(instr, 0) proto = instr[1:encoded_len + 1] protolist.append(proto) instr = instr[encoded_len + 1:] # Call the callback outstr = callback(conn, protolist) if not isinstance(outstr, _binary_type): raise TypeError("ALPN callback must return a bytestring.") # Save our callback arguments on the connection object to make # sure that they don't get freed before OpenSSL can use them. # Then, return them in the appropriate output parameters. conn._alpn_select_callback_args = [ _ffi.new("unsigned char *", len(outstr)), _ffi.new("unsigned char[]", outstr), ] outlen[0] = conn._alpn_select_callback_args[0][0] out[0] = conn._alpn_select_callback_args[1] return 0 except Exception as e: self._problems.append(e) return 2 # SSL_TLSEXT_ERR_ALERT_FATAL self.callback = _ffi.callback( ("int (*)(SSL *, unsigned char **, unsigned char *, " "const unsigned char *, unsigned int, void *)"), wrapper ) class _OCSPServerCallbackHelper(_CallbackExceptionHelper): """ Wrap a callback such that it can be used as an OCSP callback for the server side. Annoyingly, OpenSSL defines one OCSP callback but uses it in two different ways. For servers, that callback is expected to retrieve some OCSP data and hand it to OpenSSL, and may return only SSL_TLSEXT_ERR_OK, SSL_TLSEXT_ERR_FATAL, and SSL_TLSEXT_ERR_NOACK. For clients, that callback is expected to check the OCSP data, and returns a negative value on error, 0 if the response is not acceptable, or positive if it is. These are mutually exclusive return code behaviours, and they mean that we need two helpers so that we always return an appropriate error code if the user's code throws an exception. Given that we have to have two helpers anyway, these helpers are a bit more helpery than most: specifically, they hide a few more of the OpenSSL functions so that the user has an easier time writing these callbacks. This helper implements the server side. """ def __init__(self, callback): _CallbackExceptionHelper.__init__(self) @wraps(callback) def wrapper(ssl, cdata): try: conn = Connection._reverse_mapping[ssl] # Extract the data if any was provided. if cdata != _ffi.NULL: data = _ffi.from_handle(cdata) else: data = None # Call the callback. ocsp_data = callback(conn, data) if not isinstance(ocsp_data, _binary_type): raise TypeError("OCSP callback must return a bytestring.") # If the OCSP data was provided, we will pass it to OpenSSL. # However, we have an early exit here: if no OCSP data was # provided we will just exit out and tell OpenSSL that there # is nothing to do. if not ocsp_data: return 3 # SSL_TLSEXT_ERR_NOACK # OpenSSL takes ownership of this data and expects it to have # been allocated by OPENSSL_malloc. ocsp_data_length = len(ocsp_data) data_ptr = _lib.OPENSSL_malloc(ocsp_data_length) _ffi.buffer(data_ptr, ocsp_data_length)[:] = ocsp_data _lib.SSL_set_tlsext_status_ocsp_resp( ssl, data_ptr, ocsp_data_length ) return 0 except Exception as e: self._problems.append(e) return 2 # SSL_TLSEXT_ERR_ALERT_FATAL self.callback = _ffi.callback("int (*)(SSL *, void *)", wrapper) class _OCSPClientCallbackHelper(_CallbackExceptionHelper): """ Wrap a callback such that it can be used as an OCSP callback for the client side. Annoyingly, OpenSSL defines one OCSP callback but uses it in two different ways. For servers, that callback is expected to retrieve some OCSP data and hand it to OpenSSL, and may return only SSL_TLSEXT_ERR_OK, SSL_TLSEXT_ERR_FATAL, and SSL_TLSEXT_ERR_NOACK. For clients, that callback is expected to check the OCSP data, and returns a negative value on error, 0 if the response is not acceptable, or positive if it is. These are mutually exclusive return code behaviours, and they mean that we need two helpers so that we always return an appropriate error code if the user's code throws an exception. Given that we have to have two helpers anyway, these helpers are a bit more helpery than most: specifically, they hide a few more of the OpenSSL functions so that the user has an easier time writing these callbacks. This helper implements the client side. """ def __init__(self, callback): _CallbackExceptionHelper.__init__(self) @wraps(callback) def wrapper(ssl, cdata): try: conn = Connection._reverse_mapping[ssl] # Extract the data if any was provided. if cdata != _ffi.NULL: data = _ffi.from_handle(cdata) else: data = None # Get the OCSP data. ocsp_ptr = _ffi.new("unsigned char **") ocsp_len = _lib.SSL_get_tlsext_status_ocsp_resp(ssl, ocsp_ptr) if ocsp_len < 0: # No OCSP data. ocsp_data = b'' else: # Copy the OCSP data, then pass it to the callback. ocsp_data = _ffi.buffer(ocsp_ptr[0], ocsp_len)[:] valid = callback(conn, ocsp_data, data) # Return 1 on success or 0 on error. return int(bool(valid)) except Exception as e: self._problems.append(e) # Return negative value if an exception is hit. return -1 self.callback = _ffi.callback("int (*)(SSL *, void *)", wrapper) def _asFileDescriptor(obj): fd = None if not isinstance(obj, integer_types): meth = getattr(obj, "fileno", None) if meth is not None: obj = meth() if isinstance(obj, integer_types): fd = obj if not isinstance(fd, integer_types): raise TypeError("argument must be an int, or have a fileno() method.") elif fd < 0: raise ValueError( "file descriptor cannot be a negative integer (%i)" % (fd,)) return fd def SSLeay_version(type): """ Return a string describing the version of OpenSSL in use. :param type: One of the :const:`SSLEAY_` constants defined in this module. """ return _ffi.string(_lib.SSLeay_version(type)) def _make_requires(flag, error): """ Builds a decorator that ensures that functions that rely on OpenSSL functions that are not present in this build raise NotImplementedError, rather than AttributeError coming out of cryptography. :param flag: A cryptography flag that guards the functions, e.g. ``Cryptography_HAS_NEXTPROTONEG``. :param error: The string to be used in the exception if the flag is false. """ def _requires_decorator(func): if not flag: @wraps(func) def explode(*args, **kwargs): raise NotImplementedError(error) return explode else: return func return _requires_decorator _requires_npn = _make_requires( _lib.Cryptography_HAS_NEXTPROTONEG, "NPN not available" ) _requires_alpn = _make_requires( _lib.Cryptography_HAS_ALPN, "ALPN not available" ) _requires_sni = _make_requires( _lib.Cryptography_HAS_TLSEXT_HOSTNAME, "SNI not available" ) class Session(object): """ A class representing an SSL session. A session defines certain connection parameters which may be re-used to speed up the setup of subsequent connections. .. versionadded:: 0.14 """ pass class Context(object): """ :class:`OpenSSL.SSL.Context` instances define the parameters for setting up new SSL connections. :param method: One of SSLv2_METHOD, SSLv3_METHOD, SSLv23_METHOD, or TLSv1_METHOD. """ _methods = { SSLv2_METHOD: "SSLv2_method", SSLv3_METHOD: "SSLv3_method", SSLv23_METHOD: "SSLv23_method", TLSv1_METHOD: "TLSv1_method", TLSv1_1_METHOD: "TLSv1_1_method", TLSv1_2_METHOD: "TLSv1_2_method", } _methods = dict( (identifier, getattr(_lib, name)) for (identifier, name) in _methods.items() if getattr(_lib, name, None) is not None) def __init__(self, method): if not isinstance(method, integer_types): raise TypeError("method must be an integer") try: method_func = self._methods[method] except KeyError: raise ValueError("No such protocol") method_obj = method_func() _openssl_assert(method_obj != _ffi.NULL) context = _lib.SSL_CTX_new(method_obj) _openssl_assert(context != _ffi.NULL) context = _ffi.gc(context, _lib.SSL_CTX_free) # If SSL_CTX_set_ecdh_auto is available then set it so the ECDH curve # will be auto-selected. This function was added in 1.0.2 and made a # noop in 1.1.0+ (where it is set automatically). try: res = _lib.SSL_CTX_set_ecdh_auto(context, 1) _openssl_assert(res == 1) except AttributeError: pass self._context = context self._passphrase_helper = None self._passphrase_callback = None self._passphrase_userdata = None self._verify_helper = None self._verify_callback = None self._info_callback = None self._tlsext_servername_callback = None self._app_data = None self._npn_advertise_helper = None self._npn_advertise_callback = None self._npn_select_helper = None self._npn_select_callback = None self._alpn_select_helper = None self._alpn_select_callback = None self._ocsp_helper = None self._ocsp_callback = None self._ocsp_data = None self.set_mode(_lib.SSL_MODE_ENABLE_PARTIAL_WRITE) def load_verify_locations(self, cafile, capath=None): """ Let SSL know where we can find trusted certificates for the certificate chain. Note that the certificates have to be in PEM format. If capath is passed, it must be a directory prepared using the ``c_rehash`` tool included with OpenSSL. Either, but not both, of *pemfile* or *capath* may be :data:`None`. :param cafile: In which file we can find the certificates (``bytes`` or ``unicode``). :param capath: In which directory we can find the certificates (``bytes`` or ``unicode``). :return: None """ if cafile is None: cafile = _ffi.NULL else: cafile = _path_string(cafile) if capath is None: capath = _ffi.NULL else: capath = _path_string(capath) load_result = _lib.SSL_CTX_load_verify_locations( self._context, cafile, capath ) if not load_result: _raise_current_error() def _wrap_callback(self, callback): @wraps(callback) def wrapper(size, verify, userdata): return callback(size, verify, self._passphrase_userdata) return _PassphraseHelper( FILETYPE_PEM, wrapper, more_args=True, truncate=True) def set_passwd_cb(self, callback, userdata=None): """ Set the passphrase callback. This function will be called when a private key with a passphrase is loaded. :param callback: The Python callback to use. This must accept three positional arguments. First, an integer giving the maximum length of the passphrase it may return. If the returned passphrase is longer than this, it will be truncated. Second, a boolean value which will be true if the user should be prompted for the passphrase twice and the callback should verify that the two values supplied are equal. Third, the value given as the *userdata* parameter to :meth:`set_passwd_cb`. The *callback* must return a byte string. If an error occurs, *callback* should return a false value (e.g. an empty string). :param userdata: (optional) A Python object which will be given as argument to the callback :return: None """ if not callable(callback): raise TypeError("callback must be callable") self._passphrase_helper = self._wrap_callback(callback) self._passphrase_callback = self._passphrase_helper.callback _lib.SSL_CTX_set_default_passwd_cb( self._context, self._passphrase_callback) self._passphrase_userdata = userdata def set_default_verify_paths(self): """ Specify that the platform provided CA certificates are to be used for verification purposes. This method has some caveats related to the binary wheels that cryptography (pyOpenSSL's primary dependency) ships: * macOS will only load certificates using this method if the user has the ``openssl@1.1`` `Homebrew `_ formula installed in the default location. * Windows will not work. * manylinux1 cryptography wheels will work on most common Linux distributions in pyOpenSSL 17.1.0 and above. pyOpenSSL detects the manylinux1 wheel and attempts to load roots via a fallback path. :return: None """ # SSL_CTX_set_default_verify_paths will attempt to load certs from # both a cafile and capath that are set at compile time. However, # it will first check environment variables and, if present, load # those paths instead set_result = _lib.SSL_CTX_set_default_verify_paths(self._context) _openssl_assert(set_result == 1) # After attempting to set default_verify_paths we need to know whether # to go down the fallback path. # First we'll check to see if any env vars have been set. If so, # we won't try to do anything else because the user has set the path # themselves. dir_env_var = _ffi.string( _lib.X509_get_default_cert_dir_env() ).decode("ascii") file_env_var = _ffi.string( _lib.X509_get_default_cert_file_env() ).decode("ascii") if not self._check_env_vars_set(dir_env_var, file_env_var): default_dir = _ffi.string(_lib.X509_get_default_cert_dir()) default_file = _ffi.string(_lib.X509_get_default_cert_file()) # Now we check to see if the default_dir and default_file are set # to the exact values we use in our manylinux1 builds. If they are # then we know to load the fallbacks if ( default_dir == _CRYPTOGRAPHY_MANYLINUX1_CA_DIR and default_file == _CRYPTOGRAPHY_MANYLINUX1_CA_FILE ): # This is manylinux1, let's load our fallback paths self._fallback_default_verify_paths( _CERTIFICATE_FILE_LOCATIONS, _CERTIFICATE_PATH_LOCATIONS ) def _check_env_vars_set(self, dir_env_var, file_env_var): """ Check to see if the default cert dir/file environment vars are present. :return: bool """ return ( os.environ.get(file_env_var) is not None or os.environ.get(dir_env_var) is not None ) def _fallback_default_verify_paths(self, file_path, dir_path): """ Default verify paths are based on the compiled version of OpenSSL. However, when pyca/cryptography is compiled as a manylinux1 wheel that compiled location can potentially be wrong. So, like Go, we will try a predefined set of paths and attempt to load roots from there. :return: None """ for cafile in file_path: if os.path.isfile(cafile): self.load_verify_locations(cafile) break for capath in dir_path: if os.path.isdir(capath): self.load_verify_locations(None, capath) break def use_certificate_chain_file(self, certfile): """ Load a certificate chain from a file. :param certfile: The name of the certificate chain file (``bytes`` or ``unicode``). Must be PEM encoded. :return: None """ certfile = _path_string(certfile) result = _lib.SSL_CTX_use_certificate_chain_file( self._context, certfile ) if not result: _raise_current_error() def use_certificate_file(self, certfile, filetype=FILETYPE_PEM): """ Load a certificate from a file :param certfile: The name of the certificate file (``bytes`` or ``unicode``). :param filetype: (optional) The encoding of the file, which is either :const:`FILETYPE_PEM` or :const:`FILETYPE_ASN1`. The default is :const:`FILETYPE_PEM`. :return: None """ certfile = _path_string(certfile) if not isinstance(filetype, integer_types): raise TypeError("filetype must be an integer") use_result = _lib.SSL_CTX_use_certificate_file( self._context, certfile, filetype ) if not use_result: _raise_current_error() def use_certificate(self, cert): """ Load a certificate from a X509 object :param cert: The X509 object :return: None """ if not isinstance(cert, X509): raise TypeError("cert must be an X509 instance") use_result = _lib.SSL_CTX_use_certificate(self._context, cert._x509) if not use_result: _raise_current_error() def add_extra_chain_cert(self, certobj): """ Add certificate to chain :param certobj: The X509 certificate object to add to the chain :return: None """ if not isinstance(certobj, X509): raise TypeError("certobj must be an X509 instance") copy = _lib.X509_dup(certobj._x509) add_result = _lib.SSL_CTX_add_extra_chain_cert(self._context, copy) if not add_result: # TODO: This is untested. _lib.X509_free(copy) _raise_current_error() def _raise_passphrase_exception(self): if self._passphrase_helper is not None: self._passphrase_helper.raise_if_problem(Error) _raise_current_error() def use_privatekey_file(self, keyfile, filetype=_UNSPECIFIED): """ Load a private key from a file :param keyfile: The name of the key file (``bytes`` or ``unicode``) :param filetype: (optional) The encoding of the file, which is either :const:`FILETYPE_PEM` or :const:`FILETYPE_ASN1`. The default is :const:`FILETYPE_PEM`. :return: None """ keyfile = _path_string(keyfile) if filetype is _UNSPECIFIED: filetype = FILETYPE_PEM elif not isinstance(filetype, integer_types): raise TypeError("filetype must be an integer") use_result = _lib.SSL_CTX_use_PrivateKey_file( self._context, keyfile, filetype) if not use_result: self._raise_passphrase_exception() def use_privatekey(self, pkey): """ Load a private key from a PKey object :param pkey: The PKey object :return: None """ if not isinstance(pkey, PKey): raise TypeError("pkey must be a PKey instance") use_result = _lib.SSL_CTX_use_PrivateKey(self._context, pkey._pkey) if not use_result: self._raise_passphrase_exception() def check_privatekey(self): """ Check if the private key (loaded with :meth:`use_privatekey`) matches the certificate (loaded with :meth:`use_certificate`) :return: :data:`None` (raises :exc:`Error` if something's wrong) """ if not _lib.SSL_CTX_check_private_key(self._context): _raise_current_error() def load_client_ca(self, cafile): """ Load the trusted certificates that will be sent to the client. Does not actually imply any of the certificates are trusted; that must be configured separately. :param bytes cafile: The path to a certificates file in PEM format. :return: None """ ca_list = _lib.SSL_load_client_CA_file( _text_to_bytes_and_warn("cafile", cafile) ) _openssl_assert(ca_list != _ffi.NULL) _lib.SSL_CTX_set_client_CA_list(self._context, ca_list) def set_session_id(self, buf): """ Set the session id to *buf* within which a session can be reused for this Context object. This is needed when doing session resumption, because there is no way for a stored session to know which Context object it is associated with. :param bytes buf: The session id. :returns: None """ buf = _text_to_bytes_and_warn("buf", buf) _openssl_assert( _lib.SSL_CTX_set_session_id_context( self._context, buf, len(buf), ) == 1 ) def set_session_cache_mode(self, mode): """ Set the behavior of the session cache used by all connections using this Context. The previously set mode is returned. See :const:`SESS_CACHE_*` for details about particular modes. :param mode: One or more of the SESS_CACHE_* flags (combine using bitwise or) :returns: The previously set caching mode. .. versionadded:: 0.14 """ if not isinstance(mode, integer_types): raise TypeError("mode must be an integer") return _lib.SSL_CTX_set_session_cache_mode(self._context, mode) def get_session_cache_mode(self): """ Get the current session cache mode. :returns: The currently used cache mode. .. versionadded:: 0.14 """ return _lib.SSL_CTX_get_session_cache_mode(self._context) def set_verify(self, mode, callback): """ et the verification flags for this Context object to *mode* and specify that *callback* should be used for verification callbacks. :param mode: The verify mode, this should be one of :const:`VERIFY_NONE` and :const:`VERIFY_PEER`. If :const:`VERIFY_PEER` is used, *mode* can be OR:ed with :const:`VERIFY_FAIL_IF_NO_PEER_CERT` and :const:`VERIFY_CLIENT_ONCE` to further control the behaviour. :param callback: The Python callback to use. This should take five arguments: A Connection object, an X509 object, and three integer variables, which are in turn potential error number, error depth and return code. *callback* should return True if verification passes and False otherwise. :return: None See SSL_CTX_set_verify(3SSL) for further details. """ if not isinstance(mode, integer_types): raise TypeError("mode must be an integer") if not callable(callback): raise TypeError("callback must be callable") self._verify_helper = _VerifyHelper(callback) self._verify_callback = self._verify_helper.callback _lib.SSL_CTX_set_verify(self._context, mode, self._verify_callback) def set_verify_depth(self, depth): """ Set the maximum depth for the certificate chain verification that shall be allowed for this Context object. :param depth: An integer specifying the verify depth :return: None """ if not isinstance(depth, integer_types): raise TypeError("depth must be an integer") _lib.SSL_CTX_set_verify_depth(self._context, depth) def get_verify_mode(self): """ Retrieve the Context object's verify mode, as set by :meth:`set_verify`. :return: The verify mode """ return _lib.SSL_CTX_get_verify_mode(self._context) def get_verify_depth(self): """ Retrieve the Context object's verify depth, as set by :meth:`set_verify_depth`. :return: The verify depth """ return _lib.SSL_CTX_get_verify_depth(self._context) def load_tmp_dh(self, dhfile): """ Load parameters for Ephemeral Diffie-Hellman :param dhfile: The file to load EDH parameters from (``bytes`` or ``unicode``). :return: None """ dhfile = _path_string(dhfile) bio = _lib.BIO_new_file(dhfile, b"r") if bio == _ffi.NULL: _raise_current_error() bio = _ffi.gc(bio, _lib.BIO_free) dh = _lib.PEM_read_bio_DHparams(bio, _ffi.NULL, _ffi.NULL, _ffi.NULL) dh = _ffi.gc(dh, _lib.DH_free) _lib.SSL_CTX_set_tmp_dh(self._context, dh) def set_tmp_ecdh(self, curve): """ Select a curve to use for ECDHE key exchange. :param curve: A curve object to use as returned by either :meth:`OpenSSL.crypto.get_elliptic_curve` or :meth:`OpenSSL.crypto.get_elliptic_curves`. :return: None """ _lib.SSL_CTX_set_tmp_ecdh(self._context, curve._to_EC_KEY()) def set_cipher_list(self, cipher_list): """ Set the list of ciphers to be used in this context. See the OpenSSL manual for more information (e.g. :manpage:`ciphers(1)`). :param bytes cipher_list: An OpenSSL cipher string. :return: None """ cipher_list = _text_to_bytes_and_warn("cipher_list", cipher_list) if not isinstance(cipher_list, bytes): raise TypeError("cipher_list must be a byte string.") _openssl_assert( _lib.SSL_CTX_set_cipher_list(self._context, cipher_list) == 1 ) # In OpenSSL 1.1.1 setting the cipher list will always return TLS 1.3 # ciphers even if you pass an invalid cipher. Applications (like # Twisted) have tests that depend on an error being raised if an # invalid cipher string is passed, but without the following check # for the TLS 1.3 specific cipher suites it would never error. tmpconn = Connection(self, None) _openssl_assert( tmpconn.get_cipher_list() != [ 'TLS_AES_256_GCM_SHA384', 'TLS_CHACHA20_POLY1305_SHA256', 'TLS_AES_128_GCM_SHA256' ] ) def set_client_ca_list(self, certificate_authorities): """ Set the list of preferred client certificate signers for this server context. This list of certificate authorities will be sent to the client when the server requests a client certificate. :param certificate_authorities: a sequence of X509Names. :return: None .. versionadded:: 0.10 """ name_stack = _lib.sk_X509_NAME_new_null() _openssl_assert(name_stack != _ffi.NULL) try: for ca_name in certificate_authorities: if not isinstance(ca_name, X509Name): raise TypeError( "client CAs must be X509Name objects, not %s " "objects" % ( type(ca_name).__name__, ) ) copy = _lib.X509_NAME_dup(ca_name._name) _openssl_assert(copy != _ffi.NULL) push_result = _lib.sk_X509_NAME_push(name_stack, copy) if not push_result: _lib.X509_NAME_free(copy) _raise_current_error() except Exception: _lib.sk_X509_NAME_free(name_stack) raise _lib.SSL_CTX_set_client_CA_list(self._context, name_stack) def add_client_ca(self, certificate_authority): """ Add the CA certificate to the list of preferred signers for this context. The list of certificate authorities will be sent to the client when the server requests a client certificate. :param certificate_authority: certificate authority's X509 certificate. :return: None .. versionadded:: 0.10 """ if not isinstance(certificate_authority, X509): raise TypeError("certificate_authority must be an X509 instance") add_result = _lib.SSL_CTX_add_client_CA( self._context, certificate_authority._x509) _openssl_assert(add_result == 1) def set_timeout(self, timeout): """ Set the timeout for newly created sessions for this Context object to *timeout*. The default value is 300 seconds. See the OpenSSL manual for more information (e.g. :manpage:`SSL_CTX_set_timeout(3)`). :param timeout: The timeout in (whole) seconds :return: The previous session timeout """ if not isinstance(timeout, integer_types): raise TypeError("timeout must be an integer") return _lib.SSL_CTX_set_timeout(self._context, timeout) def get_timeout(self): """ Retrieve session timeout, as set by :meth:`set_timeout`. The default is 300 seconds. :return: The session timeout """ return _lib.SSL_CTX_get_timeout(self._context) def set_info_callback(self, callback): """ Set the information callback to *callback*. This function will be called from time to time during SSL handshakes. :param callback: The Python callback to use. This should take three arguments: a Connection object and two integers. The first integer specifies where in the SSL handshake the function was called, and the other the return code from a (possibly failed) internal function call. :return: None """ @wraps(callback) def wrapper(ssl, where, return_code): callback(Connection._reverse_mapping[ssl], where, return_code) self._info_callback = _ffi.callback( "void (*)(const SSL *, int, int)", wrapper) _lib.SSL_CTX_set_info_callback(self._context, self._info_callback) def get_app_data(self): """ Get the application data (supplied via :meth:`set_app_data()`) :return: The application data """ return self._app_data def set_app_data(self, data): """ Set the application data (will be returned from get_app_data()) :param data: Any Python object :return: None """ self._app_data = data def get_cert_store(self): """ Get the certificate store for the context. This can be used to add "trusted" certificates without using the :meth:`load_verify_locations` method. :return: A X509Store object or None if it does not have one. """ store = _lib.SSL_CTX_get_cert_store(self._context) if store == _ffi.NULL: # TODO: This is untested. return None pystore = X509Store.__new__(X509Store) pystore._store = store return pystore def set_options(self, options): """ Add options. Options set before are not cleared! This method should be used with the :const:`OP_*` constants. :param options: The options to add. :return: The new option bitmask. """ if not isinstance(options, integer_types): raise TypeError("options must be an integer") return _lib.SSL_CTX_set_options(self._context, options) def set_mode(self, mode): """ Add modes via bitmask. Modes set before are not cleared! This method should be used with the :const:`MODE_*` constants. :param mode: The mode to add. :return: The new mode bitmask. """ if not isinstance(mode, integer_types): raise TypeError("mode must be an integer") return _lib.SSL_CTX_set_mode(self._context, mode) @_requires_sni def set_tlsext_servername_callback(self, callback): """ Specify a callback function to be called when clients specify a server name. :param callback: The callback function. It will be invoked with one argument, the Connection instance. .. versionadded:: 0.13 """ @wraps(callback) def wrapper(ssl, alert, arg): callback(Connection._reverse_mapping[ssl]) return 0 self._tlsext_servername_callback = _ffi.callback( "int (*)(SSL *, int *, void *)", wrapper) _lib.SSL_CTX_set_tlsext_servername_callback( self._context, self._tlsext_servername_callback) def set_tlsext_use_srtp(self, profiles): """ Enable support for negotiating SRTP keying material. :param bytes profiles: A colon delimited list of protection profile names, like ``b'SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32'``. :return: None """ if not isinstance(profiles, bytes): raise TypeError("profiles must be a byte string.") _openssl_assert( _lib.SSL_CTX_set_tlsext_use_srtp(self._context, profiles) == 0 ) @_requires_npn def set_npn_advertise_callback(self, callback): """ Specify a callback function that will be called when offering `Next Protocol Negotiation `_ as a server. :param callback: The callback function. It will be invoked with one argument, the :class:`Connection` instance. It should return a list of bytestrings representing the advertised protocols, like ``[b'http/1.1', b'spdy/2']``. .. versionadded:: 0.15 """ self._npn_advertise_helper = _NpnAdvertiseHelper(callback) self._npn_advertise_callback = self._npn_advertise_helper.callback _lib.SSL_CTX_set_next_protos_advertised_cb( self._context, self._npn_advertise_callback, _ffi.NULL) @_requires_npn def set_npn_select_callback(self, callback): """ Specify a callback function that will be called when a server offers Next Protocol Negotiation options. :param callback: The callback function. It will be invoked with two arguments: the Connection, and a list of offered protocols as bytestrings, e.g. ``[b'http/1.1', b'spdy/2']``. It should return one of those bytestrings, the chosen protocol. .. versionadded:: 0.15 """ self._npn_select_helper = _NpnSelectHelper(callback) self._npn_select_callback = self._npn_select_helper.callback _lib.SSL_CTX_set_next_proto_select_cb( self._context, self._npn_select_callback, _ffi.NULL) @_requires_alpn def set_alpn_protos(self, protos): """ Specify the protocols that the client is prepared to speak after the TLS connection has been negotiated using Application Layer Protocol Negotiation. :param protos: A list of the protocols to be offered to the server. This list should be a Python list of bytestrings representing the protocols to offer, e.g. ``[b'http/1.1', b'spdy/2']``. """ # Take the list of protocols and join them together, prefixing them # with their lengths. protostr = b''.join( chain.from_iterable((int2byte(len(p)), p) for p in protos) ) # Build a C string from the list. We don't need to save this off # because OpenSSL immediately copies the data out. input_str = _ffi.new("unsigned char[]", protostr) _lib.SSL_CTX_set_alpn_protos(self._context, input_str, len(protostr)) @_requires_alpn def set_alpn_select_callback(self, callback): """ Specify a callback function that will be called on the server when a client offers protocols using ALPN. :param callback: The callback function. It will be invoked with two arguments: the Connection, and a list of offered protocols as bytestrings, e.g ``[b'http/1.1', b'spdy/2']``. It should return one of those bytestrings, the chosen protocol. """ self._alpn_select_helper = _ALPNSelectHelper(callback) self._alpn_select_callback = self._alpn_select_helper.callback _lib.SSL_CTX_set_alpn_select_cb( self._context, self._alpn_select_callback, _ffi.NULL) def _set_ocsp_callback(self, helper, data): """ This internal helper does the common work for ``set_ocsp_server_callback`` and ``set_ocsp_client_callback``, which is almost all of it. """ self._ocsp_helper = helper self._ocsp_callback = helper.callback if data is None: self._ocsp_data = _ffi.NULL else: self._ocsp_data = _ffi.new_handle(data) rc = _lib.SSL_CTX_set_tlsext_status_cb( self._context, self._ocsp_callback ) _openssl_assert(rc == 1) rc = _lib.SSL_CTX_set_tlsext_status_arg(self._context, self._ocsp_data) _openssl_assert(rc == 1) def set_ocsp_server_callback(self, callback, data=None): """ Set a callback to provide OCSP data to be stapled to the TLS handshake on the server side. :param callback: The callback function. It will be invoked with two arguments: the Connection, and the optional arbitrary data you have provided. The callback must return a bytestring that contains the OCSP data to staple to the handshake. If no OCSP data is available for this connection, return the empty bytestring. :param data: Some opaque data that will be passed into the callback function when called. This can be used to avoid needing to do complex data lookups or to keep track of what context is being used. This parameter is optional. """ helper = _OCSPServerCallbackHelper(callback) self._set_ocsp_callback(helper, data) def set_ocsp_client_callback(self, callback, data=None): """ Set a callback to validate OCSP data stapled to the TLS handshake on the client side. :param callback: The callback function. It will be invoked with three arguments: the Connection, a bytestring containing the stapled OCSP assertion, and the optional arbitrary data you have provided. The callback must return a boolean that indicates the result of validating the OCSP data: ``True`` if the OCSP data is valid and the certificate can be trusted, or ``False`` if either the OCSP data is invalid or the certificate has been revoked. :param data: Some opaque data that will be passed into the callback function when called. This can be used to avoid needing to do complex data lookups or to keep track of what context is being used. This parameter is optional. """ helper = _OCSPClientCallbackHelper(callback) self._set_ocsp_callback(helper, data) ContextType = deprecated( Context, __name__, "ContextType has been deprecated, use Context instead", DeprecationWarning ) class Connection(object): """ """ _reverse_mapping = WeakValueDictionary() def __init__(self, context, socket=None): """ Create a new Connection object, using the given OpenSSL.SSL.Context instance and socket. :param context: An SSL Context to use for this connection :param socket: The socket to use for transport layer """ if not isinstance(context, Context): raise TypeError("context must be a Context instance") ssl = _lib.SSL_new(context._context) self._ssl = _ffi.gc(ssl, _lib.SSL_free) # We set SSL_MODE_AUTO_RETRY to handle situations where OpenSSL returns # an SSL_ERROR_WANT_READ when processing a non-application data packet # even though there is still data on the underlying transport. # See https://github.com/openssl/openssl/issues/6234 for more details. _lib.SSL_set_mode(self._ssl, _lib.SSL_MODE_AUTO_RETRY) self._context = context self._app_data = None # References to strings used for Next Protocol Negotiation. OpenSSL's # header files suggest that these might get copied at some point, but # doesn't specify when, so we store them here to make sure they don't # get freed before OpenSSL uses them. self._npn_advertise_callback_args = None self._npn_select_callback_args = None # References to strings used for Application Layer Protocol # Negotiation. These strings get copied at some point but it's well # after the callback returns, so we have to hang them somewhere to # avoid them getting freed. self._alpn_select_callback_args = None self._reverse_mapping[self._ssl] = self if socket is None: self._socket = None # Don't set up any gc for these, SSL_free will take care of them. self._into_ssl = _lib.BIO_new(_lib.BIO_s_mem()) _openssl_assert(self._into_ssl != _ffi.NULL) self._from_ssl = _lib.BIO_new(_lib.BIO_s_mem()) _openssl_assert(self._from_ssl != _ffi.NULL) _lib.SSL_set_bio(self._ssl, self._into_ssl, self._from_ssl) else: self._into_ssl = None self._from_ssl = None self._socket = socket set_result = _lib.SSL_set_fd( self._ssl, _asFileDescriptor(self._socket)) _openssl_assert(set_result == 1) def __getattr__(self, name): """ Look up attributes on the wrapped socket object if they are not found on the Connection object. """ if self._socket is None: raise AttributeError("'%s' object has no attribute '%s'" % ( self.__class__.__name__, name )) else: return getattr(self._socket, name) def _raise_ssl_error(self, ssl, result): if self._context._verify_helper is not None: self._context._verify_helper.raise_if_problem() if self._context._npn_advertise_helper is not None: self._context._npn_advertise_helper.raise_if_problem() if self._context._npn_select_helper is not None: self._context._npn_select_helper.raise_if_problem() if self._context._alpn_select_helper is not None: self._context._alpn_select_helper.raise_if_problem() if self._context._ocsp_helper is not None: self._context._ocsp_helper.raise_if_problem() error = _lib.SSL_get_error(ssl, result) if error == _lib.SSL_ERROR_WANT_READ: raise WantReadError() elif error == _lib.SSL_ERROR_WANT_WRITE: raise WantWriteError() elif error == _lib.SSL_ERROR_ZERO_RETURN: raise ZeroReturnError() elif error == _lib.SSL_ERROR_WANT_X509_LOOKUP: # TODO: This is untested. raise WantX509LookupError() elif error == _lib.SSL_ERROR_SYSCALL: if _lib.ERR_peek_error() == 0: if result < 0: if platform == "win32": errno = _ffi.getwinerror()[0] else: errno = _ffi.errno if errno != 0: raise SysCallError(errno, errorcode.get(errno)) raise SysCallError(-1, "Unexpected EOF") else: # TODO: This is untested. _raise_current_error() elif error == _lib.SSL_ERROR_NONE: pass else: _raise_current_error() def get_context(self): """ Retrieve the :class:`Context` object associated with this :class:`Connection`. """ return self._context def set_context(self, context): """ Switch this connection to a new session context. :param context: A :class:`Context` instance giving the new session context to use. """ if not isinstance(context, Context): raise TypeError("context must be a Context instance") _lib.SSL_set_SSL_CTX(self._ssl, context._context) self._context = context @_requires_sni def get_servername(self): """ Retrieve the servername extension value if provided in the client hello message, or None if there wasn't one. :return: A byte string giving the server name or :data:`None`. .. versionadded:: 0.13 """ name = _lib.SSL_get_servername( self._ssl, _lib.TLSEXT_NAMETYPE_host_name ) if name == _ffi.NULL: return None return _ffi.string(name) @_requires_sni def set_tlsext_host_name(self, name): """ Set the value of the servername extension to send in the client hello. :param name: A byte string giving the name. .. versionadded:: 0.13 """ if not isinstance(name, bytes): raise TypeError("name must be a byte string") elif b"\0" in name: raise TypeError("name must not contain NUL byte") # XXX I guess this can fail sometimes? _lib.SSL_set_tlsext_host_name(self._ssl, name) def pending(self): """ Get the number of bytes that can be safely read from the SSL buffer (**not** the underlying transport buffer). :return: The number of bytes available in the receive buffer. """ return _lib.SSL_pending(self._ssl) def send(self, buf, flags=0): """ Send data on the connection. NOTE: If you get one of the WantRead, WantWrite or WantX509Lookup exceptions on this, you have to call the method again with the SAME buffer. :param buf: The string, buffer or memoryview to send :param flags: (optional) Included for compatibility with the socket API, the value is ignored :return: The number of bytes written """ # Backward compatibility buf = _text_to_bytes_and_warn("buf", buf) if isinstance(buf, memoryview): buf = buf.tobytes() if isinstance(buf, _buffer): buf = str(buf) if not isinstance(buf, bytes): raise TypeError("data must be a memoryview, buffer or byte string") if len(buf) > 2147483647: raise ValueError("Cannot send more than 2**31-1 bytes at once.") result = _lib.SSL_write(self._ssl, buf, len(buf)) self._raise_ssl_error(self._ssl, result) return result write = send def sendall(self, buf, flags=0): """ Send "all" data on the connection. This calls send() repeatedly until all data is sent. If an error occurs, it's impossible to tell how much data has been sent. :param buf: The string, buffer or memoryview to send :param flags: (optional) Included for compatibility with the socket API, the value is ignored :return: The number of bytes written """ buf = _text_to_bytes_and_warn("buf", buf) if isinstance(buf, memoryview): buf = buf.tobytes() if isinstance(buf, _buffer): buf = str(buf) if not isinstance(buf, bytes): raise TypeError("buf must be a memoryview, buffer or byte string") left_to_send = len(buf) total_sent = 0 data = _ffi.new("char[]", buf) while left_to_send: # SSL_write's num arg is an int, # so we cannot send more than 2**31-1 bytes at once. result = _lib.SSL_write( self._ssl, data + total_sent, min(left_to_send, 2147483647) ) self._raise_ssl_error(self._ssl, result) total_sent += result left_to_send -= result def recv(self, bufsiz, flags=None): """ Receive data on the connection. :param bufsiz: The maximum number of bytes to read :param flags: (optional) The only supported flag is ``MSG_PEEK``, all other flags are ignored. :return: The string read from the Connection """ buf = _no_zero_allocator("char[]", bufsiz) if flags is not None and flags & socket.MSG_PEEK: result = _lib.SSL_peek(self._ssl, buf, bufsiz) else: result = _lib.SSL_read(self._ssl, buf, bufsiz) self._raise_ssl_error(self._ssl, result) return _ffi.buffer(buf, result)[:] read = recv def recv_into(self, buffer, nbytes=None, flags=None): """ Receive data on the connection and copy it directly into the provided buffer, rather than creating a new string. :param buffer: The buffer to copy into. :param nbytes: (optional) The maximum number of bytes to read into the buffer. If not present, defaults to the size of the buffer. If larger than the size of the buffer, is reduced to the size of the buffer. :param flags: (optional) The only supported flag is ``MSG_PEEK``, all other flags are ignored. :return: The number of bytes read into the buffer. """ if nbytes is None: nbytes = len(buffer) else: nbytes = min(nbytes, len(buffer)) # We need to create a temporary buffer. This is annoying, it would be # better if we could pass memoryviews straight into the SSL_read call, # but right now we can't. Revisit this if CFFI gets that ability. buf = _no_zero_allocator("char[]", nbytes) if flags is not None and flags & socket.MSG_PEEK: result = _lib.SSL_peek(self._ssl, buf, nbytes) else: result = _lib.SSL_read(self._ssl, buf, nbytes) self._raise_ssl_error(self._ssl, result) # This strange line is all to avoid a memory copy. The buffer protocol # should allow us to assign a CFFI buffer to the LHS of this line, but # on CPython 3.3+ that segfaults. As a workaround, we can temporarily # wrap it in a memoryview. buffer[:result] = memoryview(_ffi.buffer(buf, result)) return result def _handle_bio_errors(self, bio, result): if _lib.BIO_should_retry(bio): if _lib.BIO_should_read(bio): raise WantReadError() elif _lib.BIO_should_write(bio): # TODO: This is untested. raise WantWriteError() elif _lib.BIO_should_io_special(bio): # TODO: This is untested. I think io_special means the socket # BIO has a not-yet connected socket. raise ValueError("BIO_should_io_special") else: # TODO: This is untested. raise ValueError("unknown bio failure") else: # TODO: This is untested. _raise_current_error() def bio_read(self, bufsiz): """ If the Connection was created with a memory BIO, this method can be used to read bytes from the write end of that memory BIO. Many Connection methods will add bytes which must be read in this manner or the buffer will eventually fill up and the Connection will be able to take no further actions. :param bufsiz: The maximum number of bytes to read :return: The string read. """ if self._from_ssl is None: raise TypeError("Connection sock was not None") if not isinstance(bufsiz, integer_types): raise TypeError("bufsiz must be an integer") buf = _no_zero_allocator("char[]", bufsiz) result = _lib.BIO_read(self._from_ssl, buf, bufsiz) if result <= 0: self._handle_bio_errors(self._from_ssl, result) return _ffi.buffer(buf, result)[:] def bio_write(self, buf): """ If the Connection was created with a memory BIO, this method can be used to add bytes to the read end of that memory BIO. The Connection can then read the bytes (for example, in response to a call to :meth:`recv`). :param buf: The string to put into the memory BIO. :return: The number of bytes written """ buf = _text_to_bytes_and_warn("buf", buf) if self._into_ssl is None: raise TypeError("Connection sock was not None") result = _lib.BIO_write(self._into_ssl, buf, len(buf)) if result <= 0: self._handle_bio_errors(self._into_ssl, result) return result def renegotiate(self): """ Renegotiate the session. :return: True if the renegotiation can be started, False otherwise :rtype: bool """ if not self.renegotiate_pending(): _openssl_assert(_lib.SSL_renegotiate(self._ssl) == 1) return True return False def do_handshake(self): """ Perform an SSL handshake (usually called after :meth:`renegotiate` or one of :meth:`set_accept_state` or :meth:`set_accept_state`). This can raise the same exceptions as :meth:`send` and :meth:`recv`. :return: None. """ result = _lib.SSL_do_handshake(self._ssl) self._raise_ssl_error(self._ssl, result) def renegotiate_pending(self): """ Check if there's a renegotiation in progress, it will return False once a renegotiation is finished. :return: Whether there's a renegotiation in progress :rtype: bool """ return _lib.SSL_renegotiate_pending(self._ssl) == 1 def total_renegotiations(self): """ Find out the total number of renegotiations. :return: The number of renegotiations. :rtype: int """ return _lib.SSL_total_renegotiations(self._ssl) def connect(self, addr): """ Call the :meth:`connect` method of the underlying socket and set up SSL on the socket, using the :class:`Context` object supplied to this :class:`Connection` object at creation. :param addr: A remote address :return: What the socket's connect method returns """ _lib.SSL_set_connect_state(self._ssl) return self._socket.connect(addr) def connect_ex(self, addr): """ Call the :meth:`connect_ex` method of the underlying socket and set up SSL on the socket, using the Context object supplied to this Connection object at creation. Note that if the :meth:`connect_ex` method of the socket doesn't return 0, SSL won't be initialized. :param addr: A remove address :return: What the socket's connect_ex method returns """ connect_ex = self._socket.connect_ex self.set_connect_state() return connect_ex(addr) def accept(self): """ Call the :meth:`accept` method of the underlying socket and set up SSL on the returned socket, using the Context object supplied to this :class:`Connection` object at creation. :return: A *(conn, addr)* pair where *conn* is the new :class:`Connection` object created, and *address* is as returned by the socket's :meth:`accept`. """ client, addr = self._socket.accept() conn = Connection(self._context, client) conn.set_accept_state() return (conn, addr) def bio_shutdown(self): """ If the Connection was created with a memory BIO, this method can be used to indicate that *end of file* has been reached on the read end of that memory BIO. :return: None """ if self._from_ssl is None: raise TypeError("Connection sock was not None") _lib.BIO_set_mem_eof_return(self._into_ssl, 0) def shutdown(self): """ Send the shutdown message to the Connection. :return: True if the shutdown completed successfully (i.e. both sides have sent closure alerts), False otherwise (in which case you call :meth:`recv` or :meth:`send` when the connection becomes readable/writeable). """ result = _lib.SSL_shutdown(self._ssl) if result < 0: self._raise_ssl_error(self._ssl, result) elif result > 0: return True else: return False def get_cipher_list(self): """ Retrieve the list of ciphers used by the Connection object. :return: A list of native cipher strings. """ ciphers = [] for i in count(): result = _lib.SSL_get_cipher_list(self._ssl, i) if result == _ffi.NULL: break ciphers.append(_native(_ffi.string(result))) return ciphers def get_client_ca_list(self): """ Get CAs whose certificates are suggested for client authentication. :return: If this is a server connection, the list of certificate authorities that will be sent or has been sent to the client, as controlled by this :class:`Connection`'s :class:`Context`. If this is a client connection, the list will be empty until the connection with the server is established. .. versionadded:: 0.10 """ ca_names = _lib.SSL_get_client_CA_list(self._ssl) if ca_names == _ffi.NULL: # TODO: This is untested. return [] result = [] for i in range(_lib.sk_X509_NAME_num(ca_names)): name = _lib.sk_X509_NAME_value(ca_names, i) copy = _lib.X509_NAME_dup(name) _openssl_assert(copy != _ffi.NULL) pyname = X509Name.__new__(X509Name) pyname._name = _ffi.gc(copy, _lib.X509_NAME_free) result.append(pyname) return result def makefile(self, *args, **kwargs): """ The makefile() method is not implemented, since there is no dup semantics for SSL connections :raise: NotImplementedError """ raise NotImplementedError( "Cannot make file object of OpenSSL.SSL.Connection") def get_app_data(self): """ Retrieve application data as set by :meth:`set_app_data`. :return: The application data """ return self._app_data def set_app_data(self, data): """ Set application data :param data: The application data :return: None """ self._app_data = data def get_shutdown(self): """ Get the shutdown state of the Connection. :return: The shutdown state, a bitvector of SENT_SHUTDOWN, RECEIVED_SHUTDOWN. """ return _lib.SSL_get_shutdown(self._ssl) def set_shutdown(self, state): """ Set the shutdown state of the Connection. :param state: bitvector of SENT_SHUTDOWN, RECEIVED_SHUTDOWN. :return: None """ if not isinstance(state, integer_types): raise TypeError("state must be an integer") _lib.SSL_set_shutdown(self._ssl, state) def get_state_string(self): """ Retrieve a verbose string detailing the state of the Connection. :return: A string representing the state :rtype: bytes """ return _ffi.string(_lib.SSL_state_string_long(self._ssl)) def server_random(self): """ Retrieve the random value used with the server hello message. :return: A string representing the state """ session = _lib.SSL_get_session(self._ssl) if session == _ffi.NULL: return None length = _lib.SSL_get_server_random(self._ssl, _ffi.NULL, 0) assert length > 0 outp = _no_zero_allocator("unsigned char[]", length) _lib.SSL_get_server_random(self._ssl, outp, length) return _ffi.buffer(outp, length)[:] def client_random(self): """ Retrieve the random value used with the client hello message. :return: A string representing the state """ session = _lib.SSL_get_session(self._ssl) if session == _ffi.NULL: return None length = _lib.SSL_get_client_random(self._ssl, _ffi.NULL, 0) assert length > 0 outp = _no_zero_allocator("unsigned char[]", length) _lib.SSL_get_client_random(self._ssl, outp, length) return _ffi.buffer(outp, length)[:] def master_key(self): """ Retrieve the value of the master key for this session. :return: A string representing the state """ session = _lib.SSL_get_session(self._ssl) if session == _ffi.NULL: return None length = _lib.SSL_SESSION_get_master_key(session, _ffi.NULL, 0) assert length > 0 outp = _no_zero_allocator("unsigned char[]", length) _lib.SSL_SESSION_get_master_key(session, outp, length) return _ffi.buffer(outp, length)[:] def export_keying_material(self, label, olen, context=None): """ Obtain keying material for application use. :param: label - a disambiguating label string as described in RFC 5705 :param: olen - the length of the exported key material in bytes :param: context - a per-association context value :return: the exported key material bytes or None """ outp = _no_zero_allocator("unsigned char[]", olen) context_buf = _ffi.NULL context_len = 0 use_context = 0 if context is not None: context_buf = context context_len = len(context) use_context = 1 success = _lib.SSL_export_keying_material(self._ssl, outp, olen, label, len(label), context_buf, context_len, use_context) _openssl_assert(success == 1) return _ffi.buffer(outp, olen)[:] def sock_shutdown(self, *args, **kwargs): """ Call the :meth:`shutdown` method of the underlying socket. See :manpage:`shutdown(2)`. :return: What the socket's shutdown() method returns """ return self._socket.shutdown(*args, **kwargs) def get_certificate(self): """ Retrieve the local certificate (if any) :return: The local certificate """ cert = _lib.SSL_get_certificate(self._ssl) if cert != _ffi.NULL: _lib.X509_up_ref(cert) return X509._from_raw_x509_ptr(cert) return None def get_peer_certificate(self): """ Retrieve the other side's certificate (if any) :return: The peer's certificate """ cert = _lib.SSL_get_peer_certificate(self._ssl) if cert != _ffi.NULL: return X509._from_raw_x509_ptr(cert) return None def get_peer_cert_chain(self): """ Retrieve the other side's certificate (if any) :return: A list of X509 instances giving the peer's certificate chain, or None if it does not have one. """ cert_stack = _lib.SSL_get_peer_cert_chain(self._ssl) if cert_stack == _ffi.NULL: return None result = [] for i in range(_lib.sk_X509_num(cert_stack)): # TODO could incref instead of dup here cert = _lib.X509_dup(_lib.sk_X509_value(cert_stack, i)) pycert = X509._from_raw_x509_ptr(cert) result.append(pycert) return result def want_read(self): """ Checks if more data has to be read from the transport layer to complete an operation. :return: True iff more data has to be read """ return _lib.SSL_want_read(self._ssl) def want_write(self): """ Checks if there is data to write to the transport layer to complete an operation. :return: True iff there is data to write """ return _lib.SSL_want_write(self._ssl) def set_accept_state(self): """ Set the connection to work in server mode. The handshake will be handled automatically by read/write. :return: None """ _lib.SSL_set_accept_state(self._ssl) def set_connect_state(self): """ Set the connection to work in client mode. The handshake will be handled automatically by read/write. :return: None """ _lib.SSL_set_connect_state(self._ssl) def get_session(self): """ Returns the Session currently used. :return: An instance of :class:`OpenSSL.SSL.Session` or :obj:`None` if no session exists. .. versionadded:: 0.14 """ session = _lib.SSL_get1_session(self._ssl) if session == _ffi.NULL: return None pysession = Session.__new__(Session) pysession._session = _ffi.gc(session, _lib.SSL_SESSION_free) return pysession def set_session(self, session): """ Set the session to be used when the TLS/SSL connection is established. :param session: A Session instance representing the session to use. :returns: None .. versionadded:: 0.14 """ if not isinstance(session, Session): raise TypeError("session must be a Session instance") result = _lib.SSL_set_session(self._ssl, session._session) if not result: _raise_current_error() def _get_finished_message(self, function): """ Helper to implement :meth:`get_finished` and :meth:`get_peer_finished`. :param function: Either :data:`SSL_get_finished`: or :data:`SSL_get_peer_finished`. :return: :data:`None` if the desired message has not yet been received, otherwise the contents of the message. :rtype: :class:`bytes` or :class:`NoneType` """ # The OpenSSL documentation says nothing about what might happen if the # count argument given is zero. Specifically, it doesn't say whether # the output buffer may be NULL in that case or not. Inspection of the # implementation reveals that it calls memcpy() unconditionally. # Section 7.1.4, paragraph 1 of the C standard suggests that # memcpy(NULL, source, 0) is not guaranteed to produce defined (let # alone desirable) behavior (though it probably does on just about # every implementation...) # # Allocate a tiny buffer to pass in (instead of just passing NULL as # one might expect) for the initial call so as to be safe against this # potentially undefined behavior. empty = _ffi.new("char[]", 0) size = function(self._ssl, empty, 0) if size == 0: # No Finished message so far. return None buf = _no_zero_allocator("char[]", size) function(self._ssl, buf, size) return _ffi.buffer(buf, size)[:] def get_finished(self): """ Obtain the latest TLS Finished message that we sent. :return: The contents of the message or :obj:`None` if the TLS handshake has not yet completed. :rtype: :class:`bytes` or :class:`NoneType` .. versionadded:: 0.15 """ return self._get_finished_message(_lib.SSL_get_finished) def get_peer_finished(self): """ Obtain the latest TLS Finished message that we received from the peer. :return: The contents of the message or :obj:`None` if the TLS handshake has not yet completed. :rtype: :class:`bytes` or :class:`NoneType` .. versionadded:: 0.15 """ return self._get_finished_message(_lib.SSL_get_peer_finished) def get_cipher_name(self): """ Obtain the name of the currently used cipher. :returns: The name of the currently used cipher or :obj:`None` if no connection has been established. :rtype: :class:`unicode` or :class:`NoneType` .. versionadded:: 0.15 """ cipher = _lib.SSL_get_current_cipher(self._ssl) if cipher == _ffi.NULL: return None else: name = _ffi.string(_lib.SSL_CIPHER_get_name(cipher)) return name.decode("utf-8") def get_cipher_bits(self): """ Obtain the number of secret bits of the currently used cipher. :returns: The number of secret bits of the currently used cipher or :obj:`None` if no connection has been established. :rtype: :class:`int` or :class:`NoneType` .. versionadded:: 0.15 """ cipher = _lib.SSL_get_current_cipher(self._ssl) if cipher == _ffi.NULL: return None else: return _lib.SSL_CIPHER_get_bits(cipher, _ffi.NULL) def get_cipher_version(self): """ Obtain the protocol version of the currently used cipher. :returns: The protocol name of the currently used cipher or :obj:`None` if no connection has been established. :rtype: :class:`unicode` or :class:`NoneType` .. versionadded:: 0.15 """ cipher = _lib.SSL_get_current_cipher(self._ssl) if cipher == _ffi.NULL: return None else: version = _ffi.string(_lib.SSL_CIPHER_get_version(cipher)) return version.decode("utf-8") def get_protocol_version_name(self): """ Retrieve the protocol version of the current connection. :returns: The TLS version of the current connection, for example the value for TLS 1.2 would be ``TLSv1.2``or ``Unknown`` for connections that were not successfully established. :rtype: :class:`unicode` """ version = _ffi.string(_lib.SSL_get_version(self._ssl)) return version.decode("utf-8") def get_protocol_version(self): """ Retrieve the SSL or TLS protocol version of the current connection. :returns: The TLS version of the current connection. For example, it will return ``0x769`` for connections made over TLS version 1. :rtype: :class:`int` """ version = _lib.SSL_version(self._ssl) return version @_requires_npn def get_next_proto_negotiated(self): """ Get the protocol that was negotiated by NPN. :returns: A bytestring of the protocol name. If no protocol has been negotiated yet, returns an empty string. .. versionadded:: 0.15 """ data = _ffi.new("unsigned char **") data_len = _ffi.new("unsigned int *") _lib.SSL_get0_next_proto_negotiated(self._ssl, data, data_len) return _ffi.buffer(data[0], data_len[0])[:] @_requires_alpn def set_alpn_protos(self, protos): """ Specify the client's ALPN protocol list. These protocols are offered to the server during protocol negotiation. :param protos: A list of the protocols to be offered to the server. This list should be a Python list of bytestrings representing the protocols to offer, e.g. ``[b'http/1.1', b'spdy/2']``. """ # Take the list of protocols and join them together, prefixing them # with their lengths. protostr = b''.join( chain.from_iterable((int2byte(len(p)), p) for p in protos) ) # Build a C string from the list. We don't need to save this off # because OpenSSL immediately copies the data out. input_str = _ffi.new("unsigned char[]", protostr) _lib.SSL_set_alpn_protos(self._ssl, input_str, len(protostr)) @_requires_alpn def get_alpn_proto_negotiated(self): """ Get the protocol that was negotiated by ALPN. :returns: A bytestring of the protocol name. If no protocol has been negotiated yet, returns an empty string. """ data = _ffi.new("unsigned char **") data_len = _ffi.new("unsigned int *") _lib.SSL_get0_alpn_selected(self._ssl, data, data_len) if not data_len: return b'' return _ffi.buffer(data[0], data_len[0])[:] def request_ocsp(self): """ Called to request that the server sends stapled OCSP data, if available. If this is not called on the client side then the server will not send OCSP data. Should be used in conjunction with :meth:`Context.set_ocsp_client_callback`. """ rc = _lib.SSL_set_tlsext_status_type( self._ssl, _lib.TLSEXT_STATUSTYPE_ocsp ) _openssl_assert(rc == 1) ConnectionType = deprecated( Connection, __name__, "ConnectionType has been deprecated, use Connection instead", DeprecationWarning ) # This is similar to the initialization calls at the end of OpenSSL/crypto.py # but is exercised mostly by the Context initializer. _lib.SSL_library_init() ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/OpenSSL/__init__.py ================================================ # Copyright (C) AB Strakt # See LICENSE for details. """ pyOpenSSL - A simple wrapper around the OpenSSL library """ from OpenSSL import crypto, SSL from OpenSSL.version import ( __author__, __copyright__, __email__, __license__, __summary__, __title__, __uri__, __version__, ) __all__ = [ "SSL", "crypto", "__author__", "__copyright__", "__email__", "__license__", "__summary__", "__title__", "__uri__", "__version__", ] ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/OpenSSL/_util.py ================================================ import sys import warnings from six import PY3, binary_type, text_type from cryptography.hazmat.bindings.openssl.binding import Binding binding = Binding() binding.init_static_locks() ffi = binding.ffi lib = binding.lib # This is a special CFFI allocator that does not bother to zero its memory # after allocation. This has vastly better performance on large allocations and # so should be used whenever we don't need the memory zeroed out. no_zero_allocator = ffi.new_allocator(should_clear_after_alloc=False) def text(charp): """ Get a native string type representing of the given CFFI ``char*`` object. :param charp: A C-style string represented using CFFI. :return: :class:`str` """ if not charp: return "" return native(ffi.string(charp)) def exception_from_error_queue(exception_type): """ Convert an OpenSSL library failure into a Python exception. When a call to the native OpenSSL library fails, this is usually signalled by the return value, and an error code is stored in an error queue associated with the current thread. The err library provides functions to obtain these error codes and textual error messages. """ errors = [] while True: error = lib.ERR_get_error() if error == 0: break errors.append(( text(lib.ERR_lib_error_string(error)), text(lib.ERR_func_error_string(error)), text(lib.ERR_reason_error_string(error)))) raise exception_type(errors) def make_assert(error): """ Create an assert function that uses :func:`exception_from_error_queue` to raise an exception wrapped by *error*. """ def openssl_assert(ok): """ If *ok* is not True, retrieve the error from OpenSSL and raise it. """ if ok is not True: exception_from_error_queue(error) return openssl_assert def native(s): """ Convert :py:class:`bytes` or :py:class:`unicode` to the native :py:class:`str` type, using UTF-8 encoding if conversion is necessary. :raise UnicodeError: The input string is not UTF-8 decodeable. :raise TypeError: The input is neither :py:class:`bytes` nor :py:class:`unicode`. """ if not isinstance(s, (binary_type, text_type)): raise TypeError("%r is neither bytes nor unicode" % s) if PY3: if isinstance(s, binary_type): return s.decode("utf-8") else: if isinstance(s, text_type): return s.encode("utf-8") return s def path_string(s): """ Convert a Python string to a :py:class:`bytes` string identifying the same path and which can be passed into an OpenSSL API accepting a filename. :param s: An instance of :py:class:`bytes` or :py:class:`unicode`. :return: An instance of :py:class:`bytes`. """ if isinstance(s, binary_type): return s elif isinstance(s, text_type): return s.encode(sys.getfilesystemencoding()) else: raise TypeError("Path must be represented as bytes or unicode string") if PY3: def byte_string(s): return s.encode("charmap") else: def byte_string(s): return s # A marker object to observe whether some optional arguments are passed any # value or not. UNSPECIFIED = object() _TEXT_WARNING = ( text_type.__name__ + " for {0} is no longer accepted, use bytes" ) def text_to_bytes_and_warn(label, obj): """ If ``obj`` is text, emit a warning that it should be bytes instead and try to convert it to bytes automatically. :param str label: The name of the parameter from which ``obj`` was taken (so a developer can easily find the source of the problem and correct it). :return: If ``obj`` is the text string type, a ``bytes`` object giving the UTF-8 encoding of that text is returned. Otherwise, ``obj`` itself is returned. """ if isinstance(obj, text_type): warnings.warn( _TEXT_WARNING.format(label), category=DeprecationWarning, stacklevel=3 ) return obj.encode('utf-8') return obj ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/OpenSSL/crypto.py ================================================ import datetime from base64 import b16encode from functools import partial from operator import __eq__, __ne__, __lt__, __le__, __gt__, __ge__ from six import ( integer_types as _integer_types, text_type as _text_type, PY3 as _PY3) from cryptography import x509 from cryptography.hazmat.primitives.asymmetric import dsa, rsa from cryptography.utils import deprecated from OpenSSL._util import ( ffi as _ffi, lib as _lib, exception_from_error_queue as _exception_from_error_queue, byte_string as _byte_string, native as _native, UNSPECIFIED as _UNSPECIFIED, text_to_bytes_and_warn as _text_to_bytes_and_warn, make_assert as _make_assert, ) __all__ = [ 'FILETYPE_PEM', 'FILETYPE_ASN1', 'FILETYPE_TEXT', 'TYPE_RSA', 'TYPE_DSA', 'Error', 'PKey', 'get_elliptic_curves', 'get_elliptic_curve', 'X509Name', 'X509Extension', 'X509Req', 'X509', 'X509StoreFlags', 'X509Store', 'X509StoreContextError', 'X509StoreContext', 'load_certificate', 'dump_certificate', 'dump_publickey', 'dump_privatekey', 'Revoked', 'CRL', 'PKCS7', 'PKCS12', 'NetscapeSPKI', 'load_publickey', 'load_privatekey', 'dump_certificate_request', 'load_certificate_request', 'sign', 'verify', 'dump_crl', 'load_crl', 'load_pkcs7_data', 'load_pkcs12' ] FILETYPE_PEM = _lib.SSL_FILETYPE_PEM FILETYPE_ASN1 = _lib.SSL_FILETYPE_ASN1 # TODO This was an API mistake. OpenSSL has no such constant. FILETYPE_TEXT = 2 ** 16 - 1 TYPE_RSA = _lib.EVP_PKEY_RSA TYPE_DSA = _lib.EVP_PKEY_DSA TYPE_DH = _lib.EVP_PKEY_DH TYPE_EC = _lib.EVP_PKEY_EC class Error(Exception): """ An error occurred in an `OpenSSL.crypto` API. """ _raise_current_error = partial(_exception_from_error_queue, Error) _openssl_assert = _make_assert(Error) def _get_backend(): """ Importing the backend from cryptography has the side effect of activating the osrandom engine. This mutates the global state of OpenSSL in the process and causes issues for various programs that use subinterpreters or embed Python. By putting the import in this function we can avoid triggering this side effect unless _get_backend is called. """ from cryptography.hazmat.backends.openssl.backend import backend return backend def _untested_error(where): """ An OpenSSL API failed somehow. Additionally, the failure which was encountered isn't one that's exercised by the test suite so future behavior of pyOpenSSL is now somewhat less predictable. """ raise RuntimeError("Unknown %s failure" % (where,)) def _new_mem_buf(buffer=None): """ Allocate a new OpenSSL memory BIO. Arrange for the garbage collector to clean it up automatically. :param buffer: None or some bytes to use to put into the BIO so that they can be read out. """ if buffer is None: bio = _lib.BIO_new(_lib.BIO_s_mem()) free = _lib.BIO_free else: data = _ffi.new("char[]", buffer) bio = _lib.BIO_new_mem_buf(data, len(buffer)) # Keep the memory alive as long as the bio is alive! def free(bio, ref=data): return _lib.BIO_free(bio) _openssl_assert(bio != _ffi.NULL) bio = _ffi.gc(bio, free) return bio def _bio_to_string(bio): """ Copy the contents of an OpenSSL BIO object into a Python byte string. """ result_buffer = _ffi.new('char**') buffer_length = _lib.BIO_get_mem_data(bio, result_buffer) return _ffi.buffer(result_buffer[0], buffer_length)[:] def _set_asn1_time(boundary, when): """ The the time value of an ASN1 time object. @param boundary: An ASN1_TIME pointer (or an object safely castable to that type) which will have its value set. @param when: A string representation of the desired time value. @raise TypeError: If C{when} is not a L{bytes} string. @raise ValueError: If C{when} does not represent a time in the required format. @raise RuntimeError: If the time value cannot be set for some other (unspecified) reason. """ if not isinstance(when, bytes): raise TypeError("when must be a byte string") set_result = _lib.ASN1_TIME_set_string(boundary, when) if set_result == 0: raise ValueError("Invalid string") def _get_asn1_time(timestamp): """ Retrieve the time value of an ASN1 time object. @param timestamp: An ASN1_GENERALIZEDTIME* (or an object safely castable to that type) from which the time value will be retrieved. @return: The time value from C{timestamp} as a L{bytes} string in a certain format. Or C{None} if the object contains no time value. """ string_timestamp = _ffi.cast('ASN1_STRING*', timestamp) if _lib.ASN1_STRING_length(string_timestamp) == 0: return None elif ( _lib.ASN1_STRING_type(string_timestamp) == _lib.V_ASN1_GENERALIZEDTIME ): return _ffi.string(_lib.ASN1_STRING_data(string_timestamp)) else: generalized_timestamp = _ffi.new("ASN1_GENERALIZEDTIME**") _lib.ASN1_TIME_to_generalizedtime(timestamp, generalized_timestamp) if generalized_timestamp[0] == _ffi.NULL: # This may happen: # - if timestamp was not an ASN1_TIME # - if allocating memory for the ASN1_GENERALIZEDTIME failed # - if a copy of the time data from timestamp cannot be made for # the newly allocated ASN1_GENERALIZEDTIME # # These are difficult to test. cffi enforces the ASN1_TIME type. # Memory allocation failures are a pain to trigger # deterministically. _untested_error("ASN1_TIME_to_generalizedtime") else: string_timestamp = _ffi.cast( "ASN1_STRING*", generalized_timestamp[0]) string_data = _lib.ASN1_STRING_data(string_timestamp) string_result = _ffi.string(string_data) _lib.ASN1_GENERALIZEDTIME_free(generalized_timestamp[0]) return string_result class _X509NameInvalidator(object): def __init__(self): self._names = [] def add(self, name): self._names.append(name) def clear(self): for name in self._names: # Breaks the object, but also prevents UAF! del name._name class PKey(object): """ A class representing an DSA or RSA public key or key pair. """ _only_public = False _initialized = True def __init__(self): pkey = _lib.EVP_PKEY_new() self._pkey = _ffi.gc(pkey, _lib.EVP_PKEY_free) self._initialized = False def to_cryptography_key(self): """ Export as a ``cryptography`` key. :rtype: One of ``cryptography``'s `key interfaces`_. .. _key interfaces: https://cryptography.io/en/latest/hazmat/\ primitives/asymmetric/rsa/#key-interfaces .. versionadded:: 16.1.0 """ backend = _get_backend() if self._only_public: return backend._evp_pkey_to_public_key(self._pkey) else: return backend._evp_pkey_to_private_key(self._pkey) @classmethod def from_cryptography_key(cls, crypto_key): """ Construct based on a ``cryptography`` *crypto_key*. :param crypto_key: A ``cryptography`` key. :type crypto_key: One of ``cryptography``'s `key interfaces`_. :rtype: PKey .. versionadded:: 16.1.0 """ pkey = cls() if not isinstance(crypto_key, (rsa.RSAPublicKey, rsa.RSAPrivateKey, dsa.DSAPublicKey, dsa.DSAPrivateKey)): raise TypeError("Unsupported key type") pkey._pkey = crypto_key._evp_pkey if isinstance(crypto_key, (rsa.RSAPublicKey, dsa.DSAPublicKey)): pkey._only_public = True pkey._initialized = True return pkey def generate_key(self, type, bits): """ Generate a key pair of the given type, with the given number of bits. This generates a key "into" the this object. :param type: The key type. :type type: :py:data:`TYPE_RSA` or :py:data:`TYPE_DSA` :param bits: The number of bits. :type bits: :py:data:`int` ``>= 0`` :raises TypeError: If :py:data:`type` or :py:data:`bits` isn't of the appropriate type. :raises ValueError: If the number of bits isn't an integer of the appropriate size. :return: ``None`` """ if not isinstance(type, int): raise TypeError("type must be an integer") if not isinstance(bits, int): raise TypeError("bits must be an integer") if type == TYPE_RSA: if bits <= 0: raise ValueError("Invalid number of bits") # TODO Check error return exponent = _lib.BN_new() exponent = _ffi.gc(exponent, _lib.BN_free) _lib.BN_set_word(exponent, _lib.RSA_F4) rsa = _lib.RSA_new() result = _lib.RSA_generate_key_ex(rsa, bits, exponent, _ffi.NULL) _openssl_assert(result == 1) result = _lib.EVP_PKEY_assign_RSA(self._pkey, rsa) _openssl_assert(result == 1) elif type == TYPE_DSA: dsa = _lib.DSA_new() _openssl_assert(dsa != _ffi.NULL) dsa = _ffi.gc(dsa, _lib.DSA_free) res = _lib.DSA_generate_parameters_ex( dsa, bits, _ffi.NULL, 0, _ffi.NULL, _ffi.NULL, _ffi.NULL ) _openssl_assert(res == 1) _openssl_assert(_lib.DSA_generate_key(dsa) == 1) _openssl_assert(_lib.EVP_PKEY_set1_DSA(self._pkey, dsa) == 1) else: raise Error("No such key type") self._initialized = True def check(self): """ Check the consistency of an RSA private key. This is the Python equivalent of OpenSSL's ``RSA_check_key``. :return: ``True`` if key is consistent. :raise OpenSSL.crypto.Error: if the key is inconsistent. :raise TypeError: if the key is of a type which cannot be checked. Only RSA keys can currently be checked. """ if self._only_public: raise TypeError("public key only") if _lib.EVP_PKEY_type(self.type()) != _lib.EVP_PKEY_RSA: raise TypeError("key type unsupported") rsa = _lib.EVP_PKEY_get1_RSA(self._pkey) rsa = _ffi.gc(rsa, _lib.RSA_free) result = _lib.RSA_check_key(rsa) if result: return True _raise_current_error() def type(self): """ Returns the type of the key :return: The type of the key. """ return _lib.EVP_PKEY_id(self._pkey) def bits(self): """ Returns the number of bits of the key :return: The number of bits of the key. """ return _lib.EVP_PKEY_bits(self._pkey) PKeyType = deprecated( PKey, __name__, "PKeyType has been deprecated, use PKey instead", DeprecationWarning ) class _EllipticCurve(object): """ A representation of a supported elliptic curve. @cvar _curves: :py:obj:`None` until an attempt is made to load the curves. Thereafter, a :py:type:`set` containing :py:type:`_EllipticCurve` instances each of which represents one curve supported by the system. @type _curves: :py:type:`NoneType` or :py:type:`set` """ _curves = None if _PY3: # This only necessary on Python 3. Morever, it is broken on Python 2. def __ne__(self, other): """ Implement cooperation with the right-hand side argument of ``!=``. Python 3 seems to have dropped this cooperation in this very narrow circumstance. """ if isinstance(other, _EllipticCurve): return super(_EllipticCurve, self).__ne__(other) return NotImplemented @classmethod def _load_elliptic_curves(cls, lib): """ Get the curves supported by OpenSSL. :param lib: The OpenSSL library binding object. :return: A :py:type:`set` of ``cls`` instances giving the names of the elliptic curves the underlying library supports. """ num_curves = lib.EC_get_builtin_curves(_ffi.NULL, 0) builtin_curves = _ffi.new('EC_builtin_curve[]', num_curves) # The return value on this call should be num_curves again. We # could check it to make sure but if it *isn't* then.. what could # we do? Abort the whole process, I suppose...? -exarkun lib.EC_get_builtin_curves(builtin_curves, num_curves) return set( cls.from_nid(lib, c.nid) for c in builtin_curves) @classmethod def _get_elliptic_curves(cls, lib): """ Get, cache, and return the curves supported by OpenSSL. :param lib: The OpenSSL library binding object. :return: A :py:type:`set` of ``cls`` instances giving the names of the elliptic curves the underlying library supports. """ if cls._curves is None: cls._curves = cls._load_elliptic_curves(lib) return cls._curves @classmethod def from_nid(cls, lib, nid): """ Instantiate a new :py:class:`_EllipticCurve` associated with the given OpenSSL NID. :param lib: The OpenSSL library binding object. :param nid: The OpenSSL NID the resulting curve object will represent. This must be a curve NID (and not, for example, a hash NID) or subsequent operations will fail in unpredictable ways. :type nid: :py:class:`int` :return: The curve object. """ return cls(lib, nid, _ffi.string(lib.OBJ_nid2sn(nid)).decode("ascii")) def __init__(self, lib, nid, name): """ :param _lib: The :py:mod:`cryptography` binding instance used to interface with OpenSSL. :param _nid: The OpenSSL NID identifying the curve this object represents. :type _nid: :py:class:`int` :param name: The OpenSSL short name identifying the curve this object represents. :type name: :py:class:`unicode` """ self._lib = lib self._nid = nid self.name = name def __repr__(self): return "" % (self.name,) def _to_EC_KEY(self): """ Create a new OpenSSL EC_KEY structure initialized to use this curve. The structure is automatically garbage collected when the Python object is garbage collected. """ key = self._lib.EC_KEY_new_by_curve_name(self._nid) return _ffi.gc(key, _lib.EC_KEY_free) def get_elliptic_curves(): """ Return a set of objects representing the elliptic curves supported in the OpenSSL build in use. The curve objects have a :py:class:`unicode` ``name`` attribute by which they identify themselves. The curve objects are useful as values for the argument accepted by :py:meth:`Context.set_tmp_ecdh` to specify which elliptical curve should be used for ECDHE key exchange. """ return _EllipticCurve._get_elliptic_curves(_lib) def get_elliptic_curve(name): """ Return a single curve object selected by name. See :py:func:`get_elliptic_curves` for information about curve objects. :param name: The OpenSSL short name identifying the curve object to retrieve. :type name: :py:class:`unicode` If the named curve is not supported then :py:class:`ValueError` is raised. """ for curve in get_elliptic_curves(): if curve.name == name: return curve raise ValueError("unknown curve name", name) class X509Name(object): """ An X.509 Distinguished Name. :ivar countryName: The country of the entity. :ivar C: Alias for :py:attr:`countryName`. :ivar stateOrProvinceName: The state or province of the entity. :ivar ST: Alias for :py:attr:`stateOrProvinceName`. :ivar localityName: The locality of the entity. :ivar L: Alias for :py:attr:`localityName`. :ivar organizationName: The organization name of the entity. :ivar O: Alias for :py:attr:`organizationName`. :ivar organizationalUnitName: The organizational unit of the entity. :ivar OU: Alias for :py:attr:`organizationalUnitName` :ivar commonName: The common name of the entity. :ivar CN: Alias for :py:attr:`commonName`. :ivar emailAddress: The e-mail address of the entity. """ def __init__(self, name): """ Create a new X509Name, copying the given X509Name instance. :param name: The name to copy. :type name: :py:class:`X509Name` """ name = _lib.X509_NAME_dup(name._name) self._name = _ffi.gc(name, _lib.X509_NAME_free) def __setattr__(self, name, value): if name.startswith('_'): return super(X509Name, self).__setattr__(name, value) # Note: we really do not want str subclasses here, so we do not use # isinstance. if type(name) is not str: raise TypeError("attribute name must be string, not '%.200s'" % ( type(value).__name__,)) nid = _lib.OBJ_txt2nid(_byte_string(name)) if nid == _lib.NID_undef: try: _raise_current_error() except Error: pass raise AttributeError("No such attribute") # If there's an old entry for this NID, remove it for i in range(_lib.X509_NAME_entry_count(self._name)): ent = _lib.X509_NAME_get_entry(self._name, i) ent_obj = _lib.X509_NAME_ENTRY_get_object(ent) ent_nid = _lib.OBJ_obj2nid(ent_obj) if nid == ent_nid: ent = _lib.X509_NAME_delete_entry(self._name, i) _lib.X509_NAME_ENTRY_free(ent) break if isinstance(value, _text_type): value = value.encode('utf-8') add_result = _lib.X509_NAME_add_entry_by_NID( self._name, nid, _lib.MBSTRING_UTF8, value, -1, -1, 0) if not add_result: _raise_current_error() def __getattr__(self, name): """ Find attribute. An X509Name object has the following attributes: countryName (alias C), stateOrProvince (alias ST), locality (alias L), organization (alias O), organizationalUnit (alias OU), commonName (alias CN) and more... """ nid = _lib.OBJ_txt2nid(_byte_string(name)) if nid == _lib.NID_undef: # This is a bit weird. OBJ_txt2nid indicated failure, but it seems # a lower level function, a2d_ASN1_OBJECT, also feels the need to # push something onto the error queue. If we don't clean that up # now, someone else will bump into it later and be quite confused. # See lp#314814. try: _raise_current_error() except Error: pass return super(X509Name, self).__getattr__(name) entry_index = _lib.X509_NAME_get_index_by_NID(self._name, nid, -1) if entry_index == -1: return None entry = _lib.X509_NAME_get_entry(self._name, entry_index) data = _lib.X509_NAME_ENTRY_get_data(entry) result_buffer = _ffi.new("unsigned char**") data_length = _lib.ASN1_STRING_to_UTF8(result_buffer, data) _openssl_assert(data_length >= 0) try: result = _ffi.buffer( result_buffer[0], data_length )[:].decode('utf-8') finally: # XXX untested _lib.OPENSSL_free(result_buffer[0]) return result def _cmp(op): def f(self, other): if not isinstance(other, X509Name): return NotImplemented result = _lib.X509_NAME_cmp(self._name, other._name) return op(result, 0) return f __eq__ = _cmp(__eq__) __ne__ = _cmp(__ne__) __lt__ = _cmp(__lt__) __le__ = _cmp(__le__) __gt__ = _cmp(__gt__) __ge__ = _cmp(__ge__) def __repr__(self): """ String representation of an X509Name """ result_buffer = _ffi.new("char[]", 512) format_result = _lib.X509_NAME_oneline( self._name, result_buffer, len(result_buffer)) _openssl_assert(format_result != _ffi.NULL) return "" % ( _native(_ffi.string(result_buffer)),) def hash(self): """ Return an integer representation of the first four bytes of the MD5 digest of the DER representation of the name. This is the Python equivalent of OpenSSL's ``X509_NAME_hash``. :return: The (integer) hash of this name. :rtype: :py:class:`int` """ return _lib.X509_NAME_hash(self._name) def der(self): """ Return the DER encoding of this name. :return: The DER encoded form of this name. :rtype: :py:class:`bytes` """ result_buffer = _ffi.new('unsigned char**') encode_result = _lib.i2d_X509_NAME(self._name, result_buffer) _openssl_assert(encode_result >= 0) string_result = _ffi.buffer(result_buffer[0], encode_result)[:] _lib.OPENSSL_free(result_buffer[0]) return string_result def get_components(self): """ Returns the components of this name, as a sequence of 2-tuples. :return: The components of this name. :rtype: :py:class:`list` of ``name, value`` tuples. """ result = [] for i in range(_lib.X509_NAME_entry_count(self._name)): ent = _lib.X509_NAME_get_entry(self._name, i) fname = _lib.X509_NAME_ENTRY_get_object(ent) fval = _lib.X509_NAME_ENTRY_get_data(ent) nid = _lib.OBJ_obj2nid(fname) name = _lib.OBJ_nid2sn(nid) # ffi.string does not handle strings containing NULL bytes # (which may have been generated by old, broken software) value = _ffi.buffer(_lib.ASN1_STRING_data(fval), _lib.ASN1_STRING_length(fval))[:] result.append((_ffi.string(name), value)) return result X509NameType = deprecated( X509Name, __name__, "X509NameType has been deprecated, use X509Name instead", DeprecationWarning ) class X509Extension(object): """ An X.509 v3 certificate extension. """ def __init__(self, type_name, critical, value, subject=None, issuer=None): """ Initializes an X509 extension. :param type_name: The name of the type of extension_ to create. :type type_name: :py:data:`bytes` :param bool critical: A flag indicating whether this is a critical extension. :param value: The value of the extension. :type value: :py:data:`bytes` :param subject: Optional X509 certificate to use as subject. :type subject: :py:class:`X509` :param issuer: Optional X509 certificate to use as issuer. :type issuer: :py:class:`X509` .. _extension: https://www.openssl.org/docs/manmaster/man5/ x509v3_config.html#STANDARD-EXTENSIONS """ ctx = _ffi.new("X509V3_CTX*") # A context is necessary for any extension which uses the r2i # conversion method. That is, X509V3_EXT_nconf may segfault if passed # a NULL ctx. Start off by initializing most of the fields to NULL. _lib.X509V3_set_ctx(ctx, _ffi.NULL, _ffi.NULL, _ffi.NULL, _ffi.NULL, 0) # We have no configuration database - but perhaps we should (some # extensions may require it). _lib.X509V3_set_ctx_nodb(ctx) # Initialize the subject and issuer, if appropriate. ctx is a local, # and as far as I can tell none of the X509V3_* APIs invoked here steal # any references, so no need to mess with reference counts or # duplicates. if issuer is not None: if not isinstance(issuer, X509): raise TypeError("issuer must be an X509 instance") ctx.issuer_cert = issuer._x509 if subject is not None: if not isinstance(subject, X509): raise TypeError("subject must be an X509 instance") ctx.subject_cert = subject._x509 if critical: # There are other OpenSSL APIs which would let us pass in critical # separately, but they're harder to use, and since value is already # a pile of crappy junk smuggling a ton of utterly important # structured data, what's the point of trying to avoid nasty stuff # with strings? (However, X509V3_EXT_i2d in particular seems like # it would be a better API to invoke. I do not know where to get # the ext_struc it desires for its last parameter, though.) value = b"critical," + value extension = _lib.X509V3_EXT_nconf(_ffi.NULL, ctx, type_name, value) if extension == _ffi.NULL: _raise_current_error() self._extension = _ffi.gc(extension, _lib.X509_EXTENSION_free) @property def _nid(self): return _lib.OBJ_obj2nid( _lib.X509_EXTENSION_get_object(self._extension) ) _prefixes = { _lib.GEN_EMAIL: "email", _lib.GEN_DNS: "DNS", _lib.GEN_URI: "URI", } def _subjectAltNameString(self): names = _ffi.cast( "GENERAL_NAMES*", _lib.X509V3_EXT_d2i(self._extension) ) names = _ffi.gc(names, _lib.GENERAL_NAMES_free) parts = [] for i in range(_lib.sk_GENERAL_NAME_num(names)): name = _lib.sk_GENERAL_NAME_value(names, i) try: label = self._prefixes[name.type] except KeyError: bio = _new_mem_buf() _lib.GENERAL_NAME_print(bio, name) parts.append(_native(_bio_to_string(bio))) else: value = _native( _ffi.buffer(name.d.ia5.data, name.d.ia5.length)[:]) parts.append(label + ":" + value) return ", ".join(parts) def __str__(self): """ :return: a nice text representation of the extension """ if _lib.NID_subject_alt_name == self._nid: return self._subjectAltNameString() bio = _new_mem_buf() print_result = _lib.X509V3_EXT_print(bio, self._extension, 0, 0) _openssl_assert(print_result != 0) return _native(_bio_to_string(bio)) def get_critical(self): """ Returns the critical field of this X.509 extension. :return: The critical field. """ return _lib.X509_EXTENSION_get_critical(self._extension) def get_short_name(self): """ Returns the short type name of this X.509 extension. The result is a byte string such as :py:const:`b"basicConstraints"`. :return: The short type name. :rtype: :py:data:`bytes` .. versionadded:: 0.12 """ obj = _lib.X509_EXTENSION_get_object(self._extension) nid = _lib.OBJ_obj2nid(obj) return _ffi.string(_lib.OBJ_nid2sn(nid)) def get_data(self): """ Returns the data of the X509 extension, encoded as ASN.1. :return: The ASN.1 encoded data of this X509 extension. :rtype: :py:data:`bytes` .. versionadded:: 0.12 """ octet_result = _lib.X509_EXTENSION_get_data(self._extension) string_result = _ffi.cast('ASN1_STRING*', octet_result) char_result = _lib.ASN1_STRING_data(string_result) result_length = _lib.ASN1_STRING_length(string_result) return _ffi.buffer(char_result, result_length)[:] X509ExtensionType = deprecated( X509Extension, __name__, "X509ExtensionType has been deprecated, use X509Extension instead", DeprecationWarning ) class X509Req(object): """ An X.509 certificate signing requests. """ def __init__(self): req = _lib.X509_REQ_new() self._req = _ffi.gc(req, _lib.X509_REQ_free) # Default to version 0. self.set_version(0) def to_cryptography(self): """ Export as a ``cryptography`` certificate signing request. :rtype: ``cryptography.x509.CertificateSigningRequest`` .. versionadded:: 17.1.0 """ from cryptography.hazmat.backends.openssl.x509 import ( _CertificateSigningRequest ) backend = _get_backend() return _CertificateSigningRequest(backend, self._req) @classmethod def from_cryptography(cls, crypto_req): """ Construct based on a ``cryptography`` *crypto_req*. :param crypto_req: A ``cryptography`` X.509 certificate signing request :type crypto_req: ``cryptography.x509.CertificateSigningRequest`` :rtype: X509Req .. versionadded:: 17.1.0 """ if not isinstance(crypto_req, x509.CertificateSigningRequest): raise TypeError("Must be a certificate signing request") req = cls() req._req = crypto_req._x509_req return req def set_pubkey(self, pkey): """ Set the public key of the certificate signing request. :param pkey: The public key to use. :type pkey: :py:class:`PKey` :return: ``None`` """ set_result = _lib.X509_REQ_set_pubkey(self._req, pkey._pkey) _openssl_assert(set_result == 1) def get_pubkey(self): """ Get the public key of the certificate signing request. :return: The public key. :rtype: :py:class:`PKey` """ pkey = PKey.__new__(PKey) pkey._pkey = _lib.X509_REQ_get_pubkey(self._req) _openssl_assert(pkey._pkey != _ffi.NULL) pkey._pkey = _ffi.gc(pkey._pkey, _lib.EVP_PKEY_free) pkey._only_public = True return pkey def set_version(self, version): """ Set the version subfield (RFC 2459, section 4.1.2.1) of the certificate request. :param int version: The version number. :return: ``None`` """ set_result = _lib.X509_REQ_set_version(self._req, version) _openssl_assert(set_result == 1) def get_version(self): """ Get the version subfield (RFC 2459, section 4.1.2.1) of the certificate request. :return: The value of the version subfield. :rtype: :py:class:`int` """ return _lib.X509_REQ_get_version(self._req) def get_subject(self): """ Return the subject of this certificate signing request. This creates a new :class:`X509Name` that wraps the underlying subject name field on the certificate signing request. Modifying it will modify the underlying signing request, and will have the effect of modifying any other :class:`X509Name` that refers to this subject. :return: The subject of this certificate signing request. :rtype: :class:`X509Name` """ name = X509Name.__new__(X509Name) name._name = _lib.X509_REQ_get_subject_name(self._req) _openssl_assert(name._name != _ffi.NULL) # The name is owned by the X509Req structure. As long as the X509Name # Python object is alive, keep the X509Req Python object alive. name._owner = self return name def add_extensions(self, extensions): """ Add extensions to the certificate signing request. :param extensions: The X.509 extensions to add. :type extensions: iterable of :py:class:`X509Extension` :return: ``None`` """ stack = _lib.sk_X509_EXTENSION_new_null() _openssl_assert(stack != _ffi.NULL) stack = _ffi.gc(stack, _lib.sk_X509_EXTENSION_free) for ext in extensions: if not isinstance(ext, X509Extension): raise ValueError("One of the elements is not an X509Extension") # TODO push can fail (here and elsewhere) _lib.sk_X509_EXTENSION_push(stack, ext._extension) add_result = _lib.X509_REQ_add_extensions(self._req, stack) _openssl_assert(add_result == 1) def get_extensions(self): """ Get X.509 extensions in the certificate signing request. :return: The X.509 extensions in this request. :rtype: :py:class:`list` of :py:class:`X509Extension` objects. .. versionadded:: 0.15 """ exts = [] native_exts_obj = _lib.X509_REQ_get_extensions(self._req) for i in range(_lib.sk_X509_EXTENSION_num(native_exts_obj)): ext = X509Extension.__new__(X509Extension) ext._extension = _lib.sk_X509_EXTENSION_value(native_exts_obj, i) exts.append(ext) return exts def sign(self, pkey, digest): """ Sign the certificate signing request with this key and digest type. :param pkey: The key pair to sign with. :type pkey: :py:class:`PKey` :param digest: The name of the message digest to use for the signature, e.g. :py:data:`b"sha256"`. :type digest: :py:class:`bytes` :return: ``None`` """ if pkey._only_public: raise ValueError("Key has only public part") if not pkey._initialized: raise ValueError("Key is uninitialized") digest_obj = _lib.EVP_get_digestbyname(_byte_string(digest)) if digest_obj == _ffi.NULL: raise ValueError("No such digest method") sign_result = _lib.X509_REQ_sign(self._req, pkey._pkey, digest_obj) _openssl_assert(sign_result > 0) def verify(self, pkey): """ Verifies the signature on this certificate signing request. :param PKey key: A public key. :return: ``True`` if the signature is correct. :rtype: bool :raises OpenSSL.crypto.Error: If the signature is invalid or there is a problem verifying the signature. """ if not isinstance(pkey, PKey): raise TypeError("pkey must be a PKey instance") result = _lib.X509_REQ_verify(self._req, pkey._pkey) if result <= 0: _raise_current_error() return result X509ReqType = deprecated( X509Req, __name__, "X509ReqType has been deprecated, use X509Req instead", DeprecationWarning ) class X509(object): """ An X.509 certificate. """ def __init__(self): x509 = _lib.X509_new() _openssl_assert(x509 != _ffi.NULL) self._x509 = _ffi.gc(x509, _lib.X509_free) self._issuer_invalidator = _X509NameInvalidator() self._subject_invalidator = _X509NameInvalidator() @classmethod def _from_raw_x509_ptr(cls, x509): cert = cls.__new__(cls) cert._x509 = _ffi.gc(x509, _lib.X509_free) cert._issuer_invalidator = _X509NameInvalidator() cert._subject_invalidator = _X509NameInvalidator() return cert def to_cryptography(self): """ Export as a ``cryptography`` certificate. :rtype: ``cryptography.x509.Certificate`` .. versionadded:: 17.1.0 """ from cryptography.hazmat.backends.openssl.x509 import _Certificate backend = _get_backend() return _Certificate(backend, self._x509) @classmethod def from_cryptography(cls, crypto_cert): """ Construct based on a ``cryptography`` *crypto_cert*. :param crypto_key: A ``cryptography`` X.509 certificate. :type crypto_key: ``cryptography.x509.Certificate`` :rtype: X509 .. versionadded:: 17.1.0 """ if not isinstance(crypto_cert, x509.Certificate): raise TypeError("Must be a certificate") cert = cls() cert._x509 = crypto_cert._x509 return cert def set_version(self, version): """ Set the version number of the certificate. Note that the version value is zero-based, eg. a value of 0 is V1. :param version: The version number of the certificate. :type version: :py:class:`int` :return: ``None`` """ if not isinstance(version, int): raise TypeError("version must be an integer") _lib.X509_set_version(self._x509, version) def get_version(self): """ Return the version number of the certificate. :return: The version number of the certificate. :rtype: :py:class:`int` """ return _lib.X509_get_version(self._x509) def get_pubkey(self): """ Get the public key of the certificate. :return: The public key. :rtype: :py:class:`PKey` """ pkey = PKey.__new__(PKey) pkey._pkey = _lib.X509_get_pubkey(self._x509) if pkey._pkey == _ffi.NULL: _raise_current_error() pkey._pkey = _ffi.gc(pkey._pkey, _lib.EVP_PKEY_free) pkey._only_public = True return pkey def set_pubkey(self, pkey): """ Set the public key of the certificate. :param pkey: The public key. :type pkey: :py:class:`PKey` :return: :py:data:`None` """ if not isinstance(pkey, PKey): raise TypeError("pkey must be a PKey instance") set_result = _lib.X509_set_pubkey(self._x509, pkey._pkey) _openssl_assert(set_result == 1) def sign(self, pkey, digest): """ Sign the certificate with this key and digest type. :param pkey: The key to sign with. :type pkey: :py:class:`PKey` :param digest: The name of the message digest to use. :type digest: :py:class:`bytes` :return: :py:data:`None` """ if not isinstance(pkey, PKey): raise TypeError("pkey must be a PKey instance") if pkey._only_public: raise ValueError("Key only has public part") if not pkey._initialized: raise ValueError("Key is uninitialized") evp_md = _lib.EVP_get_digestbyname(_byte_string(digest)) if evp_md == _ffi.NULL: raise ValueError("No such digest method") sign_result = _lib.X509_sign(self._x509, pkey._pkey, evp_md) _openssl_assert(sign_result > 0) def get_signature_algorithm(self): """ Return the signature algorithm used in the certificate. :return: The name of the algorithm. :rtype: :py:class:`bytes` :raises ValueError: If the signature algorithm is undefined. .. versionadded:: 0.13 """ algor = _lib.X509_get0_tbs_sigalg(self._x509) nid = _lib.OBJ_obj2nid(algor.algorithm) if nid == _lib.NID_undef: raise ValueError("Undefined signature algorithm") return _ffi.string(_lib.OBJ_nid2ln(nid)) def digest(self, digest_name): """ Return the digest of the X509 object. :param digest_name: The name of the digest algorithm to use. :type digest_name: :py:class:`bytes` :return: The digest of the object, formatted as :py:const:`b":"`-delimited hex pairs. :rtype: :py:class:`bytes` """ digest = _lib.EVP_get_digestbyname(_byte_string(digest_name)) if digest == _ffi.NULL: raise ValueError("No such digest method") result_buffer = _ffi.new("unsigned char[]", _lib.EVP_MAX_MD_SIZE) result_length = _ffi.new("unsigned int[]", 1) result_length[0] = len(result_buffer) digest_result = _lib.X509_digest( self._x509, digest, result_buffer, result_length) _openssl_assert(digest_result == 1) return b":".join([ b16encode(ch).upper() for ch in _ffi.buffer(result_buffer, result_length[0])]) def subject_name_hash(self): """ Return the hash of the X509 subject. :return: The hash of the subject. :rtype: :py:class:`bytes` """ return _lib.X509_subject_name_hash(self._x509) def set_serial_number(self, serial): """ Set the serial number of the certificate. :param serial: The new serial number. :type serial: :py:class:`int` :return: :py:data`None` """ if not isinstance(serial, _integer_types): raise TypeError("serial must be an integer") hex_serial = hex(serial)[2:] if not isinstance(hex_serial, bytes): hex_serial = hex_serial.encode('ascii') bignum_serial = _ffi.new("BIGNUM**") # BN_hex2bn stores the result in &bignum. Unless it doesn't feel like # it. If bignum is still NULL after this call, then the return value # is actually the result. I hope. -exarkun small_serial = _lib.BN_hex2bn(bignum_serial, hex_serial) if bignum_serial[0] == _ffi.NULL: set_result = _lib.ASN1_INTEGER_set( _lib.X509_get_serialNumber(self._x509), small_serial) if set_result: # TODO Not tested _raise_current_error() else: asn1_serial = _lib.BN_to_ASN1_INTEGER(bignum_serial[0], _ffi.NULL) _lib.BN_free(bignum_serial[0]) if asn1_serial == _ffi.NULL: # TODO Not tested _raise_current_error() asn1_serial = _ffi.gc(asn1_serial, _lib.ASN1_INTEGER_free) set_result = _lib.X509_set_serialNumber(self._x509, asn1_serial) _openssl_assert(set_result == 1) def get_serial_number(self): """ Return the serial number of this certificate. :return: The serial number. :rtype: int """ asn1_serial = _lib.X509_get_serialNumber(self._x509) bignum_serial = _lib.ASN1_INTEGER_to_BN(asn1_serial, _ffi.NULL) try: hex_serial = _lib.BN_bn2hex(bignum_serial) try: hexstring_serial = _ffi.string(hex_serial) serial = int(hexstring_serial, 16) return serial finally: _lib.OPENSSL_free(hex_serial) finally: _lib.BN_free(bignum_serial) def gmtime_adj_notAfter(self, amount): """ Adjust the time stamp on which the certificate stops being valid. :param int amount: The number of seconds by which to adjust the timestamp. :return: ``None`` """ if not isinstance(amount, int): raise TypeError("amount must be an integer") notAfter = _lib.X509_get_notAfter(self._x509) _lib.X509_gmtime_adj(notAfter, amount) def gmtime_adj_notBefore(self, amount): """ Adjust the timestamp on which the certificate starts being valid. :param amount: The number of seconds by which to adjust the timestamp. :return: ``None`` """ if not isinstance(amount, int): raise TypeError("amount must be an integer") notBefore = _lib.X509_get_notBefore(self._x509) _lib.X509_gmtime_adj(notBefore, amount) def has_expired(self): """ Check whether the certificate has expired. :return: ``True`` if the certificate has expired, ``False`` otherwise. :rtype: bool """ time_string = _native(self.get_notAfter()) not_after = datetime.datetime.strptime(time_string, "%Y%m%d%H%M%SZ") return not_after < datetime.datetime.utcnow() def _get_boundary_time(self, which): return _get_asn1_time(which(self._x509)) def get_notBefore(self): """ Get the timestamp at which the certificate starts being valid. The timestamp is formatted as an ASN.1 TIME:: YYYYMMDDhhmmssZ :return: A timestamp string, or ``None`` if there is none. :rtype: bytes or NoneType """ return self._get_boundary_time(_lib.X509_get_notBefore) def _set_boundary_time(self, which, when): return _set_asn1_time(which(self._x509), when) def set_notBefore(self, when): """ Set the timestamp at which the certificate starts being valid. The timestamp is formatted as an ASN.1 TIME:: YYYYMMDDhhmmssZ :param bytes when: A timestamp string. :return: ``None`` """ return self._set_boundary_time(_lib.X509_get_notBefore, when) def get_notAfter(self): """ Get the timestamp at which the certificate stops being valid. The timestamp is formatted as an ASN.1 TIME:: YYYYMMDDhhmmssZ :return: A timestamp string, or ``None`` if there is none. :rtype: bytes or NoneType """ return self._get_boundary_time(_lib.X509_get_notAfter) def set_notAfter(self, when): """ Set the timestamp at which the certificate stops being valid. The timestamp is formatted as an ASN.1 TIME:: YYYYMMDDhhmmssZ :param bytes when: A timestamp string. :return: ``None`` """ return self._set_boundary_time(_lib.X509_get_notAfter, when) def _get_name(self, which): name = X509Name.__new__(X509Name) name._name = which(self._x509) _openssl_assert(name._name != _ffi.NULL) # The name is owned by the X509 structure. As long as the X509Name # Python object is alive, keep the X509 Python object alive. name._owner = self return name def _set_name(self, which, name): if not isinstance(name, X509Name): raise TypeError("name must be an X509Name") set_result = which(self._x509, name._name) _openssl_assert(set_result == 1) def get_issuer(self): """ Return the issuer of this certificate. This creates a new :class:`X509Name` that wraps the underlying issuer name field on the certificate. Modifying it will modify the underlying certificate, and will have the effect of modifying any other :class:`X509Name` that refers to this issuer. :return: The issuer of this certificate. :rtype: :class:`X509Name` """ name = self._get_name(_lib.X509_get_issuer_name) self._issuer_invalidator.add(name) return name def set_issuer(self, issuer): """ Set the issuer of this certificate. :param issuer: The issuer. :type issuer: :py:class:`X509Name` :return: ``None`` """ self._set_name(_lib.X509_set_issuer_name, issuer) self._issuer_invalidator.clear() def get_subject(self): """ Return the subject of this certificate. This creates a new :class:`X509Name` that wraps the underlying subject name field on the certificate. Modifying it will modify the underlying certificate, and will have the effect of modifying any other :class:`X509Name` that refers to this subject. :return: The subject of this certificate. :rtype: :class:`X509Name` """ name = self._get_name(_lib.X509_get_subject_name) self._subject_invalidator.add(name) return name def set_subject(self, subject): """ Set the subject of this certificate. :param subject: The subject. :type subject: :py:class:`X509Name` :return: ``None`` """ self._set_name(_lib.X509_set_subject_name, subject) self._subject_invalidator.clear() def get_extension_count(self): """ Get the number of extensions on this certificate. :return: The number of extensions. :rtype: :py:class:`int` .. versionadded:: 0.12 """ return _lib.X509_get_ext_count(self._x509) def add_extensions(self, extensions): """ Add extensions to the certificate. :param extensions: The extensions to add. :type extensions: An iterable of :py:class:`X509Extension` objects. :return: ``None`` """ for ext in extensions: if not isinstance(ext, X509Extension): raise ValueError("One of the elements is not an X509Extension") add_result = _lib.X509_add_ext(self._x509, ext._extension, -1) if not add_result: _raise_current_error() def get_extension(self, index): """ Get a specific extension of the certificate by index. Extensions on a certificate are kept in order. The index parameter selects which extension will be returned. :param int index: The index of the extension to retrieve. :return: The extension at the specified index. :rtype: :py:class:`X509Extension` :raises IndexError: If the extension index was out of bounds. .. versionadded:: 0.12 """ ext = X509Extension.__new__(X509Extension) ext._extension = _lib.X509_get_ext(self._x509, index) if ext._extension == _ffi.NULL: raise IndexError("extension index out of bounds") extension = _lib.X509_EXTENSION_dup(ext._extension) ext._extension = _ffi.gc(extension, _lib.X509_EXTENSION_free) return ext X509Type = deprecated( X509, __name__, "X509Type has been deprecated, use X509 instead", DeprecationWarning ) class X509StoreFlags(object): """ Flags for X509 verification, used to change the behavior of :class:`X509Store`. See `OpenSSL Verification Flags`_ for details. .. _OpenSSL Verification Flags: https://www.openssl.org/docs/manmaster/man3/X509_VERIFY_PARAM_set_flags.html """ CRL_CHECK = _lib.X509_V_FLAG_CRL_CHECK CRL_CHECK_ALL = _lib.X509_V_FLAG_CRL_CHECK_ALL IGNORE_CRITICAL = _lib.X509_V_FLAG_IGNORE_CRITICAL X509_STRICT = _lib.X509_V_FLAG_X509_STRICT ALLOW_PROXY_CERTS = _lib.X509_V_FLAG_ALLOW_PROXY_CERTS POLICY_CHECK = _lib.X509_V_FLAG_POLICY_CHECK EXPLICIT_POLICY = _lib.X509_V_FLAG_EXPLICIT_POLICY INHIBIT_MAP = _lib.X509_V_FLAG_INHIBIT_MAP NOTIFY_POLICY = _lib.X509_V_FLAG_NOTIFY_POLICY CHECK_SS_SIGNATURE = _lib.X509_V_FLAG_CHECK_SS_SIGNATURE CB_ISSUER_CHECK = _lib.X509_V_FLAG_CB_ISSUER_CHECK class X509Store(object): """ An X.509 store. An X.509 store is used to describe a context in which to verify a certificate. A description of a context may include a set of certificates to trust, a set of certificate revocation lists, verification flags and more. An X.509 store, being only a description, cannot be used by itself to verify a certificate. To carry out the actual verification process, see :class:`X509StoreContext`. """ def __init__(self): store = _lib.X509_STORE_new() self._store = _ffi.gc(store, _lib.X509_STORE_free) def add_cert(self, cert): """ Adds a trusted certificate to this store. Adding a certificate with this method adds this certificate as a *trusted* certificate. :param X509 cert: The certificate to add to this store. :raises TypeError: If the certificate is not an :class:`X509`. :raises OpenSSL.crypto.Error: If OpenSSL was unhappy with your certificate. :return: ``None`` if the certificate was added successfully. """ if not isinstance(cert, X509): raise TypeError() # As of OpenSSL 1.1.0i adding the same cert to the store more than # once doesn't cause an error. Accordingly, this code now silences # the error for OpenSSL < 1.1.0i as well. if _lib.X509_STORE_add_cert(self._store, cert._x509) == 0: code = _lib.ERR_peek_error() err_reason = _lib.ERR_GET_REASON(code) _openssl_assert( err_reason == _lib.X509_R_CERT_ALREADY_IN_HASH_TABLE ) _lib.ERR_clear_error() def add_crl(self, crl): """ Add a certificate revocation list to this store. The certificate revocation lists added to a store will only be used if the associated flags are configured to check certificate revocation lists. .. versionadded:: 16.1.0 :param CRL crl: The certificate revocation list to add to this store. :return: ``None`` if the certificate revocation list was added successfully. """ _openssl_assert(_lib.X509_STORE_add_crl(self._store, crl._crl) != 0) def set_flags(self, flags): """ Set verification flags to this store. Verification flags can be combined by oring them together. .. note:: Setting a verification flag sometimes requires clients to add additional information to the store, otherwise a suitable error will be raised. For example, in setting flags to enable CRL checking a suitable CRL must be added to the store otherwise an error will be raised. .. versionadded:: 16.1.0 :param int flags: The verification flags to set on this store. See :class:`X509StoreFlags` for available constants. :return: ``None`` if the verification flags were successfully set. """ _openssl_assert(_lib.X509_STORE_set_flags(self._store, flags) != 0) def set_time(self, vfy_time): """ Set the time against which the certificates are verified. Normally the current time is used. .. note:: For example, you can determine if a certificate was valid at a given time. .. versionadded:: 17.0.0 :param datetime vfy_time: The verification time to set on this store. :return: ``None`` if the verification time was successfully set. """ param = _lib.X509_VERIFY_PARAM_new() param = _ffi.gc(param, _lib.X509_VERIFY_PARAM_free) _lib.X509_VERIFY_PARAM_set_time(param, int(vfy_time.strftime('%s'))) _openssl_assert(_lib.X509_STORE_set1_param(self._store, param) != 0) X509StoreType = deprecated( X509Store, __name__, "X509StoreType has been deprecated, use X509Store instead", DeprecationWarning ) class X509StoreContextError(Exception): """ An exception raised when an error occurred while verifying a certificate using `OpenSSL.X509StoreContext.verify_certificate`. :ivar certificate: The certificate which caused verificate failure. :type certificate: :class:`X509` """ def __init__(self, message, certificate): super(X509StoreContextError, self).__init__(message) self.certificate = certificate class X509StoreContext(object): """ An X.509 store context. An X.509 store context is used to carry out the actual verification process of a certificate in a described context. For describing such a context, see :class:`X509Store`. :ivar _store_ctx: The underlying X509_STORE_CTX structure used by this instance. It is dynamically allocated and automatically garbage collected. :ivar _store: See the ``store`` ``__init__`` parameter. :ivar _cert: See the ``certificate`` ``__init__`` parameter. :param X509Store store: The certificates which will be trusted for the purposes of any verifications. :param X509 certificate: The certificate to be verified. """ def __init__(self, store, certificate): store_ctx = _lib.X509_STORE_CTX_new() self._store_ctx = _ffi.gc(store_ctx, _lib.X509_STORE_CTX_free) self._store = store self._cert = certificate # Make the store context available for use after instantiating this # class by initializing it now. Per testing, subsequent calls to # :meth:`_init` have no adverse affect. self._init() def _init(self): """ Set up the store context for a subsequent verification operation. Calling this method more than once without first calling :meth:`_cleanup` will leak memory. """ ret = _lib.X509_STORE_CTX_init( self._store_ctx, self._store._store, self._cert._x509, _ffi.NULL ) if ret <= 0: _raise_current_error() def _cleanup(self): """ Internally cleans up the store context. The store context can then be reused with a new call to :meth:`_init`. """ _lib.X509_STORE_CTX_cleanup(self._store_ctx) def _exception_from_context(self): """ Convert an OpenSSL native context error failure into a Python exception. When a call to native OpenSSL X509_verify_cert fails, additional information about the failure can be obtained from the store context. """ errors = [ _lib.X509_STORE_CTX_get_error(self._store_ctx), _lib.X509_STORE_CTX_get_error_depth(self._store_ctx), _native(_ffi.string(_lib.X509_verify_cert_error_string( _lib.X509_STORE_CTX_get_error(self._store_ctx)))), ] # A context error should always be associated with a certificate, so we # expect this call to never return :class:`None`. _x509 = _lib.X509_STORE_CTX_get_current_cert(self._store_ctx) _cert = _lib.X509_dup(_x509) pycert = X509._from_raw_x509_ptr(_cert) return X509StoreContextError(errors, pycert) def set_store(self, store): """ Set the context's X.509 store. .. versionadded:: 0.15 :param X509Store store: The store description which will be used for the purposes of any *future* verifications. """ self._store = store def verify_certificate(self): """ Verify a certificate in a context. .. versionadded:: 0.15 :raises X509StoreContextError: If an error occurred when validating a certificate in the context. Sets ``certificate`` attribute to indicate which certificate caused the error. """ # Always re-initialize the store context in case # :meth:`verify_certificate` is called multiple times. # # :meth:`_init` is called in :meth:`__init__` so _cleanup is called # before _init to ensure memory is not leaked. self._cleanup() self._init() ret = _lib.X509_verify_cert(self._store_ctx) self._cleanup() if ret <= 0: raise self._exception_from_context() def load_certificate(type, buffer): """ Load a certificate (X509) from the string *buffer* encoded with the type *type*. :param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1) :param bytes buffer: The buffer the certificate is stored in :return: The X509 object """ if isinstance(buffer, _text_type): buffer = buffer.encode("ascii") bio = _new_mem_buf(buffer) if type == FILETYPE_PEM: x509 = _lib.PEM_read_bio_X509(bio, _ffi.NULL, _ffi.NULL, _ffi.NULL) elif type == FILETYPE_ASN1: x509 = _lib.d2i_X509_bio(bio, _ffi.NULL) else: raise ValueError( "type argument must be FILETYPE_PEM or FILETYPE_ASN1") if x509 == _ffi.NULL: _raise_current_error() return X509._from_raw_x509_ptr(x509) def dump_certificate(type, cert): """ Dump the certificate *cert* into a buffer string encoded with the type *type*. :param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1, or FILETYPE_TEXT) :param cert: The certificate to dump :return: The buffer with the dumped certificate in """ bio = _new_mem_buf() if type == FILETYPE_PEM: result_code = _lib.PEM_write_bio_X509(bio, cert._x509) elif type == FILETYPE_ASN1: result_code = _lib.i2d_X509_bio(bio, cert._x509) elif type == FILETYPE_TEXT: result_code = _lib.X509_print_ex(bio, cert._x509, 0, 0) else: raise ValueError( "type argument must be FILETYPE_PEM, FILETYPE_ASN1, or " "FILETYPE_TEXT") assert result_code == 1 return _bio_to_string(bio) def dump_publickey(type, pkey): """ Dump a public key to a buffer. :param type: The file type (one of :data:`FILETYPE_PEM` or :data:`FILETYPE_ASN1`). :param PKey pkey: The public key to dump :return: The buffer with the dumped key in it. :rtype: bytes """ bio = _new_mem_buf() if type == FILETYPE_PEM: write_bio = _lib.PEM_write_bio_PUBKEY elif type == FILETYPE_ASN1: write_bio = _lib.i2d_PUBKEY_bio else: raise ValueError("type argument must be FILETYPE_PEM or FILETYPE_ASN1") result_code = write_bio(bio, pkey._pkey) if result_code != 1: # pragma: no cover _raise_current_error() return _bio_to_string(bio) def dump_privatekey(type, pkey, cipher=None, passphrase=None): """ Dump the private key *pkey* into a buffer string encoded with the type *type*. Optionally (if *type* is :const:`FILETYPE_PEM`) encrypting it using *cipher* and *passphrase*. :param type: The file type (one of :const:`FILETYPE_PEM`, :const:`FILETYPE_ASN1`, or :const:`FILETYPE_TEXT`) :param PKey pkey: The PKey to dump :param cipher: (optional) if encrypted PEM format, the cipher to use :param passphrase: (optional) if encrypted PEM format, this can be either the passphrase to use, or a callback for providing the passphrase. :return: The buffer with the dumped key in :rtype: bytes """ bio = _new_mem_buf() if not isinstance(pkey, PKey): raise TypeError("pkey must be a PKey") if cipher is not None: if passphrase is None: raise TypeError( "if a value is given for cipher " "one must also be given for passphrase") cipher_obj = _lib.EVP_get_cipherbyname(_byte_string(cipher)) if cipher_obj == _ffi.NULL: raise ValueError("Invalid cipher name") else: cipher_obj = _ffi.NULL helper = _PassphraseHelper(type, passphrase) if type == FILETYPE_PEM: result_code = _lib.PEM_write_bio_PrivateKey( bio, pkey._pkey, cipher_obj, _ffi.NULL, 0, helper.callback, helper.callback_args) helper.raise_if_problem() elif type == FILETYPE_ASN1: result_code = _lib.i2d_PrivateKey_bio(bio, pkey._pkey) elif type == FILETYPE_TEXT: if _lib.EVP_PKEY_id(pkey._pkey) != _lib.EVP_PKEY_RSA: raise TypeError("Only RSA keys are supported for FILETYPE_TEXT") rsa = _ffi.gc( _lib.EVP_PKEY_get1_RSA(pkey._pkey), _lib.RSA_free ) result_code = _lib.RSA_print(bio, rsa, 0) else: raise ValueError( "type argument must be FILETYPE_PEM, FILETYPE_ASN1, or " "FILETYPE_TEXT") _openssl_assert(result_code != 0) return _bio_to_string(bio) class Revoked(object): """ A certificate revocation. """ # https://www.openssl.org/docs/manmaster/man5/x509v3_config.html#CRL-distribution-points # which differs from crl_reasons of crypto/x509v3/v3_enum.c that matches # OCSP_crl_reason_str. We use the latter, just like the command line # program. _crl_reasons = [ b"unspecified", b"keyCompromise", b"CACompromise", b"affiliationChanged", b"superseded", b"cessationOfOperation", b"certificateHold", # b"removeFromCRL", ] def __init__(self): revoked = _lib.X509_REVOKED_new() self._revoked = _ffi.gc(revoked, _lib.X509_REVOKED_free) def set_serial(self, hex_str): """ Set the serial number. The serial number is formatted as a hexadecimal number encoded in ASCII. :param bytes hex_str: The new serial number. :return: ``None`` """ bignum_serial = _ffi.gc(_lib.BN_new(), _lib.BN_free) bignum_ptr = _ffi.new("BIGNUM**") bignum_ptr[0] = bignum_serial bn_result = _lib.BN_hex2bn(bignum_ptr, hex_str) if not bn_result: raise ValueError("bad hex string") asn1_serial = _ffi.gc( _lib.BN_to_ASN1_INTEGER(bignum_serial, _ffi.NULL), _lib.ASN1_INTEGER_free) _lib.X509_REVOKED_set_serialNumber(self._revoked, asn1_serial) def get_serial(self): """ Get the serial number. The serial number is formatted as a hexadecimal number encoded in ASCII. :return: The serial number. :rtype: bytes """ bio = _new_mem_buf() asn1_int = _lib.X509_REVOKED_get0_serialNumber(self._revoked) _openssl_assert(asn1_int != _ffi.NULL) result = _lib.i2a_ASN1_INTEGER(bio, asn1_int) _openssl_assert(result >= 0) return _bio_to_string(bio) def _delete_reason(self): for i in range(_lib.X509_REVOKED_get_ext_count(self._revoked)): ext = _lib.X509_REVOKED_get_ext(self._revoked, i) obj = _lib.X509_EXTENSION_get_object(ext) if _lib.OBJ_obj2nid(obj) == _lib.NID_crl_reason: _lib.X509_EXTENSION_free(ext) _lib.X509_REVOKED_delete_ext(self._revoked, i) break def set_reason(self, reason): """ Set the reason of this revocation. If :data:`reason` is ``None``, delete the reason instead. :param reason: The reason string. :type reason: :class:`bytes` or :class:`NoneType` :return: ``None`` .. seealso:: :meth:`all_reasons`, which gives you a list of all supported reasons which you might pass to this method. """ if reason is None: self._delete_reason() elif not isinstance(reason, bytes): raise TypeError("reason must be None or a byte string") else: reason = reason.lower().replace(b' ', b'') reason_code = [r.lower() for r in self._crl_reasons].index(reason) new_reason_ext = _lib.ASN1_ENUMERATED_new() _openssl_assert(new_reason_ext != _ffi.NULL) new_reason_ext = _ffi.gc(new_reason_ext, _lib.ASN1_ENUMERATED_free) set_result = _lib.ASN1_ENUMERATED_set(new_reason_ext, reason_code) _openssl_assert(set_result != _ffi.NULL) self._delete_reason() add_result = _lib.X509_REVOKED_add1_ext_i2d( self._revoked, _lib.NID_crl_reason, new_reason_ext, 0, 0) _openssl_assert(add_result == 1) def get_reason(self): """ Get the reason of this revocation. :return: The reason, or ``None`` if there is none. :rtype: bytes or NoneType .. seealso:: :meth:`all_reasons`, which gives you a list of all supported reasons this method might return. """ for i in range(_lib.X509_REVOKED_get_ext_count(self._revoked)): ext = _lib.X509_REVOKED_get_ext(self._revoked, i) obj = _lib.X509_EXTENSION_get_object(ext) if _lib.OBJ_obj2nid(obj) == _lib.NID_crl_reason: bio = _new_mem_buf() print_result = _lib.X509V3_EXT_print(bio, ext, 0, 0) if not print_result: print_result = _lib.M_ASN1_OCTET_STRING_print( bio, _lib.X509_EXTENSION_get_data(ext) ) _openssl_assert(print_result != 0) return _bio_to_string(bio) def all_reasons(self): """ Return a list of all the supported reason strings. This list is a copy; modifying it does not change the supported reason strings. :return: A list of reason strings. :rtype: :class:`list` of :class:`bytes` """ return self._crl_reasons[:] def set_rev_date(self, when): """ Set the revocation timestamp. :param bytes when: The timestamp of the revocation, as ASN.1 TIME. :return: ``None`` """ dt = _lib.X509_REVOKED_get0_revocationDate(self._revoked) return _set_asn1_time(dt, when) def get_rev_date(self): """ Get the revocation timestamp. :return: The timestamp of the revocation, as ASN.1 TIME. :rtype: bytes """ dt = _lib.X509_REVOKED_get0_revocationDate(self._revoked) return _get_asn1_time(dt) class CRL(object): """ A certificate revocation list. """ def __init__(self): crl = _lib.X509_CRL_new() self._crl = _ffi.gc(crl, _lib.X509_CRL_free) def to_cryptography(self): """ Export as a ``cryptography`` CRL. :rtype: ``cryptography.x509.CertificateRevocationList`` .. versionadded:: 17.1.0 """ from cryptography.hazmat.backends.openssl.x509 import ( _CertificateRevocationList ) backend = _get_backend() return _CertificateRevocationList(backend, self._crl) @classmethod def from_cryptography(cls, crypto_crl): """ Construct based on a ``cryptography`` *crypto_crl*. :param crypto_crl: A ``cryptography`` certificate revocation list :type crypto_crl: ``cryptography.x509.CertificateRevocationList`` :rtype: CRL .. versionadded:: 17.1.0 """ if not isinstance(crypto_crl, x509.CertificateRevocationList): raise TypeError("Must be a certificate revocation list") crl = cls() crl._crl = crypto_crl._x509_crl return crl def get_revoked(self): """ Return the revocations in this certificate revocation list. These revocations will be provided by value, not by reference. That means it's okay to mutate them: it won't affect this CRL. :return: The revocations in this CRL. :rtype: :class:`tuple` of :class:`Revocation` """ results = [] revoked_stack = _lib.X509_CRL_get_REVOKED(self._crl) for i in range(_lib.sk_X509_REVOKED_num(revoked_stack)): revoked = _lib.sk_X509_REVOKED_value(revoked_stack, i) revoked_copy = _lib.Cryptography_X509_REVOKED_dup(revoked) pyrev = Revoked.__new__(Revoked) pyrev._revoked = _ffi.gc(revoked_copy, _lib.X509_REVOKED_free) results.append(pyrev) if results: return tuple(results) def add_revoked(self, revoked): """ Add a revoked (by value not reference) to the CRL structure This revocation will be added by value, not by reference. That means it's okay to mutate it after adding: it won't affect this CRL. :param Revoked revoked: The new revocation. :return: ``None`` """ copy = _lib.Cryptography_X509_REVOKED_dup(revoked._revoked) _openssl_assert(copy != _ffi.NULL) add_result = _lib.X509_CRL_add0_revoked(self._crl, copy) _openssl_assert(add_result != 0) def get_issuer(self): """ Get the CRL's issuer. .. versionadded:: 16.1.0 :rtype: X509Name """ _issuer = _lib.X509_NAME_dup(_lib.X509_CRL_get_issuer(self._crl)) _openssl_assert(_issuer != _ffi.NULL) _issuer = _ffi.gc(_issuer, _lib.X509_NAME_free) issuer = X509Name.__new__(X509Name) issuer._name = _issuer return issuer def set_version(self, version): """ Set the CRL version. .. versionadded:: 16.1.0 :param int version: The version of the CRL. :return: ``None`` """ _openssl_assert(_lib.X509_CRL_set_version(self._crl, version) != 0) def _set_boundary_time(self, which, when): return _set_asn1_time(which(self._crl), when) def set_lastUpdate(self, when): """ Set when the CRL was last updated. The timestamp is formatted as an ASN.1 TIME:: YYYYMMDDhhmmssZ .. versionadded:: 16.1.0 :param bytes when: A timestamp string. :return: ``None`` """ return self._set_boundary_time(_lib.X509_CRL_get_lastUpdate, when) def set_nextUpdate(self, when): """ Set when the CRL will next be udpated. The timestamp is formatted as an ASN.1 TIME:: YYYYMMDDhhmmssZ .. versionadded:: 16.1.0 :param bytes when: A timestamp string. :return: ``None`` """ return self._set_boundary_time(_lib.X509_CRL_get_nextUpdate, when) def sign(self, issuer_cert, issuer_key, digest): """ Sign the CRL. Signing a CRL enables clients to associate the CRL itself with an issuer. Before a CRL is meaningful to other OpenSSL functions, it must be signed by an issuer. This method implicitly sets the issuer's name based on the issuer certificate and private key used to sign the CRL. .. versionadded:: 16.1.0 :param X509 issuer_cert: The issuer's certificate. :param PKey issuer_key: The issuer's private key. :param bytes digest: The digest method to sign the CRL with. """ digest_obj = _lib.EVP_get_digestbyname(digest) _openssl_assert(digest_obj != _ffi.NULL) _lib.X509_CRL_set_issuer_name( self._crl, _lib.X509_get_subject_name(issuer_cert._x509)) _lib.X509_CRL_sort(self._crl) result = _lib.X509_CRL_sign(self._crl, issuer_key._pkey, digest_obj) _openssl_assert(result != 0) def export(self, cert, key, type=FILETYPE_PEM, days=100, digest=_UNSPECIFIED): """ Export the CRL as a string. :param X509 cert: The certificate used to sign the CRL. :param PKey key: The key used to sign the CRL. :param int type: The export format, either :data:`FILETYPE_PEM`, :data:`FILETYPE_ASN1`, or :data:`FILETYPE_TEXT`. :param int days: The number of days until the next update of this CRL. :param bytes digest: The name of the message digest to use (eg ``b"sha2566"``). :rtype: bytes """ if not isinstance(cert, X509): raise TypeError("cert must be an X509 instance") if not isinstance(key, PKey): raise TypeError("key must be a PKey instance") if not isinstance(type, int): raise TypeError("type must be an integer") if digest is _UNSPECIFIED: raise TypeError("digest must be provided") digest_obj = _lib.EVP_get_digestbyname(digest) if digest_obj == _ffi.NULL: raise ValueError("No such digest method") bio = _lib.BIO_new(_lib.BIO_s_mem()) _openssl_assert(bio != _ffi.NULL) # A scratch time object to give different values to different CRL # fields sometime = _lib.ASN1_TIME_new() _openssl_assert(sometime != _ffi.NULL) _lib.X509_gmtime_adj(sometime, 0) _lib.X509_CRL_set_lastUpdate(self._crl, sometime) _lib.X509_gmtime_adj(sometime, days * 24 * 60 * 60) _lib.X509_CRL_set_nextUpdate(self._crl, sometime) _lib.X509_CRL_set_issuer_name( self._crl, _lib.X509_get_subject_name(cert._x509) ) sign_result = _lib.X509_CRL_sign(self._crl, key._pkey, digest_obj) if not sign_result: _raise_current_error() return dump_crl(type, self) CRLType = deprecated( CRL, __name__, "CRLType has been deprecated, use CRL instead", DeprecationWarning ) class PKCS7(object): def type_is_signed(self): """ Check if this NID_pkcs7_signed object :return: True if the PKCS7 is of type signed """ return bool(_lib.PKCS7_type_is_signed(self._pkcs7)) def type_is_enveloped(self): """ Check if this NID_pkcs7_enveloped object :returns: True if the PKCS7 is of type enveloped """ return bool(_lib.PKCS7_type_is_enveloped(self._pkcs7)) def type_is_signedAndEnveloped(self): """ Check if this NID_pkcs7_signedAndEnveloped object :returns: True if the PKCS7 is of type signedAndEnveloped """ return bool(_lib.PKCS7_type_is_signedAndEnveloped(self._pkcs7)) def type_is_data(self): """ Check if this NID_pkcs7_data object :return: True if the PKCS7 is of type data """ return bool(_lib.PKCS7_type_is_data(self._pkcs7)) def get_type_name(self): """ Returns the type name of the PKCS7 structure :return: A string with the typename """ nid = _lib.OBJ_obj2nid(self._pkcs7.type) string_type = _lib.OBJ_nid2sn(nid) return _ffi.string(string_type) PKCS7Type = deprecated( PKCS7, __name__, "PKCS7Type has been deprecated, use PKCS7 instead", DeprecationWarning ) class PKCS12(object): """ A PKCS #12 archive. """ def __init__(self): self._pkey = None self._cert = None self._cacerts = None self._friendlyname = None def get_certificate(self): """ Get the certificate in the PKCS #12 structure. :return: The certificate, or :py:const:`None` if there is none. :rtype: :py:class:`X509` or :py:const:`None` """ return self._cert def set_certificate(self, cert): """ Set the certificate in the PKCS #12 structure. :param cert: The new certificate, or :py:const:`None` to unset it. :type cert: :py:class:`X509` or :py:const:`None` :return: ``None`` """ if not isinstance(cert, X509): raise TypeError("cert must be an X509 instance") self._cert = cert def get_privatekey(self): """ Get the private key in the PKCS #12 structure. :return: The private key, or :py:const:`None` if there is none. :rtype: :py:class:`PKey` """ return self._pkey def set_privatekey(self, pkey): """ Set the certificate portion of the PKCS #12 structure. :param pkey: The new private key, or :py:const:`None` to unset it. :type pkey: :py:class:`PKey` or :py:const:`None` :return: ``None`` """ if not isinstance(pkey, PKey): raise TypeError("pkey must be a PKey instance") self._pkey = pkey def get_ca_certificates(self): """ Get the CA certificates in the PKCS #12 structure. :return: A tuple with the CA certificates in the chain, or :py:const:`None` if there are none. :rtype: :py:class:`tuple` of :py:class:`X509` or :py:const:`None` """ if self._cacerts is not None: return tuple(self._cacerts) def set_ca_certificates(self, cacerts): """ Replace or set the CA certificates within the PKCS12 object. :param cacerts: The new CA certificates, or :py:const:`None` to unset them. :type cacerts: An iterable of :py:class:`X509` or :py:const:`None` :return: ``None`` """ if cacerts is None: self._cacerts = None else: cacerts = list(cacerts) for cert in cacerts: if not isinstance(cert, X509): raise TypeError( "iterable must only contain X509 instances" ) self._cacerts = cacerts def set_friendlyname(self, name): """ Set the friendly name in the PKCS #12 structure. :param name: The new friendly name, or :py:const:`None` to unset. :type name: :py:class:`bytes` or :py:const:`None` :return: ``None`` """ if name is None: self._friendlyname = None elif not isinstance(name, bytes): raise TypeError( "name must be a byte string or None (not %r)" % (name,) ) self._friendlyname = name def get_friendlyname(self): """ Get the friendly name in the PKCS# 12 structure. :returns: The friendly name, or :py:const:`None` if there is none. :rtype: :py:class:`bytes` or :py:const:`None` """ return self._friendlyname def export(self, passphrase=None, iter=2048, maciter=1): """ Dump a PKCS12 object as a string. For more information, see the :c:func:`PKCS12_create` man page. :param passphrase: The passphrase used to encrypt the structure. Unlike some other passphrase arguments, this *must* be a string, not a callback. :type passphrase: :py:data:`bytes` :param iter: Number of times to repeat the encryption step. :type iter: :py:data:`int` :param maciter: Number of times to repeat the MAC step. :type maciter: :py:data:`int` :return: The string representation of the PKCS #12 structure. :rtype: """ passphrase = _text_to_bytes_and_warn("passphrase", passphrase) if self._cacerts is None: cacerts = _ffi.NULL else: cacerts = _lib.sk_X509_new_null() cacerts = _ffi.gc(cacerts, _lib.sk_X509_free) for cert in self._cacerts: _lib.sk_X509_push(cacerts, cert._x509) if passphrase is None: passphrase = _ffi.NULL friendlyname = self._friendlyname if friendlyname is None: friendlyname = _ffi.NULL if self._pkey is None: pkey = _ffi.NULL else: pkey = self._pkey._pkey if self._cert is None: cert = _ffi.NULL else: cert = self._cert._x509 pkcs12 = _lib.PKCS12_create( passphrase, friendlyname, pkey, cert, cacerts, _lib.NID_pbe_WithSHA1And3_Key_TripleDES_CBC, _lib.NID_pbe_WithSHA1And3_Key_TripleDES_CBC, iter, maciter, 0) if pkcs12 == _ffi.NULL: _raise_current_error() pkcs12 = _ffi.gc(pkcs12, _lib.PKCS12_free) bio = _new_mem_buf() _lib.i2d_PKCS12_bio(bio, pkcs12) return _bio_to_string(bio) PKCS12Type = deprecated( PKCS12, __name__, "PKCS12Type has been deprecated, use PKCS12 instead", DeprecationWarning ) class NetscapeSPKI(object): """ A Netscape SPKI object. """ def __init__(self): spki = _lib.NETSCAPE_SPKI_new() self._spki = _ffi.gc(spki, _lib.NETSCAPE_SPKI_free) def sign(self, pkey, digest): """ Sign the certificate request with this key and digest type. :param pkey: The private key to sign with. :type pkey: :py:class:`PKey` :param digest: The message digest to use. :type digest: :py:class:`bytes` :return: ``None`` """ if pkey._only_public: raise ValueError("Key has only public part") if not pkey._initialized: raise ValueError("Key is uninitialized") digest_obj = _lib.EVP_get_digestbyname(_byte_string(digest)) if digest_obj == _ffi.NULL: raise ValueError("No such digest method") sign_result = _lib.NETSCAPE_SPKI_sign( self._spki, pkey._pkey, digest_obj ) _openssl_assert(sign_result > 0) def verify(self, key): """ Verifies a signature on a certificate request. :param PKey key: The public key that signature is supposedly from. :return: ``True`` if the signature is correct. :rtype: bool :raises OpenSSL.crypto.Error: If the signature is invalid, or there was a problem verifying the signature. """ answer = _lib.NETSCAPE_SPKI_verify(self._spki, key._pkey) if answer <= 0: _raise_current_error() return True def b64_encode(self): """ Generate a base64 encoded representation of this SPKI object. :return: The base64 encoded string. :rtype: :py:class:`bytes` """ encoded = _lib.NETSCAPE_SPKI_b64_encode(self._spki) result = _ffi.string(encoded) _lib.OPENSSL_free(encoded) return result def get_pubkey(self): """ Get the public key of this certificate. :return: The public key. :rtype: :py:class:`PKey` """ pkey = PKey.__new__(PKey) pkey._pkey = _lib.NETSCAPE_SPKI_get_pubkey(self._spki) _openssl_assert(pkey._pkey != _ffi.NULL) pkey._pkey = _ffi.gc(pkey._pkey, _lib.EVP_PKEY_free) pkey._only_public = True return pkey def set_pubkey(self, pkey): """ Set the public key of the certificate :param pkey: The public key :return: ``None`` """ set_result = _lib.NETSCAPE_SPKI_set_pubkey(self._spki, pkey._pkey) _openssl_assert(set_result == 1) NetscapeSPKIType = deprecated( NetscapeSPKI, __name__, "NetscapeSPKIType has been deprecated, use NetscapeSPKI instead", DeprecationWarning ) class _PassphraseHelper(object): def __init__(self, type, passphrase, more_args=False, truncate=False): if type != FILETYPE_PEM and passphrase is not None: raise ValueError( "only FILETYPE_PEM key format supports encryption" ) self._passphrase = passphrase self._more_args = more_args self._truncate = truncate self._problems = [] @property def callback(self): if self._passphrase is None: return _ffi.NULL elif isinstance(self._passphrase, bytes): return _ffi.NULL elif callable(self._passphrase): return _ffi.callback("pem_password_cb", self._read_passphrase) else: raise TypeError( "Last argument must be a byte string or a callable." ) @property def callback_args(self): if self._passphrase is None: return _ffi.NULL elif isinstance(self._passphrase, bytes): return self._passphrase elif callable(self._passphrase): return _ffi.NULL else: raise TypeError( "Last argument must be a byte string or a callable." ) def raise_if_problem(self, exceptionType=Error): if self._problems: # Flush the OpenSSL error queue try: _exception_from_error_queue(exceptionType) except exceptionType: pass raise self._problems.pop(0) def _read_passphrase(self, buf, size, rwflag, userdata): try: if self._more_args: result = self._passphrase(size, rwflag, userdata) else: result = self._passphrase(rwflag) if not isinstance(result, bytes): raise ValueError("String expected") if len(result) > size: if self._truncate: result = result[:size] else: raise ValueError( "passphrase returned by callback is too long" ) for i in range(len(result)): buf[i] = result[i:i + 1] return len(result) except Exception as e: self._problems.append(e) return 0 def load_publickey(type, buffer): """ Load a public key from a buffer. :param type: The file type (one of :data:`FILETYPE_PEM`, :data:`FILETYPE_ASN1`). :param buffer: The buffer the key is stored in. :type buffer: A Python string object, either unicode or bytestring. :return: The PKey object. :rtype: :class:`PKey` """ if isinstance(buffer, _text_type): buffer = buffer.encode("ascii") bio = _new_mem_buf(buffer) if type == FILETYPE_PEM: evp_pkey = _lib.PEM_read_bio_PUBKEY( bio, _ffi.NULL, _ffi.NULL, _ffi.NULL) elif type == FILETYPE_ASN1: evp_pkey = _lib.d2i_PUBKEY_bio(bio, _ffi.NULL) else: raise ValueError("type argument must be FILETYPE_PEM or FILETYPE_ASN1") if evp_pkey == _ffi.NULL: _raise_current_error() pkey = PKey.__new__(PKey) pkey._pkey = _ffi.gc(evp_pkey, _lib.EVP_PKEY_free) pkey._only_public = True return pkey def load_privatekey(type, buffer, passphrase=None): """ Load a private key (PKey) from the string *buffer* encoded with the type *type*. :param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1) :param buffer: The buffer the key is stored in :param passphrase: (optional) if encrypted PEM format, this can be either the passphrase to use, or a callback for providing the passphrase. :return: The PKey object """ if isinstance(buffer, _text_type): buffer = buffer.encode("ascii") bio = _new_mem_buf(buffer) helper = _PassphraseHelper(type, passphrase) if type == FILETYPE_PEM: evp_pkey = _lib.PEM_read_bio_PrivateKey( bio, _ffi.NULL, helper.callback, helper.callback_args) helper.raise_if_problem() elif type == FILETYPE_ASN1: evp_pkey = _lib.d2i_PrivateKey_bio(bio, _ffi.NULL) else: raise ValueError("type argument must be FILETYPE_PEM or FILETYPE_ASN1") if evp_pkey == _ffi.NULL: _raise_current_error() pkey = PKey.__new__(PKey) pkey._pkey = _ffi.gc(evp_pkey, _lib.EVP_PKEY_free) return pkey def dump_certificate_request(type, req): """ Dump the certificate request *req* into a buffer string encoded with the type *type*. :param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1) :param req: The certificate request to dump :return: The buffer with the dumped certificate request in """ bio = _new_mem_buf() if type == FILETYPE_PEM: result_code = _lib.PEM_write_bio_X509_REQ(bio, req._req) elif type == FILETYPE_ASN1: result_code = _lib.i2d_X509_REQ_bio(bio, req._req) elif type == FILETYPE_TEXT: result_code = _lib.X509_REQ_print_ex(bio, req._req, 0, 0) else: raise ValueError( "type argument must be FILETYPE_PEM, FILETYPE_ASN1, or " "FILETYPE_TEXT" ) _openssl_assert(result_code != 0) return _bio_to_string(bio) def load_certificate_request(type, buffer): """ Load a certificate request (X509Req) from the string *buffer* encoded with the type *type*. :param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1) :param buffer: The buffer the certificate request is stored in :return: The X509Req object """ if isinstance(buffer, _text_type): buffer = buffer.encode("ascii") bio = _new_mem_buf(buffer) if type == FILETYPE_PEM: req = _lib.PEM_read_bio_X509_REQ(bio, _ffi.NULL, _ffi.NULL, _ffi.NULL) elif type == FILETYPE_ASN1: req = _lib.d2i_X509_REQ_bio(bio, _ffi.NULL) else: raise ValueError("type argument must be FILETYPE_PEM or FILETYPE_ASN1") _openssl_assert(req != _ffi.NULL) x509req = X509Req.__new__(X509Req) x509req._req = _ffi.gc(req, _lib.X509_REQ_free) return x509req def sign(pkey, data, digest): """ Sign a data string using the given key and message digest. :param pkey: PKey to sign with :param data: data to be signed :param digest: message digest to use :return: signature .. versionadded:: 0.11 """ data = _text_to_bytes_and_warn("data", data) digest_obj = _lib.EVP_get_digestbyname(_byte_string(digest)) if digest_obj == _ffi.NULL: raise ValueError("No such digest method") md_ctx = _lib.Cryptography_EVP_MD_CTX_new() md_ctx = _ffi.gc(md_ctx, _lib.Cryptography_EVP_MD_CTX_free) _lib.EVP_SignInit(md_ctx, digest_obj) _lib.EVP_SignUpdate(md_ctx, data, len(data)) length = _lib.EVP_PKEY_size(pkey._pkey) _openssl_assert(length > 0) signature_buffer = _ffi.new("unsigned char[]", length) signature_length = _ffi.new("unsigned int *") final_result = _lib.EVP_SignFinal( md_ctx, signature_buffer, signature_length, pkey._pkey) _openssl_assert(final_result == 1) return _ffi.buffer(signature_buffer, signature_length[0])[:] def verify(cert, signature, data, digest): """ Verify the signature for a data string. :param cert: signing certificate (X509 object) corresponding to the private key which generated the signature. :param signature: signature returned by sign function :param data: data to be verified :param digest: message digest to use :return: ``None`` if the signature is correct, raise exception otherwise. .. versionadded:: 0.11 """ data = _text_to_bytes_and_warn("data", data) digest_obj = _lib.EVP_get_digestbyname(_byte_string(digest)) if digest_obj == _ffi.NULL: raise ValueError("No such digest method") pkey = _lib.X509_get_pubkey(cert._x509) _openssl_assert(pkey != _ffi.NULL) pkey = _ffi.gc(pkey, _lib.EVP_PKEY_free) md_ctx = _lib.Cryptography_EVP_MD_CTX_new() md_ctx = _ffi.gc(md_ctx, _lib.Cryptography_EVP_MD_CTX_free) _lib.EVP_VerifyInit(md_ctx, digest_obj) _lib.EVP_VerifyUpdate(md_ctx, data, len(data)) verify_result = _lib.EVP_VerifyFinal( md_ctx, signature, len(signature), pkey ) if verify_result != 1: _raise_current_error() def dump_crl(type, crl): """ Dump a certificate revocation list to a buffer. :param type: The file type (one of ``FILETYPE_PEM``, ``FILETYPE_ASN1``, or ``FILETYPE_TEXT``). :param CRL crl: The CRL to dump. :return: The buffer with the CRL. :rtype: bytes """ bio = _new_mem_buf() if type == FILETYPE_PEM: ret = _lib.PEM_write_bio_X509_CRL(bio, crl._crl) elif type == FILETYPE_ASN1: ret = _lib.i2d_X509_CRL_bio(bio, crl._crl) elif type == FILETYPE_TEXT: ret = _lib.X509_CRL_print(bio, crl._crl) else: raise ValueError( "type argument must be FILETYPE_PEM, FILETYPE_ASN1, or " "FILETYPE_TEXT") assert ret == 1 return _bio_to_string(bio) def load_crl(type, buffer): """ Load Certificate Revocation List (CRL) data from a string *buffer*. *buffer* encoded with the type *type*. :param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1) :param buffer: The buffer the CRL is stored in :return: The PKey object """ if isinstance(buffer, _text_type): buffer = buffer.encode("ascii") bio = _new_mem_buf(buffer) if type == FILETYPE_PEM: crl = _lib.PEM_read_bio_X509_CRL(bio, _ffi.NULL, _ffi.NULL, _ffi.NULL) elif type == FILETYPE_ASN1: crl = _lib.d2i_X509_CRL_bio(bio, _ffi.NULL) else: raise ValueError("type argument must be FILETYPE_PEM or FILETYPE_ASN1") if crl == _ffi.NULL: _raise_current_error() result = CRL.__new__(CRL) result._crl = _ffi.gc(crl, _lib.X509_CRL_free) return result def load_pkcs7_data(type, buffer): """ Load pkcs7 data from the string *buffer* encoded with the type *type*. :param type: The file type (one of FILETYPE_PEM or FILETYPE_ASN1) :param buffer: The buffer with the pkcs7 data. :return: The PKCS7 object """ if isinstance(buffer, _text_type): buffer = buffer.encode("ascii") bio = _new_mem_buf(buffer) if type == FILETYPE_PEM: pkcs7 = _lib.PEM_read_bio_PKCS7(bio, _ffi.NULL, _ffi.NULL, _ffi.NULL) elif type == FILETYPE_ASN1: pkcs7 = _lib.d2i_PKCS7_bio(bio, _ffi.NULL) else: raise ValueError("type argument must be FILETYPE_PEM or FILETYPE_ASN1") if pkcs7 == _ffi.NULL: _raise_current_error() pypkcs7 = PKCS7.__new__(PKCS7) pypkcs7._pkcs7 = _ffi.gc(pkcs7, _lib.PKCS7_free) return pypkcs7 def load_pkcs12(buffer, passphrase=None): """ Load pkcs12 data from the string *buffer*. If the pkcs12 structure is encrypted, a *passphrase* must be included. The MAC is always checked and thus required. See also the man page for the C function :py:func:`PKCS12_parse`. :param buffer: The buffer the certificate is stored in :param passphrase: (Optional) The password to decrypt the PKCS12 lump :returns: The PKCS12 object """ passphrase = _text_to_bytes_and_warn("passphrase", passphrase) if isinstance(buffer, _text_type): buffer = buffer.encode("ascii") bio = _new_mem_buf(buffer) # Use null passphrase if passphrase is None or empty string. With PKCS#12 # password based encryption no password and a zero length password are two # different things, but OpenSSL implementation will try both to figure out # which one works. if not passphrase: passphrase = _ffi.NULL p12 = _lib.d2i_PKCS12_bio(bio, _ffi.NULL) if p12 == _ffi.NULL: _raise_current_error() p12 = _ffi.gc(p12, _lib.PKCS12_free) pkey = _ffi.new("EVP_PKEY**") cert = _ffi.new("X509**") cacerts = _ffi.new("Cryptography_STACK_OF_X509**") parse_result = _lib.PKCS12_parse(p12, passphrase, pkey, cert, cacerts) if not parse_result: _raise_current_error() cacerts = _ffi.gc(cacerts[0], _lib.sk_X509_free) # openssl 1.0.0 sometimes leaves an X509_check_private_key error in the # queue for no particular reason. This error isn't interesting to anyone # outside this function. It's not even interesting to us. Get rid of it. try: _raise_current_error() except Error: pass if pkey[0] == _ffi.NULL: pykey = None else: pykey = PKey.__new__(PKey) pykey._pkey = _ffi.gc(pkey[0], _lib.EVP_PKEY_free) if cert[0] == _ffi.NULL: pycert = None friendlyname = None else: pycert = X509._from_raw_x509_ptr(cert[0]) friendlyname_length = _ffi.new("int*") friendlyname_buffer = _lib.X509_alias_get0( cert[0], friendlyname_length ) friendlyname = _ffi.buffer( friendlyname_buffer, friendlyname_length[0] )[:] if friendlyname_buffer == _ffi.NULL: friendlyname = None pycacerts = [] for i in range(_lib.sk_X509_num(cacerts)): x509 = _lib.sk_X509_value(cacerts, i) pycacert = X509._from_raw_x509_ptr(x509) pycacerts.append(pycacert) if not pycacerts: pycacerts = None pkcs12 = PKCS12.__new__(PKCS12) pkcs12._pkey = pykey pkcs12._cert = pycert pkcs12._cacerts = pycacerts pkcs12._friendlyname = friendlyname return pkcs12 # There are no direct unit tests for this initialization. It is tested # indirectly since it is necessary for functions like dump_privatekey when # using encryption. # # Thus OpenSSL.test.test_crypto.FunctionTests.test_dump_privatekey_passphrase # and some other similar tests may fail without this (though they may not if # the Python runtime has already done some initialization of the underlying # OpenSSL library (and is linked against the same one that cryptography is # using)). _lib.OpenSSL_add_all_algorithms() # This is similar but exercised mainly by exception_from_error_queue. It calls # both ERR_load_crypto_strings() and ERR_load_SSL_strings(). _lib.SSL_load_error_strings() # Set the default string mask to match OpenSSL upstream (since 2005) and # RFC5280 recommendations. _lib.ASN1_STRING_set_default_mask_asc(b'utf8only') ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/OpenSSL/debug.py ================================================ from __future__ import print_function import ssl import sys import OpenSSL.SSL import cffi import cryptography from . import version _env_info = u"""\ pyOpenSSL: {pyopenssl} cryptography: {cryptography} cffi: {cffi} cryptography's compiled against OpenSSL: {crypto_openssl_compile} cryptography's linked OpenSSL: {crypto_openssl_link} Pythons's OpenSSL: {python_openssl} Python executable: {python} Python version: {python_version} Platform: {platform} sys.path: {sys_path}""".format( pyopenssl=version.__version__, crypto_openssl_compile=OpenSSL._util.ffi.string( OpenSSL._util.lib.OPENSSL_VERSION_TEXT, ).decode("ascii"), crypto_openssl_link=OpenSSL.SSL.SSLeay_version( OpenSSL.SSL.SSLEAY_VERSION ).decode("ascii"), python_openssl=getattr(ssl, "OPENSSL_VERSION", "n/a"), cryptography=cryptography.__version__, cffi=cffi.__version__, python=sys.executable, python_version=sys.version, platform=sys.platform, sys_path=sys.path, ) if __name__ == "__main__": print(_env_info) ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/OpenSSL/rand.py ================================================ """ PRNG management routines, thin wrappers. """ from OpenSSL._util import lib as _lib def add(buffer, entropy): """ Mix bytes from *string* into the PRNG state. The *entropy* argument is (the lower bound of) an estimate of how much randomness is contained in *string*, measured in bytes. For more information, see e.g. :rfc:`1750`. This function is only relevant if you are forking Python processes and need to reseed the CSPRNG after fork. :param buffer: Buffer with random data. :param entropy: The entropy (in bytes) measurement of the buffer. :return: :obj:`None` """ if not isinstance(buffer, bytes): raise TypeError("buffer must be a byte string") if not isinstance(entropy, int): raise TypeError("entropy must be an integer") _lib.RAND_add(buffer, len(buffer), entropy) def status(): """ Check whether the PRNG has been seeded with enough data. :return: 1 if the PRNG is seeded enough, 0 otherwise. """ return _lib.RAND_status() ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/OpenSSL/tsafe.py ================================================ import warnings from threading import RLock as _RLock from OpenSSL import SSL as _ssl warnings.warn( "OpenSSL.tsafe is deprecated and will be removed", DeprecationWarning, stacklevel=3 ) class Connection: def __init__(self, *args): self._ssl_conn = _ssl.Connection(*args) self._lock = _RLock() for f in ('get_context', 'pending', 'send', 'write', 'recv', 'read', 'renegotiate', 'bind', 'listen', 'connect', 'accept', 'setblocking', 'fileno', 'shutdown', 'close', 'get_cipher_list', 'getpeername', 'getsockname', 'getsockopt', 'setsockopt', 'makefile', 'get_app_data', 'set_app_data', 'state_string', 'sock_shutdown', 'get_peer_certificate', 'get_peer_cert_chain', 'want_read', 'want_write', 'set_connect_state', 'set_accept_state', 'connect_ex', 'sendall'): exec("""def %s(self, *args): self._lock.acquire() try: return self._ssl_conn.%s(*args) finally: self._lock.release()\n""" % (f, f)) ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/OpenSSL/version.py ================================================ # Copyright (C) AB Strakt # Copyright (C) Jean-Paul Calderone # See LICENSE for details. """ pyOpenSSL - A simple wrapper around the OpenSSL library """ __all__ = [ "__author__", "__copyright__", "__email__", "__license__", "__summary__", "__title__", "__uri__", "__version__", ] __version__ = "19.0.0" __title__ = "pyOpenSSL" __uri__ = "https://pyopenssl.org/" __summary__ = "Python wrapper module around the OpenSSL library" __author__ = "The pyOpenSSL developers" __email__ = "cryptography-dev@python.org" __license__ = "Apache License, Version 2.0" __copyright__ = "Copyright 2001-2017 {0}".format(__author__) ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/PyDispatcher-2.0.5-py3.6.egg-info/PKG-INFO ================================================ Metadata-Version: 1.2 Name: PyDispatcher Version: 2.0.5 Summary: Multi-producer-multi-consumer signal dispatching mechanism Home-page: http://pydispatcher.sourceforge.net Author: Patrick K. O'Brien Author-email: pydispatcher-devel@lists.sourceforge.net Maintainer: Mike C. Fletcher Maintainer-email: pydispatcher-devel@lists.sourceforge.net License: BSD Description: Dispatcher mechanism for creating event models PyDispatcher is an enhanced version of Patrick K. O'Brien's original dispatcher.py module. It provides the Python programmer with a robust mechanism for event routing within various application contexts. Included in the package are the robustapply and saferef modules, which provide the ability to selectively apply arguments to callable objects and to reference instance methods using weak-references. Keywords: dispatcher,dispatch,pydispatch,event,signal,sender,receiver,propagate,multi-consumer,multi-producer,saferef,robustapply,apply Platform: Any Classifier: License :: OSI Approved :: BSD License Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 3 Classifier: Topic :: Software Development :: Libraries :: Python Modules Classifier: Intended Audience :: Developers ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/PyDispatcher-2.0.5-py3.6.egg-info/SOURCES.txt ================================================ MANIFEST.in license.txt setup.cfg setup.py PyDispatcher.egg-info/PKG-INFO PyDispatcher.egg-info/SOURCES.txt PyDispatcher.egg-info/dependency_links.txt PyDispatcher.egg-info/top_level.txt docs/index.html docs/images/greypinstripe.png docs/pydoc/__init__.py docs/pydoc/builddocs.py docs/pydoc/pydispatch.__init__.html docs/pydoc/pydispatch.dispatcher.html docs/pydoc/pydispatch.errors.html docs/pydoc/pydispatch.html docs/pydoc/pydispatch.robust.html docs/pydoc/pydispatch.robustapply.html docs/pydoc/pydispatch.saferef.html docs/pydoc/pydoc2.py docs/pydoc/weakref.html docs/style/sitestyle.css examples/__init__.py examples/extra_args.py examples/hello_messages.py examples/simple_sample.py pydispatch/__init__.py pydispatch/dispatcher.py pydispatch/errors.py pydispatch/robust.py pydispatch/robustapply.py pydispatch/saferef.py tests/__init__.py tests/test_dispatcher.py tests/test_robustapply.py tests/test_saferef.py ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/PyDispatcher-2.0.5-py3.6.egg-info/dependency_links.txt ================================================ ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/PyDispatcher-2.0.5-py3.6.egg-info/installed-files.txt ================================================ ../pydispatch/__init__.py ../pydispatch/__pycache__/__init__.cpython-36.pyc ../pydispatch/__pycache__/dispatcher.cpython-36.pyc ../pydispatch/__pycache__/errors.cpython-36.pyc ../pydispatch/__pycache__/robust.cpython-36.pyc ../pydispatch/__pycache__/robustapply.cpython-36.pyc ../pydispatch/__pycache__/saferef.cpython-36.pyc ../pydispatch/dispatcher.py ../pydispatch/errors.py ../pydispatch/robust.py ../pydispatch/robustapply.py ../pydispatch/saferef.py PKG-INFO SOURCES.txt dependency_links.txt top_level.txt ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/PyDispatcher-2.0.5-py3.6.egg-info/top_level.txt ================================================ pydispatch ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/PyHamcrest-1.9.0.dist-info/DESCRIPTION.rst ================================================ PyHamcrest ========== | |docs| |travis| |coveralls| |landscape| |scrutinizer| |codeclimate| | |version| |downloads| |wheel| |supported-versions| |supported-implementations| .. |docs| image:: https://readthedocs.org/projects/pyhamcrest/badge/?style=flat :target: https://pyhamcrest.readthedocs.org/ :alt: Documentation Status .. |travis| image:: http://img.shields.io/travis/hamcrest/PyHamcrest/master.png?style=flat :alt: Travis-CI Build Status :target: https://travis-ci.org/hamcrest/PyHamcrest .. |appveyor| image:: https://ci.appveyor.com/api/projects/status/github/hamcrest/PyHamcrest?branch=master :alt: AppVeyor Build Status :target: https://ci.appveyor.com/project/hamcrest/PyHamcrest .. |coveralls| image:: http://img.shields.io/coveralls/hamcrest/PyHamcrest/master.png?style=flat :alt: Coverage Status :target: https://coveralls.io/r/hamcrest/PyHamcrest .. |landscape| image:: https://landscape.io/github/hamcrest/PyHamcrest/master/landscape.svg?style=flat :target: https://landscape.io/github/hamcrest/PyHamcrest/master :alt: Code Quality Status .. |codeclimate| image:: https://codeclimate.com/github/hamcrest/PyHamcrest/badges/gpa.svg :target: https://codeclimate.com/github/hamcrest/PyHamcrest :alt: Code Climate .. |version| image:: http://img.shields.io/pypi/v/PyHamcrest.png?style=flat :alt: PyPI Package latest release :target: https://pypi.python.org/pypi/PyHamcrest .. |downloads| image:: http://img.shields.io/pypi/dm/PyHamcrest.png?style=flat :alt: PyPI Package monthly downloads :target: https://pypi.python.org/pypi/PyHamcrest .. |wheel| image:: https://pypip.in/wheel/PyHamcrest/badge.png?style=flat :alt: PyPI Wheel :target: https://pypi.python.org/pypi/PyHamcrest .. |supported-versions| image:: https://pypip.in/py_versions/PyHamcrest/badge.png?style=flat :alt: Supported versions :target: https://pypi.python.org/pypi/PyHamcrest .. |supported-implementations| image:: https://pypip.in/implementation/PyHamcrest/badge.png?style=flat :alt: Supported imlementations :target: https://pypi.python.org/pypi/PyHamcrest .. |scrutinizer| image:: https://img.shields.io/scrutinizer/g/hamcrest/PyHamcrest/master.png?style=flat :alt: Scrtinizer Status :target: https://scrutinizer-ci.com/g/hamcrest/PyHamcrest/ Introduction ============ PyHamcrest is a framework for writing matcher objects, allowing you to declaratively define "match" rules. There are a number of situations where matchers are invaluable, such as UI validation, or data filtering, but it is in the area of writing flexible tests that matchers are most commonly used. This tutorial shows you how to use PyHamcrest for unit testing. When writing tests it is sometimes difficult to get the balance right between overspecifying the test (and making it brittle to changes), and not specifying enough (making the test less valuable since it continues to pass even when the thing being tested is broken). Having a tool that allows you to pick out precisely the aspect under test and describe the values it should have, to a controlled level of precision, helps greatly in writing tests that are "just right." Such tests fail when the behavior of the aspect under test deviates from the expected behavior, yet continue to pass when minor, unrelated changes to the behaviour are made. Installation ============ Hamcrest can be installed using the usual Python packaging tools. It depends on distribute, but as long as you have a network connection when you install, the installation process will take care of that for you. My first PyHamcrest test ======================== We'll start by writing a very simple PyUnit test, but instead of using PyUnit's ``assertEqual`` method, we'll use PyHamcrest's ``assert_that`` construct and the standard set of matchers: .. code:: python from hamcrest import * import unittest class BiscuitTest(unittest.TestCase): def testEquals(self): theBiscuit = Biscuit('Ginger') myBiscuit = Biscuit('Ginger') assert_that(theBiscuit, equal_to(myBiscuit)) if __name__ == '__main__': unittest.main() The ``assert_that`` function is a stylized sentence for making a test assertion. In this example, the subject of the assertion is the object ``theBiscuit``, which is the first method parameter. The second method parameter is a matcher for ``Biscuit`` objects, here a matcher that checks one object is equal to another using the Python ``==`` operator. The test passes since the ``Biscuit`` class defines an ``__eq__`` method. If you have more than one assertion in your test you can include an identifier for the tested value in the assertion: .. code:: python assert_that(theBiscuit.getChocolateChipCount(), equal_to(10), 'chocolate chips') assert_that(theBiscuit.getHazelnutCount(), equal_to(3), 'hazelnuts') As a convenience, assert_that can also be used to verify a boolean condition: .. code:: python assert_that(theBiscuit.isCooked(), 'cooked') This is equivalent to the ``assert_`` method of unittest.TestCase, but because it's a standalone function, it offers greater flexibility in test writing. Predefined matchers =================== PyHamcrest comes with a library of useful matchers: * Object * ``equal_to`` - match equal object * ``has_length`` - match ``len()`` * ``has_property`` - match value of property with given name * ``has_properties`` - match an object that has all of the given properties. * ``has_string`` - match ``str()`` * ``instance_of`` - match object type * ``none``, ``not_none`` - match ``None``, or not ``None`` * ``same_instance`` - match same object * ``calling, raises`` - wrap a method call and assert that it raises an exception * Number * ``close_to`` - match number close to a given value * ``greater_than``, ``greater_than_or_equal_to``, ``less_than``, ``less_than_or_equal_to`` - match numeric ordering * Text * ``contains_string`` - match part of a string * ``ends_with`` - match the end of a string * ``equal_to_ignoring_case`` - match the complete string but ignore case * ``equal_to_ignoring_whitespace`` - match the complete string but ignore extra whitespace * ``matches_regexp`` - match a regular expression in a string * ``starts_with`` - match the beginning of a string * ``string_contains_in_order`` - match parts of a string, in relative order * Logical * ``all_of`` - ``and`` together all matchers * ``any_of`` - ``or`` together all matchers * ``anything`` - match anything, useful in composite matchers when you don't care about a particular value * ``is_not`` - negate the matcher * Sequence * ``contains`` - exactly match the entire sequence * ``contains_inanyorder`` - match the entire sequence, but in any order * ``has_item`` - match if given item appears in the sequence * ``has_items`` - match if all given items appear in the sequence, in any order * ``is_in`` - match if item appears in the given sequence * ``only_contains`` - match if sequence's items appear in given list * ``empty`` - match if the sequence is empty * Dictionary * ``has_entries`` - match dictionary with list of key-value pairs * ``has_entry`` - match dictionary containing a key-value pair * ``has_key`` - match dictionary with a key * ``has_value`` - match dictionary with a value * Decorator * ``calling`` - wrap a callable in a deffered object, for subsequent matching on calling behaviour * ``raises`` - Ensure that a deferred callable raises as expected * ``described_as`` - give the matcher a custom failure description * ``is_`` - decorator to improve readability - see `Syntactic sugar` below The arguments for many of these matchers accept not just a matching value, but another matcher, so matchers can be composed for greater flexibility. For example, ``only_contains(less_than(5))`` will match any sequence where every item is less than 5. Syntactic sugar =============== PyHamcrest strives to make your tests as readable as possible. For example, the ``is_`` matcher is a wrapper that doesn't add any extra behavior to the underlying matcher. The following assertions are all equivalent: .. code:: python assert_that(theBiscuit, equal_to(myBiscuit)) assert_that(theBiscuit, is_(equal_to(myBiscuit))) assert_that(theBiscuit, is_(myBiscuit)) The last form is allowed since ``is_(value)`` wraps most non-matcher arguments with ``equal_to``. But if the argument is a type, it is wrapped with ``instance_of``, so the following are also equivalent: .. code:: python assert_that(theBiscuit, instance_of(Biscuit)) assert_that(theBiscuit, is_(instance_of(Biscuit))) assert_that(theBiscuit, is_(Biscuit)) *Note that PyHamcrest's ``is_`` matcher is unrelated to Python's ``is`` operator. The matcher for object identity is ``same_instance``.* Writing custom matchers ======================= PyHamcrest comes bundled with lots of useful matchers, but you'll probably find that you need to create your own from time to time to fit your testing needs. This commonly occurs when you find a fragment of code that tests the same set of properties over and over again (and in different tests), and you want to bundle the fragment into a single assertion. By writing your own matcher you'll eliminate code duplication and make your tests more readable! Let's write our own matcher for testing if a calendar date falls on a Saturday. This is the test we want to write: .. code:: python def testDateIsOnASaturday(self): d = datetime.date(2008, 04, 26) assert_that(d, is_(on_a_saturday())) And here's the implementation: .. code:: python from hamcrest.core.base_matcher import BaseMatcher from hamcrest.core.helpers.hasmethod import hasmethod class IsGivenDayOfWeek(BaseMatcher): def __init__(self, day): self.day = day # Monday is 0, Sunday is 6 def _matches(self, item): if not hasmethod(item, 'weekday'): return False return item.weekday() == self.day def describe_to(self, description): day_as_string = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'] description.append_text('calendar date falling on ') \ .append_text(day_as_string[self.day]) def on_a_saturday(): return IsGivenDayOfWeek(5) For our Matcher implementation we implement the ``_matches`` method - which calls the ``weekday`` method after confirming that the argument (which may not be a date) has such a method - and the ``describe_to`` method - which is used to produce a failure message when a test fails. Here's an example of how the failure message looks: .. code:: python assert_that(datetime.date(2008, 04, 06), is_(on_a_saturday())) fails with the message:: AssertionError: Expected: is calendar date falling on Saturday got: <2008-04-06> Let's say this matcher is saved in a module named ``isgivendayofweek``. We could use it in our test by importing the factory function ``on_a_saturday``: .. code:: python from hamcrest import * import unittest from isgivendayofweek import on_a_saturday class DateTest(unittest.TestCase): def testDateIsOnASaturday(self): d = datetime.date(2008, 04, 26) assert_that(d, is_(on_a_saturday())) if __name__ == '__main__': unittest.main() Even though the ``on_a_saturday`` function creates a new matcher each time it is called, you should not assume this is the only usage pattern for your matcher. Therefore you should make sure your matcher is stateless, so a single instance can be reused between matches. More resources ============== * Documentation_ * Package_ * Sources_ * Hamcrest_ .. _Documentation: http://readthedocs.org/docs/pyhamcrest/en/V1.8.2/ .. _Package: http://pypi.python.org/pypi/PyHamcrest .. _Sources: https://github.com/hamcrest/PyHamcrest .. _Hamcrest: http://hamcrest.org ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/PyHamcrest-1.9.0.dist-info/INSTALLER ================================================ pip ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/PyHamcrest-1.9.0.dist-info/METADATA ================================================ Metadata-Version: 2.0 Name: PyHamcrest Version: 1.9.0 Summary: Hamcrest framework for matcher objects Home-page: https://github.com/hamcrest/PyHamcrest Author: Chris Rose Author-email: offline@offby1.net License: New BSD Download-URL: http://pypi.python.org/packages/source/P/PyHamcrest/PyHamcrest-1.9.0.tar.gz Keywords: hamcrest matchers pyunit unit test testing unittest unittesting Platform: All Classifier: Development Status :: 5 - Production/Stable Classifier: Environment :: Console Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: BSD License Classifier: Natural Language :: English Classifier: Operating System :: OS Independent Classifier: Programming Language :: Python :: 2 Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: 3.4 Classifier: Programming Language :: Python :: Implementation :: CPython Classifier: Programming Language :: Python :: Implementation :: Jython Classifier: Programming Language :: Python :: Implementation :: PyPy Classifier: Topic :: Software Development Classifier: Topic :: Software Development :: Quality Assurance Classifier: Topic :: Software Development :: Testing Provides: hamcrest Requires-Dist: setuptools Requires-Dist: six PyHamcrest ========== | |docs| |travis| |coveralls| |landscape| |scrutinizer| |codeclimate| | |version| |downloads| |wheel| |supported-versions| |supported-implementations| .. |docs| image:: https://readthedocs.org/projects/pyhamcrest/badge/?style=flat :target: https://pyhamcrest.readthedocs.org/ :alt: Documentation Status .. |travis| image:: http://img.shields.io/travis/hamcrest/PyHamcrest/master.png?style=flat :alt: Travis-CI Build Status :target: https://travis-ci.org/hamcrest/PyHamcrest .. |appveyor| image:: https://ci.appveyor.com/api/projects/status/github/hamcrest/PyHamcrest?branch=master :alt: AppVeyor Build Status :target: https://ci.appveyor.com/project/hamcrest/PyHamcrest .. |coveralls| image:: http://img.shields.io/coveralls/hamcrest/PyHamcrest/master.png?style=flat :alt: Coverage Status :target: https://coveralls.io/r/hamcrest/PyHamcrest .. |landscape| image:: https://landscape.io/github/hamcrest/PyHamcrest/master/landscape.svg?style=flat :target: https://landscape.io/github/hamcrest/PyHamcrest/master :alt: Code Quality Status .. |codeclimate| image:: https://codeclimate.com/github/hamcrest/PyHamcrest/badges/gpa.svg :target: https://codeclimate.com/github/hamcrest/PyHamcrest :alt: Code Climate .. |version| image:: http://img.shields.io/pypi/v/PyHamcrest.png?style=flat :alt: PyPI Package latest release :target: https://pypi.python.org/pypi/PyHamcrest .. |downloads| image:: http://img.shields.io/pypi/dm/PyHamcrest.png?style=flat :alt: PyPI Package monthly downloads :target: https://pypi.python.org/pypi/PyHamcrest .. |wheel| image:: https://pypip.in/wheel/PyHamcrest/badge.png?style=flat :alt: PyPI Wheel :target: https://pypi.python.org/pypi/PyHamcrest .. |supported-versions| image:: https://pypip.in/py_versions/PyHamcrest/badge.png?style=flat :alt: Supported versions :target: https://pypi.python.org/pypi/PyHamcrest .. |supported-implementations| image:: https://pypip.in/implementation/PyHamcrest/badge.png?style=flat :alt: Supported imlementations :target: https://pypi.python.org/pypi/PyHamcrest .. |scrutinizer| image:: https://img.shields.io/scrutinizer/g/hamcrest/PyHamcrest/master.png?style=flat :alt: Scrtinizer Status :target: https://scrutinizer-ci.com/g/hamcrest/PyHamcrest/ Introduction ============ PyHamcrest is a framework for writing matcher objects, allowing you to declaratively define "match" rules. There are a number of situations where matchers are invaluable, such as UI validation, or data filtering, but it is in the area of writing flexible tests that matchers are most commonly used. This tutorial shows you how to use PyHamcrest for unit testing. When writing tests it is sometimes difficult to get the balance right between overspecifying the test (and making it brittle to changes), and not specifying enough (making the test less valuable since it continues to pass even when the thing being tested is broken). Having a tool that allows you to pick out precisely the aspect under test and describe the values it should have, to a controlled level of precision, helps greatly in writing tests that are "just right." Such tests fail when the behavior of the aspect under test deviates from the expected behavior, yet continue to pass when minor, unrelated changes to the behaviour are made. Installation ============ Hamcrest can be installed using the usual Python packaging tools. It depends on distribute, but as long as you have a network connection when you install, the installation process will take care of that for you. My first PyHamcrest test ======================== We'll start by writing a very simple PyUnit test, but instead of using PyUnit's ``assertEqual`` method, we'll use PyHamcrest's ``assert_that`` construct and the standard set of matchers: .. code:: python from hamcrest import * import unittest class BiscuitTest(unittest.TestCase): def testEquals(self): theBiscuit = Biscuit('Ginger') myBiscuit = Biscuit('Ginger') assert_that(theBiscuit, equal_to(myBiscuit)) if __name__ == '__main__': unittest.main() The ``assert_that`` function is a stylized sentence for making a test assertion. In this example, the subject of the assertion is the object ``theBiscuit``, which is the first method parameter. The second method parameter is a matcher for ``Biscuit`` objects, here a matcher that checks one object is equal to another using the Python ``==`` operator. The test passes since the ``Biscuit`` class defines an ``__eq__`` method. If you have more than one assertion in your test you can include an identifier for the tested value in the assertion: .. code:: python assert_that(theBiscuit.getChocolateChipCount(), equal_to(10), 'chocolate chips') assert_that(theBiscuit.getHazelnutCount(), equal_to(3), 'hazelnuts') As a convenience, assert_that can also be used to verify a boolean condition: .. code:: python assert_that(theBiscuit.isCooked(), 'cooked') This is equivalent to the ``assert_`` method of unittest.TestCase, but because it's a standalone function, it offers greater flexibility in test writing. Predefined matchers =================== PyHamcrest comes with a library of useful matchers: * Object * ``equal_to`` - match equal object * ``has_length`` - match ``len()`` * ``has_property`` - match value of property with given name * ``has_properties`` - match an object that has all of the given properties. * ``has_string`` - match ``str()`` * ``instance_of`` - match object type * ``none``, ``not_none`` - match ``None``, or not ``None`` * ``same_instance`` - match same object * ``calling, raises`` - wrap a method call and assert that it raises an exception * Number * ``close_to`` - match number close to a given value * ``greater_than``, ``greater_than_or_equal_to``, ``less_than``, ``less_than_or_equal_to`` - match numeric ordering * Text * ``contains_string`` - match part of a string * ``ends_with`` - match the end of a string * ``equal_to_ignoring_case`` - match the complete string but ignore case * ``equal_to_ignoring_whitespace`` - match the complete string but ignore extra whitespace * ``matches_regexp`` - match a regular expression in a string * ``starts_with`` - match the beginning of a string * ``string_contains_in_order`` - match parts of a string, in relative order * Logical * ``all_of`` - ``and`` together all matchers * ``any_of`` - ``or`` together all matchers * ``anything`` - match anything, useful in composite matchers when you don't care about a particular value * ``is_not`` - negate the matcher * Sequence * ``contains`` - exactly match the entire sequence * ``contains_inanyorder`` - match the entire sequence, but in any order * ``has_item`` - match if given item appears in the sequence * ``has_items`` - match if all given items appear in the sequence, in any order * ``is_in`` - match if item appears in the given sequence * ``only_contains`` - match if sequence's items appear in given list * ``empty`` - match if the sequence is empty * Dictionary * ``has_entries`` - match dictionary with list of key-value pairs * ``has_entry`` - match dictionary containing a key-value pair * ``has_key`` - match dictionary with a key * ``has_value`` - match dictionary with a value * Decorator * ``calling`` - wrap a callable in a deffered object, for subsequent matching on calling behaviour * ``raises`` - Ensure that a deferred callable raises as expected * ``described_as`` - give the matcher a custom failure description * ``is_`` - decorator to improve readability - see `Syntactic sugar` below The arguments for many of these matchers accept not just a matching value, but another matcher, so matchers can be composed for greater flexibility. For example, ``only_contains(less_than(5))`` will match any sequence where every item is less than 5. Syntactic sugar =============== PyHamcrest strives to make your tests as readable as possible. For example, the ``is_`` matcher is a wrapper that doesn't add any extra behavior to the underlying matcher. The following assertions are all equivalent: .. code:: python assert_that(theBiscuit, equal_to(myBiscuit)) assert_that(theBiscuit, is_(equal_to(myBiscuit))) assert_that(theBiscuit, is_(myBiscuit)) The last form is allowed since ``is_(value)`` wraps most non-matcher arguments with ``equal_to``. But if the argument is a type, it is wrapped with ``instance_of``, so the following are also equivalent: .. code:: python assert_that(theBiscuit, instance_of(Biscuit)) assert_that(theBiscuit, is_(instance_of(Biscuit))) assert_that(theBiscuit, is_(Biscuit)) *Note that PyHamcrest's ``is_`` matcher is unrelated to Python's ``is`` operator. The matcher for object identity is ``same_instance``.* Writing custom matchers ======================= PyHamcrest comes bundled with lots of useful matchers, but you'll probably find that you need to create your own from time to time to fit your testing needs. This commonly occurs when you find a fragment of code that tests the same set of properties over and over again (and in different tests), and you want to bundle the fragment into a single assertion. By writing your own matcher you'll eliminate code duplication and make your tests more readable! Let's write our own matcher for testing if a calendar date falls on a Saturday. This is the test we want to write: .. code:: python def testDateIsOnASaturday(self): d = datetime.date(2008, 04, 26) assert_that(d, is_(on_a_saturday())) And here's the implementation: .. code:: python from hamcrest.core.base_matcher import BaseMatcher from hamcrest.core.helpers.hasmethod import hasmethod class IsGivenDayOfWeek(BaseMatcher): def __init__(self, day): self.day = day # Monday is 0, Sunday is 6 def _matches(self, item): if not hasmethod(item, 'weekday'): return False return item.weekday() == self.day def describe_to(self, description): day_as_string = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'] description.append_text('calendar date falling on ') \ .append_text(day_as_string[self.day]) def on_a_saturday(): return IsGivenDayOfWeek(5) For our Matcher implementation we implement the ``_matches`` method - which calls the ``weekday`` method after confirming that the argument (which may not be a date) has such a method - and the ``describe_to`` method - which is used to produce a failure message when a test fails. Here's an example of how the failure message looks: .. code:: python assert_that(datetime.date(2008, 04, 06), is_(on_a_saturday())) fails with the message:: AssertionError: Expected: is calendar date falling on Saturday got: <2008-04-06> Let's say this matcher is saved in a module named ``isgivendayofweek``. We could use it in our test by importing the factory function ``on_a_saturday``: .. code:: python from hamcrest import * import unittest from isgivendayofweek import on_a_saturday class DateTest(unittest.TestCase): def testDateIsOnASaturday(self): d = datetime.date(2008, 04, 26) assert_that(d, is_(on_a_saturday())) if __name__ == '__main__': unittest.main() Even though the ``on_a_saturday`` function creates a new matcher each time it is called, you should not assume this is the only usage pattern for your matcher. Therefore you should make sure your matcher is stateless, so a single instance can be reused between matches. More resources ============== * Documentation_ * Package_ * Sources_ * Hamcrest_ .. _Documentation: http://readthedocs.org/docs/pyhamcrest/en/V1.8.2/ .. _Package: http://pypi.python.org/pypi/PyHamcrest .. _Sources: https://github.com/hamcrest/PyHamcrest .. _Hamcrest: http://hamcrest.org ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/PyHamcrest-1.9.0.dist-info/RECORD ================================================ PyHamcrest-1.9.0.dist-info/DESCRIPTION.rst,sha256=13XTDh2baR2aJ91v_lAOjEXD7Ydush_RHhk0Z3azfs8,11973 PyHamcrest-1.9.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 PyHamcrest-1.9.0.dist-info/METADATA,sha256=s0naXZHUZhft0MWcUeZVaZYlREKPOqHp3mUQrhUoC6s,13276 PyHamcrest-1.9.0.dist-info/RECORD,, PyHamcrest-1.9.0.dist-info/WHEEL,sha256=AvR0WeTpDaxT645bl5FQxUK6NPsTls2ttpcGJg3j1Xg,110 PyHamcrest-1.9.0.dist-info/metadata.json,sha256=Jqs-ZSW5kWSnfvxDsRMwSQH6TxEqSJjBJWiQk1G-c_A,1545 PyHamcrest-1.9.0.dist-info/pbr.json,sha256=jdAcCmfO0nnMs9-YKXuwDyKnxc4qGwyUxyGulF9Pam4,47 PyHamcrest-1.9.0.dist-info/top_level.txt,sha256=mRc0yPsPQSqFgWBmZBY33u-05Xtm5M4GEve4NjYdloQ,9 hamcrest/__init__.py,sha256=Uo0mxeePyXP9_yIzBBvKqIL6tzEHqBwBO1eSHfAKies,230 hamcrest/__pycache__/__init__.cpython-36.pyc,, hamcrest/core/__init__.py,sha256=nDkYm1E1P7XpHmR8EHu17eahlmC6uYix4HurTyJjhlE,230 hamcrest/core/__pycache__/__init__.cpython-36.pyc,, hamcrest/core/__pycache__/assert_that.cpython-36.pyc,, hamcrest/core/__pycache__/base_description.cpython-36.pyc,, hamcrest/core/__pycache__/base_matcher.cpython-36.pyc,, hamcrest/core/__pycache__/compat.cpython-36.pyc,, hamcrest/core/__pycache__/description.cpython-36.pyc,, hamcrest/core/__pycache__/matcher.cpython-36.pyc,, hamcrest/core/__pycache__/selfdescribing.cpython-36.pyc,, hamcrest/core/__pycache__/selfdescribingvalue.cpython-36.pyc,, hamcrest/core/__pycache__/string_description.cpython-36.pyc,, hamcrest/core/assert_that.py,sha256=mPdTQQVsjUliK3xp8l_Vn3YmMzg_h5rYhWJk2mstMc0,2428 hamcrest/core/base_description.py,sha256=auvrelro2vGh_A05TQxwbaBJStvfHiFqm0TL56luxEU,2841 hamcrest/core/base_matcher.py,sha256=eRhLv7zFBJGaz68vEsDlvKbrWwU8GRDfZc7pWBNcxwI,1193 hamcrest/core/compat.py,sha256=wUi1u_nIhgUA3kFGJDZLQ2D_cRw79E1SxPDMaI4mzG0,642 hamcrest/core/core/__init__.py,sha256=7q_pNO9cmtV3BEixiGcueNdbxRxlKEFZ1RSO-5GP58E,770 hamcrest/core/core/__pycache__/__init__.cpython-36.pyc,, hamcrest/core/core/__pycache__/allof.cpython-36.pyc,, hamcrest/core/core/__pycache__/anyof.cpython-36.pyc,, hamcrest/core/core/__pycache__/described_as.cpython-36.pyc,, hamcrest/core/core/__pycache__/is_.cpython-36.pyc,, hamcrest/core/core/__pycache__/isanything.cpython-36.pyc,, hamcrest/core/core/__pycache__/isequal.cpython-36.pyc,, hamcrest/core/core/__pycache__/isinstanceof.cpython-36.pyc,, hamcrest/core/core/__pycache__/isnone.cpython-36.pyc,, hamcrest/core/core/__pycache__/isnot.cpython-36.pyc,, hamcrest/core/core/__pycache__/issame.cpython-36.pyc,, hamcrest/core/core/__pycache__/raises.cpython-36.pyc,, hamcrest/core/core/allof.py,sha256=x2ea18Z5cioRybs1heTd3E8zYtpFbuBJg3vIU3vl9k0,1487 hamcrest/core/core/anyof.py,sha256=8j2KAsaToXbv8CA5hed4bqPR3hscODIiaFhAlAyJ2Vs,1097 hamcrest/core/core/described_as.py,sha256=kyy_qRpoebWB1bS2ReAkNDt-79iXu6HqHxOG0GT7PtQ,1623 hamcrest/core/core/is_.py,sha256=C7UCASfr4AIlaaMZnT5d34OthAZQ3rYv8OhszQjz-Eg,2547 hamcrest/core/core/isanything.py,sha256=D2QO5dbDhwlVRGLFrnxOSijTyeKN2iWLRwjpvnumkvg,798 hamcrest/core/core/isequal.py,sha256=TAwF_lWIjVokPruXN8IGS6ajzPGlThanTLPdhktKwRQ,893 hamcrest/core/core/isinstanceof.py,sha256=dnt8YKLhYwGZvDkJ0OTdLd1PN9cB9ZWCg5k8kdnEuqI,1352 hamcrest/core/core/isnone.py,sha256=51ueQKBgg0RzWVLzjFOyt6K0ejk2EbXUlUX90ORPm80,557 hamcrest/core/core/isnot.py,sha256=_z_ynAVUXEUGWoiRlynFa_yaCVh9cK9LIOznDfKVZeo,1533 hamcrest/core/core/issame.py,sha256=8FvAjud4HTuyz7O-XoJbzLtKhChCr1_5JmzMYMeQt1s,1261 hamcrest/core/core/raises.py,sha256=BZXtMlQiEqEjQMYT76HUiuQNRjTECIUmL82_FKYhAvs,3610 hamcrest/core/description.py,sha256=gbVS-ejZJ783o-WEA66bXnXc9DH5cOlQXg0FlzoVGro,1729 hamcrest/core/helpers/__init__.py,sha256=mPsycYI18LoGawOo9BfETa7yKtnM-fDjFOr43BIevUg,146 hamcrest/core/helpers/__pycache__/__init__.cpython-36.pyc,, hamcrest/core/helpers/__pycache__/hasmethod.cpython-36.pyc,, hamcrest/core/helpers/__pycache__/wrap_matcher.cpython-36.pyc,, hamcrest/core/helpers/hasmethod.py,sha256=LPh_WDRuyKYII3G3fX_x2Ql-ECuPJn4tK5eWMLbetLg,325 hamcrest/core/helpers/wrap_matcher.py,sha256=IQTtw98Pp1NXcVTy9boaNh6jayvawKHhX62R3ZwnVwQ,880 hamcrest/core/matcher.py,sha256=BG6e8bIJvwFI0qkaSkt_SOuuLI0VidvoX8GQLadYssU,1851 hamcrest/core/selfdescribing.py,sha256=RzwqHRGg00AJYweGiP8JzSxoHFdBo0Q7m5axYfutfG8,574 hamcrest/core/selfdescribingvalue.py,sha256=OpGLOjdPA9FSgmLZzmkfYrDvpG261TDDiM56muROFqQ,834 hamcrest/core/string_description.py,sha256=Jp-SbuY8LAwPucL4NMrwWqRhkg6CMwYE-pH0ZDMUq8A,908 hamcrest/library/__init__.py,sha256=2atNiBCC2g3c-7jw53CltNgU4wEao1uRcheUPl1ML50,1014 hamcrest/library/__pycache__/__init__.cpython-36.pyc,, hamcrest/library/collection/__init__.py,sha256=iJU6WCsf0R22m11fqMA9Ztb161AZAdrsKG-4Cj38lZ0,635 hamcrest/library/collection/__pycache__/__init__.cpython-36.pyc,, hamcrest/library/collection/__pycache__/is_empty.cpython-36.pyc,, hamcrest/library/collection/__pycache__/isdict_containing.cpython-36.pyc,, hamcrest/library/collection/__pycache__/isdict_containingentries.cpython-36.pyc,, hamcrest/library/collection/__pycache__/isdict_containingkey.cpython-36.pyc,, hamcrest/library/collection/__pycache__/isdict_containingvalue.cpython-36.pyc,, hamcrest/library/collection/__pycache__/isin.cpython-36.pyc,, hamcrest/library/collection/__pycache__/issequence_containing.cpython-36.pyc,, hamcrest/library/collection/__pycache__/issequence_containinginanyorder.cpython-36.pyc,, hamcrest/library/collection/__pycache__/issequence_containinginorder.cpython-36.pyc,, hamcrest/library/collection/__pycache__/issequence_onlycontaining.cpython-36.pyc,, hamcrest/library/collection/is_empty.py,sha256=p3-B7DCmdbVzqiW3D1h3krdeqmu9B0mfYOaa6HehODg,913 hamcrest/library/collection/isdict_containing.py,sha256=6QxDtDp_Z2TK-6om8cHnJDh45YdmaNHAEy5n97rzf00,2056 hamcrest/library/collection/isdict_containingentries.py,sha256=xKtdFjrwLN32rUdRR4PBUSYa3yACa6jXsmlZv0D9YAU,5168 hamcrest/library/collection/isdict_containingkey.py,sha256=aiBpusjpZmkUEMZ_rUFZBB1GxIfsqluMjhXoWNScqZY,1535 hamcrest/library/collection/isdict_containingvalue.py,sha256=N7mHKgMnd7q6HsQekHH6DShNYbLiSXN9cpQgcdMIjlw,1565 hamcrest/library/collection/isin.py,sha256=bcVslW0fUq0pM_SrT9gdltTlNfeJkrVPZAlg6riV2Ys,774 hamcrest/library/collection/issequence_containing.py,sha256=ZwYMm2-Ul_JtvjcgdMjipYdz82yUbGmRNsdPAjO9RX0,3001 hamcrest/library/collection/issequence_containinginanyorder.py,sha256=Px_W2-_0XDOXiL2NTTMp16ZTZvBl4m5rXjlMoR4Ulmw,3613 hamcrest/library/collection/issequence_containinginorder.py,sha256=x7AT_kOCaPY0LmZw28ln8xLLHBtT-I3NneoCWzMJoYA,3219 hamcrest/library/collection/issequence_onlycontaining.py,sha256=Ia17P1HVgb43lZfdUEhmPyUUUWtGLix__fqXIQJTUiI,1626 hamcrest/library/integration/__init__.py,sha256=3aiupojVacPksKTXVhqRs9OwUDoUlUw-bjWItJnRg8Q,254 hamcrest/library/integration/__pycache__/__init__.cpython-36.pyc,, hamcrest/library/integration/__pycache__/match_equality.cpython-36.pyc,, hamcrest/library/integration/match_equality.py,sha256=0BMth20YLTqjqTLT4qMVldAe2dQV3CJ2j3zLXDIGl9c,1192 hamcrest/library/number/__init__.py,sha256=J3UoFdR9UPq9zXSKe1a9qAlpjaVst8-pnaxsvbCPj78,335 hamcrest/library/number/__pycache__/__init__.cpython-36.pyc,, hamcrest/library/number/__pycache__/iscloseto.cpython-36.pyc,, hamcrest/library/number/__pycache__/ordering_comparison.cpython-36.pyc,, hamcrest/library/number/iscloseto.py,sha256=2lQTw3Xvo5MW-aePxpWVUOwyV_ydXtH6cCAIAxeopk8,2259 hamcrest/library/number/ordering_comparison.py,sha256=8XxVSOzPK29D14h4wtBZYVYKZf6IcABaQEKihEuzlhI,1700 hamcrest/library/object/__init__.py,sha256=pxzCpybBHRaIg7RJUAw7R1Po0llw8QBbVv_R1TXNBhc,319 hamcrest/library/object/__pycache__/__init__.cpython-36.pyc,, hamcrest/library/object/__pycache__/haslength.cpython-36.pyc,, hamcrest/library/object/__pycache__/hasproperty.cpython-36.pyc,, hamcrest/library/object/__pycache__/hasstring.cpython-36.pyc,, hamcrest/library/object/haslength.py,sha256=mpYVvrBZV548FwEeqlHWYofv9LPgChvnypZ4RhZDMp0,1681 hamcrest/library/object/hasproperty.py,sha256=9t8upZxjqSQp6IvGyTm4ftGvcpBeyk0dy36HgvlXZBg,5740 hamcrest/library/object/hasstring.py,sha256=_Ht1x-DwV4hk2fRuGo_KoayoLOIoWObKoA30u7HnABU,1250 hamcrest/library/text/__init__.py,sha256=3Uuy1lY2p0VEUy1SAIO6IZgDDgyx8ZsB98k-J2FA_R0,548 hamcrest/library/text/__pycache__/__init__.cpython-36.pyc,, hamcrest/library/text/__pycache__/isequal_ignoring_case.cpython-36.pyc,, hamcrest/library/text/__pycache__/isequal_ignoring_whitespace.cpython-36.pyc,, hamcrest/library/text/__pycache__/stringcontains.cpython-36.pyc,, hamcrest/library/text/__pycache__/stringcontainsinorder.cpython-36.pyc,, hamcrest/library/text/__pycache__/stringendswith.cpython-36.pyc,, hamcrest/library/text/__pycache__/stringmatches.cpython-36.pyc,, hamcrest/library/text/__pycache__/stringstartswith.cpython-36.pyc,, hamcrest/library/text/__pycache__/substringmatcher.cpython-36.pyc,, hamcrest/library/text/isequal_ignoring_case.py,sha256=VGkR3PNDOVE1MJT9H4a3SjR2SIYNzT80VoV6NEq3aqw,1257 hamcrest/library/text/isequal_ignoring_whitespace.py,sha256=NQzswc7fk5rOhcoHO4zbYSWqn-WQdQ7Hwf0FoDHAwBM,1667 hamcrest/library/text/stringcontains.py,sha256=JbkSxdFkpRrNYJfSUghboxe1jRLfHAJvOn6PYvMx7fQ,953 hamcrest/library/text/stringcontainsinorder.py,sha256=B3qG7TG24_WyVPGJER2iqi7fzOMZN0UsBRJPtWutBkc,1705 hamcrest/library/text/stringendswith.py,sha256=JjukJWSVWgURvTstrbCGCQdQzY0PMWLul__UlDh2NGA,980 hamcrest/library/text/stringmatches.py,sha256=AEBn8NI3q-YzRUdXiAfnw1Kmse-LLxJUluDAuy_D9nU,1151 hamcrest/library/text/stringstartswith.py,sha256=oOro8G3z8nAOUyOjHHkHhUvY-lt7XRTJzDr9dYxxons,1007 hamcrest/library/text/substringmatcher.py,sha256=lSPxE7pTpTJlUkMtd28WgsM1FFm56JVZixSvAldSZXk,695 ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/PyHamcrest-1.9.0.dist-info/WHEEL ================================================ Wheel-Version: 1.0 Generator: bdist_wheel (0.24.0) Root-Is-Purelib: true Tag: py2-none-any Tag: py3-none-any ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/PyHamcrest-1.9.0.dist-info/metadata.json ================================================ {"license": "New BSD", "download_url": "http://pypi.python.org/packages/source/P/PyHamcrest/PyHamcrest-1.9.0.tar.gz", "name": "PyHamcrest", "provides": "hamcrest", "test_requires": [{"requires": ["hypothesis (>=1.11)", "pytest (>=2.8)", "mock", "pytest-cov"]}], "extensions": {"python.details": {"project_urls": {"Home": "https://github.com/hamcrest/PyHamcrest"}, "contacts": [{"name": "Chris Rose", "role": "author", "email": "offline@offby1.net"}], "document_names": {"description": "DESCRIPTION.rst"}}}, "run_requires": [{"requires": ["setuptools", "six"]}], "generator": "bdist_wheel (0.24.0)", "summary": "Hamcrest framework for matcher objects", "extras": [], "classifiers": ["Development Status :: 5 - Production/Stable", "Environment :: Console", "Intended Audience :: Developers", "License :: OSI Approved :: BSD License", "Natural Language :: English", "Operating System :: OS Independent", "Programming Language :: Python :: 2", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.4", "Programming Language :: Python :: Implementation :: CPython", "Programming Language :: Python :: Implementation :: Jython", "Programming Language :: Python :: Implementation :: PyPy", "Topic :: Software Development", "Topic :: Software Development :: Quality Assurance", "Topic :: Software Development :: Testing"], "version": "1.9.0", "metadata_version": "2.0", "keywords": ["hamcrest", "matchers", "pyunit", "unit", "test", "testing", "unittest", "unittesting"], "platform": "All"} ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/PyHamcrest-1.9.0.dist-info/pbr.json ================================================ {"is_release": false, "git_version": "d572d69"} ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/PyHamcrest-1.9.0.dist-info/top_level.txt ================================================ hamcrest ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/Scrapy-1.7.4.dist-info/AUTHORS ================================================ Scrapy was brought to life by Shane Evans while hacking a scraping framework prototype for Mydeco (mydeco.com). It soon became maintained, extended and improved by Insophia (insophia.com), with the initial sponsorship of Mydeco to bootstrap the project. In mid-2011, Scrapinghub became the new official maintainer. Here is the list of the primary authors & contributors: * Pablo Hoffman * Daniel Graña * Martin Olveyra * Gabriel García * Michael Cetrulo * Artem Bogomyagkov * Damian Canabal * Andres Moreira * Ismael Carnales * Matías Aguirre * German Hoffmann * Anibal Pacheco * Bruno Deferrari * Shane Evans * Ezequiel Rivero * Patrick Mezard * Rolando Espinoza * Ping Yin * Lucian Ursu * Shuaib Khan * Didier Deshommes * Vikas Dhiman * Jochen Maes * Darian Moody * Jordi Lonch * Zuhao Wan * Steven Almeroth * Tom Mortimer-Jones * Chris Tilden * Alexandr N Zamaraev * Emanuel Schorsch * Michal Danilak * Natan Lao * Hasnain Lakhani * Pedro Faustino * Alex Cepoi * Ilya Baryshev * Libor Nenadál * Jae-Myoung Yu * Vladislav Poluhin * Marc Abramowitz * Valentin-Costel Hăloiu * Jason Yeo * Сергей Прохоров * Simon Ratne * Julien Duponchelle * Jochen Maes * Vikas Dhiman * Juan Picca * Nicolás Ramírez ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/Scrapy-1.7.4.dist-info/INSTALLER ================================================ pip ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/Scrapy-1.7.4.dist-info/LICENSE ================================================ Copyright (c) Scrapy developers. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of Scrapy nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/Scrapy-1.7.4.dist-info/METADATA ================================================ Metadata-Version: 2.1 Name: Scrapy Version: 1.7.4 Summary: A high-level Web Crawling and Web Scraping framework Home-page: https://scrapy.org Author: Scrapy developers Maintainer: Pablo Hoffman Maintainer-email: pablo@pablohoffman.com License: BSD Platform: UNKNOWN Classifier: Framework :: Scrapy Classifier: Development Status :: 5 - Production/Stable Classifier: Environment :: Console Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: BSD License Classifier: Operating System :: OS Independent Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 2 Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: 3.4 Classifier: Programming Language :: Python :: 3.5 Classifier: Programming Language :: Python :: 3.6 Classifier: Programming Language :: Python :: 3.7 Classifier: Programming Language :: Python :: Implementation :: CPython Classifier: Programming Language :: Python :: Implementation :: PyPy Classifier: Topic :: Internet :: WWW/HTTP Classifier: Topic :: Software Development :: Libraries :: Application Frameworks Classifier: Topic :: Software Development :: Libraries :: Python Modules Requires-Python: >=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.* Requires-Dist: w3lib (>=1.17.0) Requires-Dist: queuelib Requires-Dist: pyOpenSSL Requires-Dist: cssselect (>=0.9) Requires-Dist: six (>=1.5.2) Requires-Dist: parsel (>=1.5) Requires-Dist: PyDispatcher (>=2.0.5) Requires-Dist: service-identity Requires-Dist: PyPyDispatcher (>=2.1.0) ; platform_python_implementation == "PyPy" Requires-Dist: Twisted (>=13.1.0) ; python_version != "3.4" Requires-Dist: lxml ; python_version != "3.4" Requires-Dist: Twisted (<=19.2.0,>=13.1.0) ; python_version == "3.4" Requires-Dist: lxml (<=4.3.5) ; python_version == "3.4" ====== Scrapy ====== .. image:: https://img.shields.io/pypi/v/Scrapy.svg :target: https://pypi.python.org/pypi/Scrapy :alt: PyPI Version .. image:: https://img.shields.io/pypi/pyversions/Scrapy.svg :target: https://pypi.python.org/pypi/Scrapy :alt: Supported Python Versions .. image:: https://img.shields.io/travis/scrapy/scrapy/master.svg :target: https://travis-ci.org/scrapy/scrapy :alt: Build Status .. image:: https://img.shields.io/badge/wheel-yes-brightgreen.svg :target: https://pypi.python.org/pypi/Scrapy :alt: Wheel Status .. image:: https://img.shields.io/codecov/c/github/scrapy/scrapy/master.svg :target: https://codecov.io/github/scrapy/scrapy?branch=master :alt: Coverage report .. image:: https://anaconda.org/conda-forge/scrapy/badges/version.svg :target: https://anaconda.org/conda-forge/scrapy :alt: Conda Version Overview ======== Scrapy is a fast high-level web crawling and web scraping framework, used to crawl websites and extract structured data from their pages. It can be used for a wide range of purposes, from data mining to monitoring and automated testing. For more information including a list of features check the Scrapy homepage at: https://scrapy.org Requirements ============ * Python 2.7 or Python 3.4+ * Works on Linux, Windows, Mac OSX, BSD Install ======= The quick way:: pip install scrapy For more details see the install section in the documentation: https://docs.scrapy.org/en/latest/intro/install.html Documentation ============= Documentation is available online at https://docs.scrapy.org/ and in the ``docs`` directory. Releases ======== You can find release notes at https://docs.scrapy.org/en/latest/news.html Community (blog, twitter, mail list, IRC) ========================================= See https://scrapy.org/community/ Contributing ============ See https://docs.scrapy.org/en/master/contributing.html Code of Conduct --------------- Please note that this project is released with a Contributor Code of Conduct (see https://github.com/scrapy/scrapy/blob/master/CODE_OF_CONDUCT.md). By participating in this project you agree to abide by its terms. Please report unacceptable behavior to opensource@scrapinghub.com. Companies using Scrapy ====================== See https://scrapy.org/companies/ Commercial Support ================== See https://scrapy.org/support/ ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/Scrapy-1.7.4.dist-info/RECORD ================================================ ../../../bin/scrapy,sha256=nBpGRsKtbys-Xp4iWs4bUk8T8k7OmhWXZrXiaWhKU1Q,285 Scrapy-1.7.4.dist-info/AUTHORS,sha256=wBeg3cpJ5eH5Ilhbd22N1Npk17-KVy7CwXL0uRshrYM,1273 Scrapy-1.7.4.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 Scrapy-1.7.4.dist-info/LICENSE,sha256=_TMa88y4d2u-fzF4IeXguRwqt8c0ZOd0JdUiBPe12YA,1517 Scrapy-1.7.4.dist-info/METADATA,sha256=Xj14ruhbCZkQFrJRpOz6IYGkmpQSzZ0UNgPoeWsjGWc,4273 Scrapy-1.7.4.dist-info/RECORD,, Scrapy-1.7.4.dist-info/WHEEL,sha256=8zNYZbwQSXoB9IfXOjPfeNwvAsALAjffgk27FqvCWbo,110 Scrapy-1.7.4.dist-info/entry_points.txt,sha256=WDkmo-mkyyTA0TS6pVQtxOnkG9VXzFeotzjdI7r5DO4,51 Scrapy-1.7.4.dist-info/top_level.txt,sha256=daQJ2I8J6o-AN_sw03XNdbAoaiFVV2v9xkB7FxB6dao,7 scrapy/VERSION,sha256=wKWmSTuO_WdX5f7Mb8zT38UTsZYzMffIryxNaFT5v2Y,6 scrapy/__init__.py,sha256=GtWfEXEqceruqbQHf_nbzQ_t-Gu8menXdEaj7C6qhR8,1146 scrapy/__main__.py,sha256=0pB9bs0MIwKYELCv21imsZMzlfacVRGv6q49Vnbclvw,77 scrapy/__pycache__/__init__.cpython-36.pyc,, scrapy/__pycache__/__main__.cpython-36.pyc,, scrapy/__pycache__/_monkeypatches.cpython-36.pyc,, scrapy/__pycache__/cmdline.cpython-36.pyc,, scrapy/__pycache__/crawler.cpython-36.pyc,, scrapy/__pycache__/dupefilters.cpython-36.pyc,, scrapy/__pycache__/exceptions.cpython-36.pyc,, scrapy/__pycache__/exporters.cpython-36.pyc,, scrapy/__pycache__/extension.cpython-36.pyc,, scrapy/__pycache__/interfaces.cpython-36.pyc,, scrapy/__pycache__/item.cpython-36.pyc,, scrapy/__pycache__/link.cpython-36.pyc,, scrapy/__pycache__/logformatter.cpython-36.pyc,, scrapy/__pycache__/mail.cpython-36.pyc,, scrapy/__pycache__/middleware.cpython-36.pyc,, scrapy/__pycache__/pqueues.cpython-36.pyc,, scrapy/__pycache__/resolver.cpython-36.pyc,, scrapy/__pycache__/responsetypes.cpython-36.pyc,, scrapy/__pycache__/shell.cpython-36.pyc,, scrapy/__pycache__/signalmanager.cpython-36.pyc,, scrapy/__pycache__/signals.cpython-36.pyc,, scrapy/__pycache__/spiderloader.cpython-36.pyc,, scrapy/__pycache__/squeues.cpython-36.pyc,, scrapy/__pycache__/statscollectors.cpython-36.pyc,, scrapy/_monkeypatches.py,sha256=IbS8a61u3tlJ-1KA_wdrDWGSjlO0MjYA23WGmGOPU8k,976 scrapy/cmdline.py,sha256=VwGYKBNrih2fpVZ7vqG5A68kdT3egvM_1dK3TjyVk7E,5486 scrapy/commands/__init__.py,sha256=RcI0G7rAPZ_FRycx9TDxV_vdI5ViJqNIbQyLSzgn9WI,3532 scrapy/commands/__pycache__/__init__.cpython-36.pyc,, scrapy/commands/__pycache__/bench.cpython-36.pyc,, scrapy/commands/__pycache__/check.cpython-36.pyc,, scrapy/commands/__pycache__/crawl.cpython-36.pyc,, scrapy/commands/__pycache__/edit.cpython-36.pyc,, scrapy/commands/__pycache__/fetch.cpython-36.pyc,, scrapy/commands/__pycache__/genspider.cpython-36.pyc,, scrapy/commands/__pycache__/list.cpython-36.pyc,, scrapy/commands/__pycache__/parse.cpython-36.pyc,, scrapy/commands/__pycache__/runspider.cpython-36.pyc,, scrapy/commands/__pycache__/settings.cpython-36.pyc,, scrapy/commands/__pycache__/shell.cpython-36.pyc,, scrapy/commands/__pycache__/startproject.cpython-36.pyc,, scrapy/commands/__pycache__/version.cpython-36.pyc,, scrapy/commands/__pycache__/view.cpython-36.pyc,, scrapy/commands/bench.py,sha256=vm6kFt45KdJsCTNydR7BK1zki8cQfVbG9VcNVbPpIgQ,1640 scrapy/commands/check.py,sha256=TaUfMEhB2IwgCGgk4i5BHGmqdtWUfm2D4FgfXpLlBPQ,3453 scrapy/commands/crawl.py,sha256=u41-TBL-3Avw9CVGHNpflJKy83Jt-bPmOMpUGlL7jHQ,2625 scrapy/commands/edit.py,sha256=OERVroFVEvfFoDda9xQ2Hm-0Sshq79cRV9g-UQKW1R8,1051 scrapy/commands/fetch.py,sha256=m23twt8conAjm43S8nNReWcEt264O-4RqNf2IgOIDjo,2734 scrapy/commands/genspider.py,sha256=7Yx4AZEGgzP1YfKAcaQkcJhR5svI7KZ92ls61sHybOg,4915 scrapy/commands/list.py,sha256=L2C-B5m7rRNrENSOUNov_BZBdB_GF4ncJmaO7HVLOoQ,374 scrapy/commands/parse.py,sha256=lUV4En8O_rOiQ_e0lfg4WgYq_v6yYcQ_twI4Q89w07c,10296 scrapy/commands/runspider.py,sha256=UslNwaSU5kkCLO5cwprJI57t7rPO4djfak9fZCdNqgY,3668 scrapy/commands/settings.py,sha256=0hbpJmWFcJTSpP7Xl67Szk03d5WJR9hJzCxKOUlctnA,1750 scrapy/commands/shell.py,sha256=-RPATQEypBo6vGRZLY_76asJfH5jgXkLmQJnk1tiD3U,2720 scrapy/commands/startproject.py,sha256=07eNX97Om03GDWdNATbCe6ff5kblTaVC85zPLY6Lq5E,3921 scrapy/commands/version.py,sha256=4p4Aw_J-w2a5EOxwGX0QSUcuE_awKnSqLSGHZnvU2TE,1021 scrapy/commands/view.py,sha256=naXH4HTkXjdSjkaevs5JuJcTbFE8o_EeHdvvfi_MWWM,557 scrapy/contracts/__init__.py,sha256=r8HO_NAh0YjEszksbddFf64JFXhL32mSaC6VGZX8iBs,6017 scrapy/contracts/__pycache__/__init__.cpython-36.pyc,, scrapy/contracts/__pycache__/default.cpython-36.pyc,, scrapy/contracts/default.py,sha256=NLJkh6yhxbm10R0d_m3FbhehxL7109OhORH9b_Iu3Ag,2334 scrapy/core/__init__.py,sha256=qWrZeCfaO0rc0hg-MW2Famk13S-U5VcBqmJzRxEL8mc,51 scrapy/core/__pycache__/__init__.cpython-36.pyc,, scrapy/core/__pycache__/engine.cpython-36.pyc,, scrapy/core/__pycache__/scheduler.cpython-36.pyc,, scrapy/core/__pycache__/scraper.cpython-36.pyc,, scrapy/core/__pycache__/spidermw.cpython-36.pyc,, scrapy/core/downloader/__init__.py,sha256=Cxa-FfH6Mz1A1Mp7PGBDpI9qWYtMea4Jt6u_DJWism4,7208 scrapy/core/downloader/__pycache__/__init__.cpython-36.pyc,, scrapy/core/downloader/__pycache__/contextfactory.cpython-36.pyc,, scrapy/core/downloader/__pycache__/middleware.cpython-36.pyc,, scrapy/core/downloader/__pycache__/tls.cpython-36.pyc,, scrapy/core/downloader/__pycache__/webclient.cpython-36.pyc,, scrapy/core/downloader/contextfactory.py,sha256=Fvr6UnBKjEVfdnR2-LHHuvvURxI7jEoL9wdGbwN7Jy8,4480 scrapy/core/downloader/handlers/__init__.py,sha256=Kf963BJqJgqknLvuDuuPg8rOdcbQWwNdoz8kQThN1WE,2806 scrapy/core/downloader/handlers/__pycache__/__init__.cpython-36.pyc,, scrapy/core/downloader/handlers/__pycache__/datauri.cpython-36.pyc,, scrapy/core/downloader/handlers/__pycache__/file.cpython-36.pyc,, scrapy/core/downloader/handlers/__pycache__/ftp.cpython-36.pyc,, scrapy/core/downloader/handlers/__pycache__/http.cpython-36.pyc,, scrapy/core/downloader/handlers/__pycache__/http10.cpython-36.pyc,, scrapy/core/downloader/handlers/__pycache__/http11.cpython-36.pyc,, scrapy/core/downloader/handlers/__pycache__/s3.cpython-36.pyc,, scrapy/core/downloader/handlers/datauri.py,sha256=7nKvTXPCot1H8kqHYJnhj37SWgfafMi8wbCkv6k6p7s,791 scrapy/core/downloader/handlers/file.py,sha256=I9YXSEhplT4-RyAjhLGeko_Uej_A5PeZew8ze32XcDY,535 scrapy/core/downloader/handlers/ftp.py,sha256=8263S1q_4Av0T_dJ6YGvTIP5wkJ_hCt0sCjAgMQk_rA,4568 scrapy/core/downloader/handlers/http.py,sha256=HKHUa25ANNGtrxEp3PDVhMno57K0EaWm2ZeroZPMZXQ,146 scrapy/core/downloader/handlers/http10.py,sha256=BVxK2wWcmMUoSdpXf4-_3P4Ys1orVbm4dSHs_BVupIk,994 scrapy/core/downloader/handlers/http11.py,sha256=12P2EfHOFXf4SMc9iO3s7bsR9NiY3oWTFw4nDQ8MznI,21150 scrapy/core/downloader/handlers/s3.py,sha256=QKJqc4HtcKPlSQj6m7Ds936aPs8b_ELeEynCIi0B2tk,3870 scrapy/core/downloader/middleware.py,sha256=Q_hkW8G5Dh6IV6Kcb6sOeWIZpVwYT9lbQCAAcNe8Agc,3500 scrapy/core/downloader/tls.py,sha256=ckhjPgbcCBuwXGyADSK_LGE2jzpX_m11K7RniQST4Q0,3620 scrapy/core/downloader/webclient.py,sha256=0I-V6vxB3dBmVsvpuKja7moGH9imAyGJ475Cu6Err6g,5796 scrapy/core/engine.py,sha256=b_W67uhavv0W_eOOIOWfWXudw2inxT2-p_xwISrT_Ro,13114 scrapy/core/scheduler.py,sha256=AXyJdDFk42wwcQtglrVjfDLM4sJM2Ebeiop04Ka9qR4,7220 scrapy/core/scraper.py,sha256=CAXJZFV6HqHjaiT7hf7luNSZ4NmedEKIFAn1mx0PSGU,10190 scrapy/core/spidermw.py,sha256=UuP_Eip2pMKB52RzoWuOMmFzcVS3ACPF63xJaHma3VA,5409 scrapy/crawler.py,sha256=HQ-RTrk_XZhq-m0lY7NvG1vKJmSVxHETmpuLxuq0GVY,13435 scrapy/downloadermiddlewares/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 scrapy/downloadermiddlewares/__pycache__/__init__.cpython-36.pyc,, scrapy/downloadermiddlewares/__pycache__/ajaxcrawl.cpython-36.pyc,, scrapy/downloadermiddlewares/__pycache__/chunked.cpython-36.pyc,, scrapy/downloadermiddlewares/__pycache__/cookies.cpython-36.pyc,, scrapy/downloadermiddlewares/__pycache__/decompression.cpython-36.pyc,, scrapy/downloadermiddlewares/__pycache__/defaultheaders.cpython-36.pyc,, scrapy/downloadermiddlewares/__pycache__/downloadtimeout.cpython-36.pyc,, scrapy/downloadermiddlewares/__pycache__/httpauth.cpython-36.pyc,, scrapy/downloadermiddlewares/__pycache__/httpcache.cpython-36.pyc,, scrapy/downloadermiddlewares/__pycache__/httpcompression.cpython-36.pyc,, scrapy/downloadermiddlewares/__pycache__/httpproxy.cpython-36.pyc,, scrapy/downloadermiddlewares/__pycache__/redirect.cpython-36.pyc,, scrapy/downloadermiddlewares/__pycache__/retry.cpython-36.pyc,, scrapy/downloadermiddlewares/__pycache__/robotstxt.cpython-36.pyc,, scrapy/downloadermiddlewares/__pycache__/stats.cpython-36.pyc,, scrapy/downloadermiddlewares/__pycache__/useragent.cpython-36.pyc,, scrapy/downloadermiddlewares/ajaxcrawl.py,sha256=wZp8pcTX4diWPRUuSfi7L80i7xa_nUDAanwDKrL6_Bc,3365 scrapy/downloadermiddlewares/chunked.py,sha256=2BEDL3dYZNSrTSJEODMYRwVp_FcnxTmGYughULNafdk,773 scrapy/downloadermiddlewares/cookies.py,sha256=Nv87VOoKoriX5VM98f_Xw_vir4lt8LQNTbhwTnSrFFM,3330 scrapy/downloadermiddlewares/decompression.py,sha256=yueO97rb4GQxKEoON5qA6r7MfMVK6olMjfT2SSix0_I,2629 scrapy/downloadermiddlewares/defaultheaders.py,sha256=2Q9ExGM7fM57k7nrv6U9NIJcl_BL9Wpaa_gRY-L_3x4,568 scrapy/downloadermiddlewares/downloadtimeout.py,sha256=Pt-9xbi3obt8eEVjMD85VWcPXZc-VI0qB1uFC1pNQaY,709 scrapy/downloadermiddlewares/httpauth.py,sha256=3ALLKVZmnsGIwTzbBad8R2As7Dt2GIRUPzXO-Jrso4s,893 scrapy/downloadermiddlewares/httpcache.py,sha256=USiehBnBQncT_Q_MSzJdioAfFWi4raWXbqiSWuyh4Hc,4706 scrapy/downloadermiddlewares/httpcompression.py,sha256=GE8MgpBzItVM3tcS2a11Avs5QS3dw87MIQMmAhl865c,2605 scrapy/downloadermiddlewares/httpproxy.py,sha256=JJzzrLbmKEsXF-We2Iim4wXn-ulhekr1M69wxe1yzS0,2561 scrapy/downloadermiddlewares/redirect.py,sha256=vjcwFvCewTsOHXW7GtBBPtl4r_tMjuUJCX6UBzYBhI4,4436 scrapy/downloadermiddlewares/retry.py,sha256=eh6MIdgapC1ftJqYoypZDbCtDhFbjHc3Z0ImLXRp6L8,3746 scrapy/downloadermiddlewares/robotstxt.py,sha256=j5fsGDc0ZINZhvaeX3kyj0DwHrKhazx7wysmGmK_L7o,4490 scrapy/downloadermiddlewares/stats.py,sha256=djbnZUa9POgJbInehoJGA3NhzlXwXQeb5OqX1ngUs1I,1495 scrapy/downloadermiddlewares/useragent.py,sha256=q-IAslxHg5ryft03xcyv8xzElGGP3zZTJCYPHTa8DQE,749 scrapy/dupefilters.py,sha256=Hyf0ZSZ05VnmCHwL8JcRLAbY5OquxeaY7bhR-5BSODU,2302 scrapy/exceptions.py,sha256=HUXqpZCoQuKnZxa-5eiK-GerV2EIqoLmYTcfANCj4ek,1620 scrapy/exporters.py,sha256=xCJBbUVlF6DoBjoWN6XErnD30dtKez0hihiq5WckLeg,12541 scrapy/extension.py,sha256=BAMLf4nYbRZkLwZZ6mXkKxozBWcnQFAaslTfCW-BqFw,396 scrapy/extensions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 scrapy/extensions/__pycache__/__init__.cpython-36.pyc,, scrapy/extensions/__pycache__/closespider.cpython-36.pyc,, scrapy/extensions/__pycache__/corestats.cpython-36.pyc,, scrapy/extensions/__pycache__/debug.cpython-36.pyc,, scrapy/extensions/__pycache__/feedexport.cpython-36.pyc,, scrapy/extensions/__pycache__/httpcache.cpython-36.pyc,, scrapy/extensions/__pycache__/logstats.cpython-36.pyc,, scrapy/extensions/__pycache__/memdebug.cpython-36.pyc,, scrapy/extensions/__pycache__/memusage.cpython-36.pyc,, scrapy/extensions/__pycache__/spiderstate.cpython-36.pyc,, scrapy/extensions/__pycache__/statsmailer.cpython-36.pyc,, scrapy/extensions/__pycache__/telnet.cpython-36.pyc,, scrapy/extensions/__pycache__/throttle.cpython-36.pyc,, scrapy/extensions/closespider.py,sha256=TaIUui6l9ZJfLWLQ4X6jKyW_WREQenUmZttN04qESJU,2583 scrapy/extensions/corestats.py,sha256=YAdF8DoCx2HeNqjvKijEcBMhMXpNyAQ9RcOrJSheCvM,1772 scrapy/extensions/debug.py,sha256=XzJwGpW8jrRrl1g6b6pr5ABoakqHv9hU_v57RasCCYw,1890 scrapy/extensions/feedexport.py,sha256=vtXB9mB34Y1TcA_YCab4THBjIHNSuAQEeUUmyNq15GE,11047 scrapy/extensions/httpcache.py,sha256=FaM1QYyjRaeHKYgrDnEET61S0qx7tx6_CXhET2oTWF8,16924 scrapy/extensions/logstats.py,sha256=5_Ds4kqQ5kf7RbjnPpUkZAZOHNK5uvWgDOQ7PzDFiEg,1754 scrapy/extensions/memdebug.py,sha256=blguRbnQhDEXDUpsOQFfaRrRwVH6skymG-vH3jYdABs,945 scrapy/extensions/memusage.py,sha256=CkteP9viQ8A5Exb5niRVsz_DnuDsIZUmZ3u7PqqFOd4,4940 scrapy/extensions/spiderstate.py,sha256=oitUjBiG7_2d0UsXgwLF0FUJtBBOWVoQjSxI0NZcZVo,1169 scrapy/extensions/statsmailer.py,sha256=BH22wLlpo2aCOvu-RJ3sfF5HrFf-SQlw8O8_gYKnpa8,1242 scrapy/extensions/telnet.py,sha256=vTJLZvs6E0aaVRbxsSJGSbqCVS-OzhVgEvhegW0lXdM,4136 scrapy/extensions/throttle.py,sha256=pRZLfXJqu_wnFkHNkKdDA2Z5vKuFhgVOpJ8TtzaRtPo,3586 scrapy/http/__init__.py,sha256=5VPoouMGxjXuKrX42XKZQhEISVjbkWXNJqr1ID0cuVc,602 scrapy/http/__pycache__/__init__.cpython-36.pyc,, scrapy/http/__pycache__/common.cpython-36.pyc,, scrapy/http/__pycache__/cookies.cpython-36.pyc,, scrapy/http/__pycache__/headers.cpython-36.pyc,, scrapy/http/common.py,sha256=xSv2z7fQKyyAtSj98H68xIcEoZI-1W7BVDD4lWM5mFM,247 scrapy/http/cookies.py,sha256=uE3Js0R-lQZztadT3MMSRrlIouOaVQ4-uTdecUni8nk,5842 scrapy/http/headers.py,sha256=95O4zWPdUmXJFgy2wMBe2SjvWfXPqzFtn6x2r8N_5-o,2738 scrapy/http/request/__init__.py,sha256=ruK2uoGLPlocbhhccQaFFbfYvy8-pT6s1w8Wi5K4d-w,3483 scrapy/http/request/__pycache__/__init__.cpython-36.pyc,, scrapy/http/request/__pycache__/form.cpython-36.pyc,, scrapy/http/request/__pycache__/json_request.cpython-36.pyc,, scrapy/http/request/__pycache__/rpc.cpython-36.pyc,, scrapy/http/request/form.py,sha256=XJhxnWFTjD6uBloDzIgr1AEnKtFHXuwshkxipTg-cWQ,7852 scrapy/http/request/json_request.py,sha256=kLnvuqkml5L-nUHRjIT9QplTPCen4pBiNKNgSqZ6MKE,1722 scrapy/http/request/rpc.py,sha256=81jlEaaSR3kOw1y7j6HQMEqdjxR__7bdnlG6PlrMEug,1109 scrapy/http/response/__init__.py,sha256=7RgWzEdOVmmB3SEUZl3gAbVBkGOpqa1HzVikMNsyFKI,4624 scrapy/http/response/__pycache__/__init__.cpython-36.pyc,, scrapy/http/response/__pycache__/html.cpython-36.pyc,, scrapy/http/response/__pycache__/text.cpython-36.pyc,, scrapy/http/response/__pycache__/xml.cpython-36.pyc,, scrapy/http/response/html.py,sha256=OMbreqX9_9ME0fUgl1FlGay86er_-bkJQCk-L7pn_DE,299 scrapy/http/response/text.py,sha256=VlBm4EI3Qqu_VF3jhhSBt1DnhOTRgpFKm37S-PoHmvU,6459 scrapy/http/response/xml.py,sha256=W02SvIrRv6OMNwqP3m5fnQVRVlExrMDOYZyyoiuNxAI,296 scrapy/interfaces.py,sha256=DGvtWeh-AqQstCHTzhSTW7GR46OY0Q9Vyql0LVNCR-g,558 scrapy/item.py,sha256=A6K2CvBY_dGmjahs83QaVqjTl5OPSPUZrDRhxDYwWHA,2936 scrapy/link.py,sha256=Z8DIzb3SKfZFoyo9ZSaLVVYjxQYo-LxVbIjLj7-RPZ8,1456 scrapy/linkextractors/__init__.py,sha256=UxqtWN2RYU9M9rFS0s8CeDmj4D1KXE-whvI3S4PRUuY,4272 scrapy/linkextractors/__pycache__/__init__.cpython-36.pyc,, scrapy/linkextractors/__pycache__/htmlparser.cpython-36.pyc,, scrapy/linkextractors/__pycache__/lxmlhtml.cpython-36.pyc,, scrapy/linkextractors/__pycache__/regex.cpython-36.pyc,, scrapy/linkextractors/__pycache__/sgml.cpython-36.pyc,, scrapy/linkextractors/htmlparser.py,sha256=e02ScMDkPaft4X8aPIDboo0K0L4WmSSFgjRfDiK_tOs,3098 scrapy/linkextractors/lxmlhtml.py,sha256=3aLIZYqNdHYTiFlHbpNjIpcV1byScQnLTwIKnsGHYGc,5167 scrapy/linkextractors/regex.py,sha256=cFNdKeznrceSOjmFG7CneFMsi4Qt3e40-8PqFSsoPxQ,1365 scrapy/linkextractors/sgml.py,sha256=Yud2amivbIrv0RHFxJbKKjVfk1GuNNqdqKQUd5sK6bw,6174 scrapy/loader/__init__.py,sha256=t12Ut1BxLGYYnerT9c32bm5E2HWiq6H2xU912Ehwi-w,7377 scrapy/loader/__pycache__/__init__.cpython-36.pyc,, scrapy/loader/__pycache__/common.cpython-36.pyc,, scrapy/loader/__pycache__/processors.cpython-36.pyc,, scrapy/loader/common.py,sha256=w6UWdlw7XwgBY0KhHpHoCBDBSsDg6DAJpXt8jPkYjQw,467 scrapy/loader/processors.py,sha256=7yeJTlOl2HYHnv7siPpQgR5ZofepLJH18ufu-Pjb3is,3514 scrapy/logformatter.py,sha256=S_J90TIMaAWIL1J19dqOYyQVmaCoCf-hhu6TATr-TPQ,2669 scrapy/mail.py,sha256=nhEXQT_mW_KhIHe7SHc9E64jG4Ev2ByZHAJPorTIOoE,5008 scrapy/middleware.py,sha256=O5I6Y14LojjmM6b72s6xCiw2MzfcwiptK2vbmp_YJSo,2729 scrapy/mime.types,sha256=7qvGIyoPSzvg9yaUpGQ8Du29MCGWi4Em_W30NUnX8qQ,20392 scrapy/pipelines/__init__.py,sha256=weq8sXL8EXHmgxrP5jXwijVI7hSfDJPY60_tGRzwNJA,714 scrapy/pipelines/__pycache__/__init__.cpython-36.pyc,, scrapy/pipelines/__pycache__/files.cpython-36.pyc,, scrapy/pipelines/__pycache__/images.cpython-36.pyc,, scrapy/pipelines/__pycache__/media.cpython-36.pyc,, scrapy/pipelines/files.py,sha256=FuuOXlAR1uUbw8vGbGT1eJ1QvWcnT35vX_7PA43iWKE,17220 scrapy/pipelines/images.py,sha256=zYgT6LBmU7fC_9HSKb9kFT-pCxR_Qtmr6lLZk6yx0-E,6282 scrapy/pipelines/media.py,sha256=5uKBskmxqUv3iEhHSXZUth9ZWVDUPeVdGaS4CpjZnxA,7927 scrapy/pqueues.py,sha256=559g--Af_FuI7nqd-swG2pI6BhmL2mTxVnzk6wzzBPk,7020 scrapy/resolver.py,sha256=yvEwscKAwSN_k0rQcqKwZEmOoC89FGSzSD4SLgsFN-c,1114 scrapy/responsetypes.py,sha256=c-0mDpDd4AzRAWL07Njsn4YDnQeJKgaMo6SyhlSFwpo,4856 scrapy/selector/__init__.py,sha256=mqtn-787YUiKAQRNKSTrfcy7msFih5dvSfLk-Pxa0aE,56 scrapy/selector/__pycache__/__init__.cpython-36.pyc,, scrapy/selector/__pycache__/unified.cpython-36.pyc,, scrapy/selector/unified.py,sha256=GPGc-44XU8boqL6BW4MOKKPJLofAJJ5L46QuFMRmWbw,2751 scrapy/settings/__init__.py,sha256=ph4PLiBWcMLnJa5uk52W5cslp6VfZljM29g-yyUpiNE,15983 scrapy/settings/__pycache__/__init__.cpython-36.pyc,, scrapy/settings/__pycache__/default_settings.cpython-36.pyc,, scrapy/settings/__pycache__/deprecated.cpython-36.pyc,, scrapy/settings/default_settings.py,sha256=AB8f1BJ81PvT6c0ip7VvzuvWg-77rGQ1PugrM28Jk8M,8753 scrapy/settings/deprecated.py,sha256=QnHMsOyZ6FDD1h92Tev15HKgOt4MkUM8K8uLgxnAwRQ,1451 scrapy/shell.py,sha256=mQjwfVt_57lkBZONQBBxJBd12p6JSUfUTE05w7-7GjA,7545 scrapy/signalmanager.py,sha256=S1H3hKakZt6SihB9gjucPut9d_HtfMY8QpG4H5EcN84,2475 scrapy/signals.py,sha256=rhvhVrwAeiuB1dXBgnjRVybdOOKnvfyWyLnoEynOQMY,726 scrapy/spiderloader.py,sha256=QDSTZ7hZXI9x5_kyN611NxnZllyDv7MsG9o9S5KDSZc,2993 scrapy/spidermiddlewares/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 scrapy/spidermiddlewares/__pycache__/__init__.cpython-36.pyc,, scrapy/spidermiddlewares/__pycache__/depth.cpython-36.pyc,, scrapy/spidermiddlewares/__pycache__/httperror.cpython-36.pyc,, scrapy/spidermiddlewares/__pycache__/offsite.cpython-36.pyc,, scrapy/spidermiddlewares/__pycache__/referer.cpython-36.pyc,, scrapy/spidermiddlewares/__pycache__/urllength.cpython-36.pyc,, scrapy/spidermiddlewares/depth.py,sha256=9PKNJhjK5ifYSAQkPm7A9a0HPgdcXy1ljNrStmN8kE4,2020 scrapy/spidermiddlewares/httperror.py,sha256=S--1Fj3kDjGRpWxKrKBDI_ZbfKyTnXY1442GXx3WeLc,1921 scrapy/spidermiddlewares/offsite.py,sha256=oj7KXRCb1yVixLCEtQfpJ_88fS4MP_l4oUyKlD3mkyE,2563 scrapy/spidermiddlewares/referer.py,sha256=-qnECc8aGubdd2MNxFH-7KqCgTFiKwuB6cnddmnRe-U,13626 scrapy/spidermiddlewares/urllength.py,sha256=ZLzHSY8GlgYElyY4L2v-XzXQ7e9ukEZ22nPfRfeeZEc,1059 scrapy/spiders/__init__.py,sha256=7prK-GN_kfDtgqme7-40Br-R7DFuR-EUnaxVKjnHbD4,3370 scrapy/spiders/__pycache__/__init__.cpython-36.pyc,, scrapy/spiders/__pycache__/crawl.cpython-36.pyc,, scrapy/spiders/__pycache__/feed.cpython-36.pyc,, scrapy/spiders/__pycache__/init.cpython-36.pyc,, scrapy/spiders/__pycache__/sitemap.cpython-36.pyc,, scrapy/spiders/crawl.py,sha256=6-5o4H2gcpTCQ51kOMIAMedKuQ0oWlncIt-Zi0fYkZU,4382 scrapy/spiders/feed.py,sha256=uglx45zWWSCkHuMPxn-X_rBKc7qo3QU8Rz1gib4dyDo,5441 scrapy/spiders/init.py,sha256=6moM5Uc_JHkB3ktCiEALBGukUIgBGKcbvGrqaZTVP6U,1354 scrapy/spiders/sitemap.py,sha256=WOFv_p6cldLxaj4RDpdMYYXxqPFpG8aGiNp_3y_7NHs,3579 scrapy/squeues.py,sha256=dTxBInUZUvE-jODzXZsA3ZGogeH43MGdU_IzdqOp1Ok,1301 scrapy/statscollectors.py,sha256=lPGG3O2pifgY0hkPc47_BP1RxLpsC-4jLNG4BaxCC8U,2129 scrapy/templates/project/module/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 scrapy/templates/project/module/__pycache__/__init__.cpython-36.pyc,, scrapy/templates/project/module/items.py.tmpl,sha256=PhB4ktMFPN6sxgq7NvBBc-jmNUl9IqIufiRigI86LJg,295 scrapy/templates/project/module/middlewares.py.tmpl,sha256=KiJuaxDkJ2Ec7YlEZ1kare3_P7hH6Kk4il0gUDU0bFo,3613 scrapy/templates/project/module/pipelines.py.tmpl,sha256=3d07xChH5DWvqHOhxnqFvwbNwVTIkHQKl5KwO-s8W1M,296 scrapy/templates/project/module/settings.py.tmpl,sha256=Yl1ax5pQbCQb1lBf1VePOL65SFtWNPkzTqKD9bNTZUU,3162 scrapy/templates/project/module/spiders/__init__.py,sha256=ULwecZkx3_NTphkz7y_qiazBeUoHFnCCWnKSjoDCZj0,161 scrapy/templates/project/module/spiders/__pycache__/__init__.cpython-36.pyc,, scrapy/templates/project/scrapy.cfg,sha256=rRXe96NnAjpS8_2AtC_flgy7uleqtduLmPd-K720IG4,273 scrapy/templates/spiders/basic.tmpl,sha256=DbIobzgnP0SSwCUFdpvF79zcViqO7Hp3MKlrSEYlriI,208 scrapy/templates/spiders/crawl.tmpl,sha256=-X_oA4pShxJtcC6BsXXp3HljYeJDknBKG1uAueFmdHk,657 scrapy/templates/spiders/csvfeed.tmpl,sha256=uxN0675_-ntfDkK9OBiu0B7x7dSXmxYWj5G5fV-0vIo,571 scrapy/templates/spiders/xmlfeed.tmpl,sha256=cStRh3fgz_48X5B9tHtlqsyYbqfvBYC4cOTmzZx8nds,565 scrapy/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 scrapy/utils/__pycache__/__init__.cpython-36.pyc,, scrapy/utils/__pycache__/benchserver.cpython-36.pyc,, scrapy/utils/__pycache__/boto.cpython-36.pyc,, scrapy/utils/__pycache__/conf.cpython-36.pyc,, scrapy/utils/__pycache__/console.cpython-36.pyc,, scrapy/utils/__pycache__/datatypes.cpython-36.pyc,, scrapy/utils/__pycache__/decorators.cpython-36.pyc,, scrapy/utils/__pycache__/defer.cpython-36.pyc,, scrapy/utils/__pycache__/deprecate.cpython-36.pyc,, scrapy/utils/__pycache__/display.cpython-36.pyc,, scrapy/utils/__pycache__/engine.cpython-36.pyc,, scrapy/utils/__pycache__/ftp.cpython-36.pyc,, scrapy/utils/__pycache__/gz.cpython-36.pyc,, scrapy/utils/__pycache__/http.cpython-36.pyc,, scrapy/utils/__pycache__/httpobj.cpython-36.pyc,, scrapy/utils/__pycache__/iterators.cpython-36.pyc,, scrapy/utils/__pycache__/job.cpython-36.pyc,, scrapy/utils/__pycache__/log.cpython-36.pyc,, scrapy/utils/__pycache__/markup.cpython-36.pyc,, scrapy/utils/__pycache__/misc.cpython-36.pyc,, scrapy/utils/__pycache__/multipart.cpython-36.pyc,, scrapy/utils/__pycache__/ossignal.cpython-36.pyc,, scrapy/utils/__pycache__/project.cpython-36.pyc,, scrapy/utils/__pycache__/python.cpython-36.pyc,, scrapy/utils/__pycache__/reactor.cpython-36.pyc,, scrapy/utils/__pycache__/reqser.cpython-36.pyc,, scrapy/utils/__pycache__/request.cpython-36.pyc,, scrapy/utils/__pycache__/response.cpython-36.pyc,, scrapy/utils/__pycache__/serialize.cpython-36.pyc,, scrapy/utils/__pycache__/signal.cpython-36.pyc,, scrapy/utils/__pycache__/sitemap.cpython-36.pyc,, scrapy/utils/__pycache__/spider.cpython-36.pyc,, scrapy/utils/__pycache__/template.cpython-36.pyc,, scrapy/utils/__pycache__/test.cpython-36.pyc,, scrapy/utils/__pycache__/testproc.cpython-36.pyc,, scrapy/utils/__pycache__/testsite.cpython-36.pyc,, scrapy/utils/__pycache__/trackref.cpython-36.pyc,, scrapy/utils/__pycache__/url.cpython-36.pyc,, scrapy/utils/__pycache__/versions.cpython-36.pyc,, scrapy/utils/benchserver.py,sha256=WVbn3Qq78Ul7P8LbBPNxBp5-dh7h87STziVFnEVe044,1332 scrapy/utils/boto.py,sha256=XOuDGZFSFu52k-zT8HR7Vmza6RevrrckvXhPPyyt45M,494 scrapy/utils/conf.py,sha256=sDQtbM-G1vUhUy4ye3nY4g6pdHw6cv7r-xC3_TaIzlI,4102 scrapy/utils/console.py,sha256=o_8iJo5CarNN5NgSEMnxkTTRScmsP4-iULNTMsr1ZPA,3403 scrapy/utils/datatypes.py,sha256=M9Hb_GIy2E7Zi79acxIePD8WP_ns0gI4GGzlrj_KXhU,9823 scrapy/utils/decorators.py,sha256=OR-tu3Xh2JW4tQsPFw18K7BdlY4xU64ukpqTFBQ8t0k,1273 scrapy/utils/defer.py,sha256=k8gTXwubNeHa-dJ9kF910d0NVIxOIqNdrIMg7_wjGf4,3576 scrapy/utils/deprecate.py,sha256=e9JdhwgIg4ygfYtxBMXi_Vw7oy69CHn1nHs7Mkcd3ho,6710 scrapy/utils/display.py,sha256=e1fwP0uIEZyEmrJtYRynwKfrAfVPa58sh_NS1q3s7aM,699 scrapy/utils/engine.py,sha256=DdlrtdxTAAT-lnC325WfGRrjJVfYYs_EIy2fXZl0p5w,1376 scrapy/utils/ftp.py,sha256=Nt5QYvnBC1fs2RTm3dGfr5v1JeuXebS9Ass7bqjY6ds,531 scrapy/utils/gz.py,sha256=3Hn1C_ck0nzowXo4NWau67ecp3GAySxnWOQ5IbFQn2U,2200 scrapy/utils/http.py,sha256=lNaFKDZxXqbA-5kkCn_zMYp4s3KkSW-Q1Q8OC6uy8lw,905 scrapy/utils/httpobj.py,sha256=zrs-XKmo12LCXqSzQUbkp17tx8CzjiM_a8K14M0805s,516 scrapy/utils/iterators.py,sha256=KlR9nWVdWZ61YWwtCeY8KkMEp5VrM2IgPb7VUmE0l40,5025 scrapy/utils/job.py,sha256=9aMdjUE8yXj_TUbTVzTVmyXpmT8WSSuytNJNM1L7Tx8,148 scrapy/utils/log.py,sha256=oSB5QV5etHOBwpzF0rRUJwRcmkciWW7Fkh0t18UpyTU,6558 scrapy/utils/markup.py,sha256=PTuqniHxdLO9IgjgdJA9_1P1iUR6itySyN5VHzdh4ss,400 scrapy/utils/misc.py,sha256=loIAdMP21eLM26wbKNDg_8TgTyOaek1iC9E1MvWV4mg,5030 scrapy/utils/multipart.py,sha256=sNbnG1slp7cNnI7ZJBFRMWeQodlPFTR_Hr8ZG2-vhjY,488 scrapy/utils/ossignal.py,sha256=kxrCur_rPYVipHIBlwWHUScEFgULrC3UNi7IHIox_Kg,994 scrapy/utils/project.py,sha256=ufFEQ5QSJ2uG9DEakWSdNOVC1R86NsG-pf8LstH65VI,2590 scrapy/utils/python.py,sha256=m1ZocXLJHnxbhWHUw-ut1Rif8LNqWFSaWZCXwagaXhc,11805 scrapy/utils/reactor.py,sha256=LkmKoT-YLTmIvCrBsvuPR_1Frkmj_0HAeOays4F9ztQ,1360 scrapy/utils/reqser.py,sha256=E1bvBMrP_lKufCXUp_pbRfZtdTmps7lq0QUaPHU9LlM,3213 scrapy/utils/request.py,sha256=Psnh6DX1vPjCIxVrYf19Zlrqh0FmH_xGj45qdeg9dGM,3459 scrapy/utils/response.py,sha256=lI_NJ-oYJOQuWTXHh61Bmu0eY9qh6jVqAepI7e5A9-Y,2665 scrapy/utils/serialize.py,sha256=J3T9E05j8HXqoqHuX_ZWSSqDes07iirCRl_BznHeyxg,1201 scrapy/utils/signal.py,sha256=b4fTZbiqVSxZazdGmLLBirKHHW0U7e-7XqbWHd_5a04,2969 scrapy/utils/sitemap.py,sha256=PSi3joL-4nVbBwhOqasDnOFcCQP8VA-BTtvEqX134as,1518 scrapy/utils/spider.py,sha256=VdMMl1EhmN65nA3tC-Z4uKn-wKfBaGApsbJjGZZnUJw,1911 scrapy/utils/template.py,sha256=JNCXL8NT0gGFgEK4aC0oCeUQlKOWzisdjdGNvnPJ4Q0,816 scrapy/utils/test.py,sha256=fhMskcoxNFyNeSS9EZ1cCt_StVNgyr0UmRhUxdIW-cw,3089 scrapy/utils/testproc.py,sha256=xDcuLRPWChiTL7L7wwYOT9XZjdzQUu0tDsMKyFSXzwc,1508 scrapy/utils/testsite.py,sha256=yDS8GwhSKKBuNLCswrrmD2GfsB827sTlKfuQ8iorxao,1562 scrapy/utils/trackref.py,sha256=rg82Iib9fkjqkfmFdE507VVxcOBfycG_FZZ9Hldyz08,2081 scrapy/utils/url.py,sha256=5sWMcSbQQBe53pa2v5JOPMSq2cQmzsI09OEvQdCg0W8,5119 scrapy/utils/versions.py,sha256=eMWzL4F0jIWnSxlSd-hysa9LoCSJjc9cwirxsdlWZIg,1419 scrapy/xlib/__init__.py,sha256=CbHNJHO8-CRSs6dP3WIWf1u4ruo2KyTrio-GBpxr45Y,92 scrapy/xlib/__pycache__/__init__.cpython-36.pyc,, scrapy/xlib/__pycache__/pydispatch.cpython-36.pyc,, scrapy/xlib/__pycache__/tx.cpython-36.pyc,, scrapy/xlib/pydispatch.py,sha256=Z4y2vxQ5k4SrDfLfjJsR2BUGNY0Pghn9lmVqpJEXyRo,629 scrapy/xlib/tx.py,sha256=v08NnjBxl_kdLlCVSLEJcyEti-DHhw2Sklai2eCZhbY,749 ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/Scrapy-1.7.4.dist-info/WHEEL ================================================ Wheel-Version: 1.0 Generator: bdist_wheel (0.33.6) Root-Is-Purelib: true Tag: py2-none-any Tag: py3-none-any ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/Scrapy-1.7.4.dist-info/entry_points.txt ================================================ [console_scripts] scrapy = scrapy.cmdline:execute ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/Scrapy-1.7.4.dist-info/top_level.txt ================================================ scrapy ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/Twisted-19.7.0.dist-info/INSTALLER ================================================ pip ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/Twisted-19.7.0.dist-info/LICENSE ================================================ Copyright (c) 2001-2019 Allen Short Amber Hawkie Brown Andrew Bennetts Andy Gayton Antoine Pitrou Apple Computer, Inc. Ashwini Oruganti Benjamin Bruheim Bob Ippolito Canonical Limited Christopher Armstrong Ciena Corporation David Reid Divmod Inc. Donovan Preston Eric Mangold Eyal Lotem Google Inc. Hybrid Logic Ltd. Hynek Schlawack Itamar Turner-Trauring James Knight Jason A. Mobarak Jean-Paul Calderone Jessica McKellar Jonathan D. Simms Jonathan Jacobs Jonathan Lange Julian Berman Jürgen Hermann Kevin Horn Kevin Turner Laurens Van Houtven Mary Gardiner Massachusetts Institute of Technology Matthew Lefkowitz Moshe Zadka Paul Swartz Pavel Pergamenshchik Rackspace, US Inc. Ralph Meijer Richard Wall Sean Riley Software Freedom Conservancy Tavendo GmbH Thijs Triemstra Thomas Herve Timothy Allen Tom Most Tom Prince Travis B. Hartwell and others that have contributed code to the public domain. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/Twisted-19.7.0.dist-info/METADATA ================================================ Metadata-Version: 2.1 Name: Twisted Version: 19.7.0 Summary: An asynchronous networking framework written in Python Home-page: https://twistedmatrix.com/ Author: Twisted Matrix Laboratories Author-email: twisted-python@twistedmatrix.com Maintainer: Glyph Lefkowitz Maintainer-email: glyph@twistedmatrix.com License: MIT Project-URL: Documentation, https://twistedmatrix.com/documents/current/ Project-URL: Source, https://github.com/twisted/twisted Project-URL: Issues, https://twistedmatrix.com/trac/report Platform: UNKNOWN Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: 3.5 Classifier: Programming Language :: Python :: 3.6 Classifier: Programming Language :: Python :: 3.7 Description-Content-Type: text/x-rst Requires-Dist: zope.interface (>=4.4.2) Requires-Dist: constantly (>=15.1) Requires-Dist: incremental (>=16.10.1) Requires-Dist: Automat (>=0.3.0) Requires-Dist: hyperlink (>=17.1.1) Requires-Dist: PyHamcrest (>=1.9.0) Requires-Dist: attrs (>=17.4.0) Provides-Extra: all_non_platform Requires-Dist: pyopenssl (>=16.0.0) ; extra == 'all_non_platform' Requires-Dist: service-identity (>=18.1.0) ; extra == 'all_non_platform' Requires-Dist: idna (!=2.3,>=0.6) ; extra == 'all_non_platform' Requires-Dist: pyasn1 ; extra == 'all_non_platform' Requires-Dist: cryptography (>=2.5) ; extra == 'all_non_platform' Requires-Dist: appdirs (>=1.4.0) ; extra == 'all_non_platform' Requires-Dist: bcrypt (>=3.0.0) ; extra == 'all_non_platform' Requires-Dist: soappy ; extra == 'all_non_platform' Requires-Dist: pyserial (>=3.0) ; extra == 'all_non_platform' Requires-Dist: h2 (<4.0,>=3.0) ; extra == 'all_non_platform' Requires-Dist: priority (<2.0,>=1.1.0) ; extra == 'all_non_platform' Provides-Extra: conch Requires-Dist: pyasn1 ; extra == 'conch' Requires-Dist: cryptography (>=2.5) ; extra == 'conch' Requires-Dist: appdirs (>=1.4.0) ; extra == 'conch' Requires-Dist: bcrypt (>=3.0.0) ; extra == 'conch' Provides-Extra: dev Requires-Dist: pyflakes (>=1.0.0) ; extra == 'dev' Requires-Dist: twisted-dev-tools (>=0.0.2) ; extra == 'dev' Requires-Dist: python-subunit ; extra == 'dev' Requires-Dist: sphinx (>=1.3.1) ; extra == 'dev' Requires-Dist: towncrier (>=17.4.0) ; extra == 'dev' Provides-Extra: http2 Requires-Dist: h2 (<4.0,>=3.0) ; extra == 'http2' Requires-Dist: priority (<2.0,>=1.1.0) ; extra == 'http2' Provides-Extra: macos_platform Requires-Dist: pyobjc-core ; extra == 'macos_platform' Requires-Dist: pyobjc-framework-CFNetwork ; extra == 'macos_platform' Requires-Dist: pyobjc-framework-Cocoa ; extra == 'macos_platform' Requires-Dist: pyopenssl (>=16.0.0) ; extra == 'macos_platform' Requires-Dist: service-identity (>=18.1.0) ; extra == 'macos_platform' Requires-Dist: idna (!=2.3,>=0.6) ; extra == 'macos_platform' Requires-Dist: pyasn1 ; extra == 'macos_platform' Requires-Dist: cryptography (>=2.5) ; extra == 'macos_platform' Requires-Dist: appdirs (>=1.4.0) ; extra == 'macos_platform' Requires-Dist: bcrypt (>=3.0.0) ; extra == 'macos_platform' Requires-Dist: soappy ; extra == 'macos_platform' Requires-Dist: pyserial (>=3.0) ; extra == 'macos_platform' Requires-Dist: h2 (<4.0,>=3.0) ; extra == 'macos_platform' Requires-Dist: priority (<2.0,>=1.1.0) ; extra == 'macos_platform' Provides-Extra: osx_platform Requires-Dist: pyobjc-core ; extra == 'osx_platform' Requires-Dist: pyobjc-framework-CFNetwork ; extra == 'osx_platform' Requires-Dist: pyobjc-framework-Cocoa ; extra == 'osx_platform' Requires-Dist: pyopenssl (>=16.0.0) ; extra == 'osx_platform' Requires-Dist: service-identity (>=18.1.0) ; extra == 'osx_platform' Requires-Dist: idna (!=2.3,>=0.6) ; extra == 'osx_platform' Requires-Dist: pyasn1 ; extra == 'osx_platform' Requires-Dist: cryptography (>=2.5) ; extra == 'osx_platform' Requires-Dist: appdirs (>=1.4.0) ; extra == 'osx_platform' Requires-Dist: bcrypt (>=3.0.0) ; extra == 'osx_platform' Requires-Dist: soappy ; extra == 'osx_platform' Requires-Dist: pyserial (>=3.0) ; extra == 'osx_platform' Requires-Dist: h2 (<4.0,>=3.0) ; extra == 'osx_platform' Requires-Dist: priority (<2.0,>=1.1.0) ; extra == 'osx_platform' Provides-Extra: serial Requires-Dist: pyserial (>=3.0) ; extra == 'serial' Provides-Extra: soap Requires-Dist: soappy ; extra == 'soap' Provides-Extra: tls Requires-Dist: pyopenssl (>=16.0.0) ; extra == 'tls' Requires-Dist: service-identity (>=18.1.0) ; extra == 'tls' Requires-Dist: idna (!=2.3,>=0.6) ; extra == 'tls' Provides-Extra: windows_platform Requires-Dist: pywin32 ; extra == 'windows_platform' Requires-Dist: pyopenssl (>=16.0.0) ; extra == 'windows_platform' Requires-Dist: service-identity (>=18.1.0) ; extra == 'windows_platform' Requires-Dist: idna (!=2.3,>=0.6) ; extra == 'windows_platform' Requires-Dist: pyasn1 ; extra == 'windows_platform' Requires-Dist: cryptography (>=2.5) ; extra == 'windows_platform' Requires-Dist: appdirs (>=1.4.0) ; extra == 'windows_platform' Requires-Dist: bcrypt (>=3.0.0) ; extra == 'windows_platform' Requires-Dist: soappy ; extra == 'windows_platform' Requires-Dist: pyserial (>=3.0) ; extra == 'windows_platform' Requires-Dist: h2 (<4.0,>=3.0) ; extra == 'windows_platform' Requires-Dist: priority (<2.0,>=1.1.0) ; extra == 'windows_platform' Twisted ======= |pypi|_ |travis|_ |circleci|_ For information on what's new in Twisted 19.2.0, see the `NEWS `_ file that comes with the distribution. What is this? ------------- Twisted is an event-based framework for internet applications, supporting Python 2.7 and Python 3.5+. It includes modules for many different purposes, including the following: - ``twisted.web``: HTTP clients and servers, HTML templating, and a WSGI server - ``twisted.conch``: SSHv2 and Telnet clients and servers and terminal emulators - ``twisted.words``: Clients and servers for IRC, XMPP, and other IM protocols - ``twisted.mail``: IMAPv4, POP3, SMTP clients and servers - ``twisted.positioning``: Tools for communicating with NMEA-compatible GPS receivers - ``twisted.names``: DNS client and tools for making your own DNS servers - ``twisted.trial``: A unit testing framework that integrates well with Twisted-based code. Twisted supports all major system event loops -- ``select`` (all platforms), ``poll`` (most POSIX platforms), ``epoll`` (Linux), ``kqueue`` (FreeBSD, macOS), IOCP (Windows), and various GUI event loops (GTK+2/3, Qt, wxWidgets). Third-party reactors can plug into Twisted, and provide support for additional event loops. Installing ---------- To install the latest version of Twisted using pip:: $ pip install twisted Additional instructions for installing this software are in `the installation instructions `_. Documentation and Support ------------------------- Twisted's documentation is available from the `Twisted Matrix website `_. This documentation contains how-tos, code examples, and an API reference. Help is also available on the `Twisted mailing list `_. There is also a pair of very lively IRC channels, ``#twisted`` (for general Twisted questions) and ``#twisted.web`` (for Twisted Web), on ``chat.freenode.net``. Unit Tests ---------- Twisted has a comprehensive test suite, which can be run by ``tox``:: $ tox -l # to view all test environments $ tox -e py27-tests # to run the tests for Python 2.7 $ tox -e py35-tests # to run the tests for Python 3.5 You can test running the test suite under the different reactors with the ``TWISTED_REACTOR`` environment variable:: $ env TWISTED_REACTOR=epoll tox -e py27-tests Some of these tests may fail if you: * don't have the dependencies required for a particular subsystem installed, * have a firewall blocking some ports (or things like Multicast, which Linux NAT has shown itself to do), or * run them as root. Copyright --------- All of the code in this distribution is Copyright (c) 2001-2019 Twisted Matrix Laboratories. Twisted is made available under the MIT license. The included `LICENSE `_ file describes this in detail. Warranty -------- THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE USE OF THIS SOFTWARE IS WITH YOU. IN NO EVENT WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY, BE LIABLE TO YOU FOR ANY DAMAGES, EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. Again, see the included `LICENSE `_ file for specific legal details. .. |pypi| image:: http://img.shields.io/pypi/v/twisted.svg .. _pypi: https://pypi.python.org/pypi/twisted .. |travis| image:: https://travis-ci.org/twisted/twisted.svg?branch=trunk .. _travis: https://travis-ci.org/twisted/twisted .. |circleci| image:: https://circleci.com/gh/twisted/twisted.svg?style=svg .. _circleci: https://circleci.com/gh/twisted/twisted ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/Twisted-19.7.0.dist-info/RECORD ================================================ ../../../bin/cftp,sha256=uQ-4stYf8E120-asLychp7hW1VjLJxFL_6HNQI0aHdo,289 ../../../bin/ckeygen,sha256=4GXdm-6Esn7pGzUxOvnNH_g6nl_jIsNazaBBzD_dkM4,292 ../../../bin/conch,sha256=_8hQIr6ODtna6muwkpUnV333R-PyKSOVPjW0PORO3Ho,290 ../../../bin/mailmail,sha256=QXut2P7LTlyKMFD6eM8uDlaXlUwnm523mrKmxiYgd4Y,292 ../../../bin/pyhtmlizer,sha256=fcX6JmFsYRGMDV9hyV1PULC6x3vJhi3fNW8hwlZVLdg,287 ../../../bin/tkconch,sha256=m7e0vrKcr_kYHru2A8qfTV-LynkDFJIc4uMZGh8yEMM,292 ../../../bin/trial,sha256=m3QRoAfu-MXf3yMnwDsRzEayV-GGnxNl5J9Si3psuX4,284 ../../../bin/twist,sha256=kJTyCYIA1VJw8qmtYnumNRt2eOljm68iOeauiljwibY,304 ../../../bin/twistd,sha256=RnXH8pBHK-V3QlTXoxihOlZjhkudgOV1hJr174Z7Sw0,285 Twisted-19.7.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 Twisted-19.7.0.dist-info/LICENSE,sha256=hbeYQTuohbBswbke_oV6OfaUBxwpsE6A0j6ibuJx1hM,1926 Twisted-19.7.0.dist-info/METADATA,sha256=9lvJRkxJOpFZ8fFA81XkDN6jkCljIvfEvxHUTrWRyFo,9321 Twisted-19.7.0.dist-info/RECORD,, Twisted-19.7.0.dist-info/WHEEL,sha256=q6ZS0x11G9XscKQI--PbS172VpPpBOOoLI4QlxtsUa0,109 Twisted-19.7.0.dist-info/entry_points.txt,sha256=UK8U0KNTSAegCW9a4j4bDwbOO5c1579QKqXzwsPPcnI,394 Twisted-19.7.0.dist-info/top_level.txt,sha256=e9eVTH2N7T_qnhIPUQhDQilKWgnW7rTHCvHGyd7xp0k,8 twisted/__init__.py,sha256=A7hcrXmwPGeAGHDPU_wyOTjgqRHAPAuLVvMI9E6xblg,256 twisted/__main__.py,sha256=-IXh5Xk046Kf8k4NqwciSb4K6q4X4RnKEMwsrbrsn9g,448 twisted/__pycache__/__init__.cpython-36.pyc,, twisted/__pycache__/__main__.cpython-36.pyc,, twisted/__pycache__/_version.cpython-36.pyc,, twisted/__pycache__/copyright.cpython-36.pyc,, twisted/__pycache__/plugin.cpython-36.pyc,, twisted/_threads/__init__.py,sha256=XUQc4vy6dlY3VYcNQZEGPOThfz6cB6x9-ySpiv3eW8w,570 twisted/_threads/__pycache__/__init__.cpython-36.pyc,, twisted/_threads/__pycache__/_convenience.cpython-36.pyc,, twisted/_threads/__pycache__/_ithreads.cpython-36.pyc,, twisted/_threads/__pycache__/_memory.cpython-36.pyc,, twisted/_threads/__pycache__/_pool.cpython-36.pyc,, twisted/_threads/__pycache__/_team.cpython-36.pyc,, twisted/_threads/__pycache__/_threadworker.cpython-36.pyc,, twisted/_threads/_convenience.py,sha256=bME26wNYCSEtoVqCOSqqwMyEhgU9_UXzFu4r-lK9fsI,969 twisted/_threads/_ithreads.py,sha256=phOeuVsKw3K-BPex6ZutkvNyij8nrYZAmhVgi5wERUo,1810 twisted/_threads/_memory.py,sha256=8V-KVBG6ngic_XNenwGAslQWsNyoeRhn4Hd5vv4ByoY,1666 twisted/_threads/_pool.py,sha256=_Nw_ltHAfF24Vy72CoxPXiNkUAfRUlLD3PFiavzy00E,2399 twisted/_threads/_team.py,sha256=60gJbzlRrx6Ga8Qse7Klpsv5Sqc4a1DYGh52Qt1GJVA,7259 twisted/_threads/_threadworker.py,sha256=GnzPGY_4nz9_aohIK4l_UnEPEg-o-0u4jCmR8emV4AE,3376 twisted/_threads/test/__init__.py,sha256=-tNWrOXAaGo9x-k49W4kk9ol44DaBbLFeBSZaHxtzKk,226 twisted/_threads/test/__pycache__/__init__.cpython-36.pyc,, twisted/_threads/test/__pycache__/test_convenience.cpython-36.pyc,, twisted/_threads/test/__pycache__/test_memory.cpython-36.pyc,, twisted/_threads/test/__pycache__/test_team.cpython-36.pyc,, twisted/_threads/test/__pycache__/test_threadworker.cpython-36.pyc,, twisted/_threads/test/test_convenience.py,sha256=-088jkN0O_GroTglswcmnzz9iS7vUdLvOwN0nwMcJuE,1442 twisted/_threads/test/test_memory.py,sha256=H3pafUk-1CJL3kE7JM_zQKd0Dte6twFJqFD4j3ntkNY,2148 twisted/_threads/test/test_team.py,sha256=zY3BDEA5TrQgL5ka1WHOFC4A-6NNA0QU2Th8FBgi5G0,9534 twisted/_threads/test/test_threadworker.py,sha256=O5QpeGz0vLPApZV1jmnq29jfhG9y8MV8ygnh_4A_YXw,8093 twisted/_version.py,sha256=2gUxEnRoE1XvGCGzKAozLESbm4b5o6Aaa8H9hqtyLFk,260 twisted/application/__init__.py,sha256=qAl6aEqUMpJJXs69xa8mxSVpiE4E9MzMkKWX26xo8MM,129 twisted/application/__pycache__/__init__.cpython-36.pyc,, twisted/application/__pycache__/app.cpython-36.pyc,, twisted/application/__pycache__/internet.cpython-36.pyc,, twisted/application/__pycache__/reactors.cpython-36.pyc,, twisted/application/__pycache__/service.cpython-36.pyc,, twisted/application/__pycache__/strports.cpython-36.pyc,, twisted/application/app.py,sha256=bILSMk-3-7MLqoZf7OpbbXwZpxu9KSPAeC52WjR26Hg,23465 twisted/application/internet.py,sha256=EzTydNA6GYP6bPhkw1Bs4u_hxmGmd-RE_oQwpZszXSg,36974 twisted/application/reactors.py,sha256=p0LAxCG6gUX4L5k07rIaDhwXZu22pyxaELpoD7USe1M,2169 twisted/application/runner/__init__.py,sha256=oAOyWGGBaaPSeeHS_vHk2pvip3_-nPVZlPvIf4EkKh4,185 twisted/application/runner/__pycache__/__init__.cpython-36.pyc,, twisted/application/runner/__pycache__/_exit.cpython-36.pyc,, twisted/application/runner/__pycache__/_pidfile.cpython-36.pyc,, twisted/application/runner/__pycache__/_runner.cpython-36.pyc,, twisted/application/runner/_exit.py,sha256=injGMM6zHAa488X2m7VE_ImIKxRHR76aXIuGftbTZyQ,3984 twisted/application/runner/_pidfile.py,sha256=7PJHb2IBI5nz6280u_LpE1yoR0SbbojjJBPvIJHlECQ,6995 twisted/application/runner/_runner.py,sha256=A2wlGmCgxoWMn48mK-AkN74MeODYbfvhzGU6nxCngK0,5765 twisted/application/runner/test/__init__.py,sha256=NAk9flgxX4siFhfJm6zpSt9odTHr3mmjQeuq-SOBobo,180 twisted/application/runner/test/__pycache__/__init__.cpython-36.pyc,, twisted/application/runner/test/__pycache__/test_exit.cpython-36.pyc,, twisted/application/runner/test/__pycache__/test_pidfile.cpython-36.pyc,, twisted/application/runner/test/__pycache__/test_runner.cpython-36.pyc,, twisted/application/runner/test/test_exit.py,sha256=M3WZICqMykDZg-02VMo2p8QIuyoONkmjMDFKFfIaKMw,2489 twisted/application/runner/test/test_pidfile.py,sha256=7VHnxmHJJk-_w-77Egk6zm2u-LoN5Sc-DX_Sif-7yHo,12984 twisted/application/runner/test/test_runner.py,sha256=RZkx-HqEe0lqyTN3QX6t7y7kUbsChAfRo4R5HWKf0s0,13293 twisted/application/service.py,sha256=7JGdq40MJ_8lgOmEqu_vR7oQHaiXE2H_51hzpneTSJA,12021 twisted/application/strports.py,sha256=n8kh_673Beui-gQQu5xj7lYxgNyzXWg4IzNNO39UIjk,2233 twisted/application/test/__init__.py,sha256=QJh3C_0yH0jDm6ViNbaoefp_no7sv7FyuV32ZYWE75s,124 twisted/application/test/__pycache__/__init__.cpython-36.pyc,, twisted/application/test/__pycache__/test_internet.cpython-36.pyc,, twisted/application/test/__pycache__/test_service.cpython-36.pyc,, twisted/application/test/test_internet.py,sha256=bBcMqDsAoXDy88xg5X1nkm8tMruEYBtVmkCkylyeyoI,42340 twisted/application/test/test_service.py,sha256=YPdTXv2BdRFUOyJdhKO8cPtdplxOmwi1fQjcft_Kw4M,5091 twisted/application/twist/__init__.py,sha256=YPzoFOyJSICe6QB4XZXFxNyJWsRru-RRvYizhrN9jJE,166 twisted/application/twist/__pycache__/__init__.cpython-36.pyc,, twisted/application/twist/__pycache__/_options.cpython-36.pyc,, twisted/application/twist/__pycache__/_twist.cpython-36.pyc,, twisted/application/twist/_options.py,sha256=7SUx3kQpZbmXEUusRl4tJrGqv0s78GHJGjSOcWk5088,5719 twisted/application/twist/_twist.py,sha256=hmdSn31p0CPsBupdKoaa_RvTShH4gwigOyuYsJns3to,3499 twisted/application/twist/test/__init__.py,sha256=B0KIIGDdfaLWhGhs1WBlDQoABIMxwJBl5tSEQmIkoBo,178 twisted/application/twist/test/__pycache__/__init__.cpython-36.pyc,, twisted/application/twist/test/__pycache__/test_options.cpython-36.pyc,, twisted/application/twist/test/__pycache__/test_twist.cpython-36.pyc,, twisted/application/twist/test/test_options.py,sha256=XP8TpbptQST3zFChhBxGJ8SKqUdloxYhEPrUznFHPMc,10906 twisted/application/twist/test/test_twist.py,sha256=SkVSPN9RcaXZMBVzx3QqnBf2Ljquvjcldb4kZo_DzqI,7618 twisted/conch/__init__.py,sha256=ePuf1Y1dXhse4EBuyIQUPsHFurM3l28cenQc9R3fL3A,198 twisted/conch/__pycache__/__init__.cpython-36.pyc,, twisted/conch/__pycache__/avatar.cpython-36.pyc,, twisted/conch/__pycache__/checkers.cpython-36.pyc,, twisted/conch/__pycache__/endpoints.cpython-36.pyc,, twisted/conch/__pycache__/error.cpython-36.pyc,, twisted/conch/__pycache__/interfaces.cpython-36.pyc,, twisted/conch/__pycache__/ls.cpython-36.pyc,, twisted/conch/__pycache__/manhole.cpython-36.pyc,, twisted/conch/__pycache__/manhole_ssh.cpython-36.pyc,, twisted/conch/__pycache__/manhole_tap.cpython-36.pyc,, twisted/conch/__pycache__/mixin.cpython-36.pyc,, twisted/conch/__pycache__/recvline.cpython-36.pyc,, twisted/conch/__pycache__/stdio.cpython-36.pyc,, twisted/conch/__pycache__/tap.cpython-36.pyc,, twisted/conch/__pycache__/telnet.cpython-36.pyc,, twisted/conch/__pycache__/ttymodes.cpython-36.pyc,, twisted/conch/__pycache__/unix.cpython-36.pyc,, twisted/conch/avatar.py,sha256=cJqlSmAbhtnxxsBFLvQ6-kRvbnDSuf4FvnrpvZqEo_Y,1438 twisted/conch/checkers.py,sha256=UPSJAg4CXSF8Sr1e6CvPYyOcrDJjCr9LLpj3kFisD_M,19742 twisted/conch/client/__init__.py,sha256=vbi0H87oC9ZMg2pFDUwAa-W7W7XDnFnrglQ3S1TOxKM,139 twisted/conch/client/__pycache__/__init__.cpython-36.pyc,, twisted/conch/client/__pycache__/agent.cpython-36.pyc,, twisted/conch/client/__pycache__/connect.cpython-36.pyc,, twisted/conch/client/__pycache__/default.cpython-36.pyc,, twisted/conch/client/__pycache__/direct.cpython-36.pyc,, twisted/conch/client/__pycache__/knownhosts.cpython-36.pyc,, twisted/conch/client/__pycache__/options.cpython-36.pyc,, twisted/conch/client/agent.py,sha256=0barVVIXiD1O_DvfBdGsRobOS2i9pH1tHXuqq_kA1jo,1730 twisted/conch/client/connect.py,sha256=mEiTeBIhhKdZZkb-qYNwZ_RC75CZ1hf9A_b0Rg7eHuw,672 twisted/conch/client/default.py,sha256=ekQY-TV_kubRLcp2YGdEi3C1OnAc1_egRVV3qlP5VAQ,11976 twisted/conch/client/direct.py,sha256=O7Jf4KPh7cyh67VqD8HokSKWQtsyG6dAnexAFY-BbpU,3264 twisted/conch/client/knownhosts.py,sha256=MiXC4BSXkxq8AsvLhPA_wcgSywBwFOCD7KYvzUocDzA,19875 twisted/conch/client/options.py,sha256=MJPpxYF36jME_VH-b54klDTdCIlS5YevnDq_ozodjtg,4145 twisted/conch/endpoints.py,sha256=jOs-YG4F9qaZubNI2xKeKbJ5oXJ0cRym6EeqmO69FM8,29743 twisted/conch/error.py,sha256=ynbrCK0fo_wdvyUhbV5GsMVvNjbNIFZHzvoT05hOEyg,2716 twisted/conch/insults/__init__.py,sha256=PALruuxw5vHDKLyzbY6XUcn73FFKhMk44dRQpFdrJvc,76 twisted/conch/insults/__pycache__/__init__.cpython-36.pyc,, twisted/conch/insults/__pycache__/helper.cpython-36.pyc,, twisted/conch/insults/__pycache__/insults.cpython-36.pyc,, twisted/conch/insults/__pycache__/text.cpython-36.pyc,, twisted/conch/insults/__pycache__/window.cpython-36.pyc,, twisted/conch/insults/helper.py,sha256=SwL14WVDDvHl1uWesi0c0H4BD6JLjgDsY2TUsg3IFPo,14396 twisted/conch/insults/insults.py,sha256=8q8d5kxf0ah9xgxgzaSfeYDqBhbpCtsO7_k06TOl-BQ,35589 twisted/conch/insults/text.py,sha256=Cc07uGyoLNcsmtsd_uGMj0aT37zZbUamJB2J4uiXqlk,5424 twisted/conch/insults/window.py,sha256=eC-Delffu-yT-cKOvkvPpm_Ft9nRYk8QF8_zNuJo8Sg,27812 twisted/conch/interfaces.py,sha256=6pOyjMrOXPqS1TVwYuoiXSoutO4Wmq-RbiXO1E3p_tI,13636 twisted/conch/ls.py,sha256=1KtrdFww3j6bIEY2gZ0y_gi4TBy6CLQsoHUzWRcsUR8,2551 twisted/conch/manhole.py,sha256=wjpTsXUQ2QRbev_1WcJ9Z-2pbi1J5OKmHY2XoeLUpeQ,11832 twisted/conch/manhole_ssh.py,sha256=NqYFUy305e1DH1WQ3X2SFEG8UPZ6aD8CMKfiQ_4Iduk,3990 twisted/conch/manhole_tap.py,sha256=Q5Ljl6d73Shi_84GNeAmnIcZKFo_MTkhaPBZIKvW9bs,5370 twisted/conch/mixin.py,sha256=8haxUUg5oxVCUzJ71-agK4lJ_ObJ828O2U2sds8dGPM,1374 twisted/conch/openssh_compat/__init__.py,sha256=uIe8Ifysdq6wuLyqjeMXT81DKsZw56QqgxWazKZERu0,152 twisted/conch/openssh_compat/__pycache__/__init__.cpython-36.pyc,, twisted/conch/openssh_compat/__pycache__/factory.cpython-36.pyc,, twisted/conch/openssh_compat/__pycache__/primes.cpython-36.pyc,, twisted/conch/openssh_compat/factory.py,sha256=csprCbaqAQV2V3jcm0jmltxDnl4nY8v3hH7ztTf3lNE,2323 twisted/conch/openssh_compat/primes.py,sha256=_RyvlWjxwymp18gcA0HaiISr8OPwXM3WmsdowkTybeg,682 twisted/conch/recvline.py,sha256=jre0-Le7dp-RplyURznthdQuhu1ZQ5JC7V2YT93EK20,11523 twisted/conch/scripts/__init__.py,sha256=UJRr3MgRq7dcUk9OBG9M0jOmMs2H746XbolCl0dZgwI,16 twisted/conch/scripts/__pycache__/__init__.cpython-36.pyc,, twisted/conch/scripts/__pycache__/cftp.cpython-36.pyc,, twisted/conch/scripts/__pycache__/ckeygen.cpython-36.pyc,, twisted/conch/scripts/__pycache__/conch.cpython-36.pyc,, twisted/conch/scripts/__pycache__/tkconch.cpython-36.pyc,, twisted/conch/scripts/cftp.py,sha256=TF1LsKgpmK1nCM_Z-2mgdP2ArVwULAYW44zWesmStkM,31775 twisted/conch/scripts/ckeygen.py,sha256=fceeMBsu3imO-lINBtU72KDMJMsXAT9t74jI9C9Mq6I,10078 twisted/conch/scripts/conch.py,sha256=gNpQFxlMJsrockj4-14kIqkHgEbB1l-xiXK5pQdeVEA,18462 twisted/conch/scripts/tkconch.py,sha256=nuBbI7FPh-ufV-RZGqOHFtJoN1-btbzjWE9LBsNd1_s,23189 twisted/conch/ssh/__init__.py,sha256=IDSvIu8OyDtv2iyBNQlgpZCYPmRDQ1OWBYDm2FUnSXM,183 twisted/conch/ssh/__pycache__/__init__.cpython-36.pyc,, twisted/conch/ssh/__pycache__/_kex.cpython-36.pyc,, twisted/conch/ssh/__pycache__/address.cpython-36.pyc,, twisted/conch/ssh/__pycache__/agent.cpython-36.pyc,, twisted/conch/ssh/__pycache__/channel.cpython-36.pyc,, twisted/conch/ssh/__pycache__/common.cpython-36.pyc,, twisted/conch/ssh/__pycache__/connection.cpython-36.pyc,, twisted/conch/ssh/__pycache__/factory.cpython-36.pyc,, twisted/conch/ssh/__pycache__/filetransfer.cpython-36.pyc,, twisted/conch/ssh/__pycache__/forwarding.cpython-36.pyc,, twisted/conch/ssh/__pycache__/keys.cpython-36.pyc,, twisted/conch/ssh/__pycache__/service.cpython-36.pyc,, twisted/conch/ssh/__pycache__/session.cpython-36.pyc,, twisted/conch/ssh/__pycache__/sexpy.cpython-36.pyc,, twisted/conch/ssh/__pycache__/transport.cpython-36.pyc,, twisted/conch/ssh/__pycache__/userauth.cpython-36.pyc,, twisted/conch/ssh/_kex.py,sha256=keHgecXDjuUHu_hv21Aaq6FBasMUZqFk1BtDAZ8DhUE,7668 twisted/conch/ssh/address.py,sha256=2ZCPpaUa_Evaj_M_KjbBzllx2gf1l2DQt30rXJwL_-s,1158 twisted/conch/ssh/agent.py,sha256=YITkSpOpiaNSI6EBt4M2EKogOk0Rlj4_QJX0lznRsAs,9692 twisted/conch/ssh/channel.py,sha256=nS1uE0DmZWUvp0vESpSQoanfktxYI50WNV6Sdfyrz1U,9852 twisted/conch/ssh/common.py,sha256=B9LRnUkmWZoQOF1PRFk6b-85_NH1jRzMaE0ROPZk1KY,2059 twisted/conch/ssh/connection.py,sha256=oTD85RQqrKGjHfRBG_PFNoMAJzLc8v6FvZpPY86Vxy0,26151 twisted/conch/ssh/factory.py,sha256=X28xtqHwEpsDtVswL6ele4Wo_4-q6mLugeW03LGW1As,3820 twisted/conch/ssh/filetransfer.py,sha256=pIbW2bXLGagYFKSNKmsn9px7tLto-mS3EhTgoM90778,34723 twisted/conch/ssh/forwarding.py,sha256=L0hBefu4bo4-L-4GCX-wnoFSGmCO9evRFQsm1YcPOVk,8176 twisted/conch/ssh/keys.py,sha256=zlpe3nNB5xWmgmepeXLN_2RsdCdNmTCR1fmhDw5tIdg,54988 twisted/conch/ssh/service.py,sha256=YV99lc0ZxNZMqKFurGXe-i5m8VbeBOZjti7HlO61fvU,1456 twisted/conch/ssh/session.py,sha256=xTVxNdd2MHBP-PhACVZHBLRJPdYn6auAbHZrYPtJ5TE,11225 twisted/conch/ssh/sexpy.py,sha256=lb0LVT8frScz5WEbMklatpcH5xqSV23ayw-m3CPlJP8,1053 twisted/conch/ssh/transport.py,sha256=r1xXHsOow7lOooe0rMgfb2cjyRgFcYrgg-JqiXb3los,73499 twisted/conch/ssh/userauth.py,sha256=jM51sMI7wmOgDVqH8Mbmc0QGWknJK5T5-y0iigchLR4,27336 twisted/conch/stdio.py,sha256=daZfnkeiP4dWbrAWVS3IwRVRrXA-VWvkyL1JpXO0uco,2764 twisted/conch/tap.py,sha256=9edTigyWQ7HmwQM52PPXIQEtjK_ENzLIm2TOqbsLnaE,3183 twisted/conch/telnet.py,sha256=hqa_MuP0QsaBfjqCA5I4qoJNgT0CIevrFZhlZRRqkhk,38539 twisted/conch/test/__init__.py,sha256=HAuvSUTlRN7E22xo4FEOw_2INTlSQcW-j3maA64RIWE,14 twisted/conch/test/__pycache__/__init__.cpython-36.pyc,, twisted/conch/test/__pycache__/keydata.cpython-36.pyc,, twisted/conch/test/__pycache__/loopback.cpython-36.pyc,, twisted/conch/test/__pycache__/test_address.cpython-36.pyc,, twisted/conch/test/__pycache__/test_agent.cpython-36.pyc,, twisted/conch/test/__pycache__/test_cftp.cpython-36.pyc,, twisted/conch/test/__pycache__/test_channel.cpython-36.pyc,, twisted/conch/test/__pycache__/test_checkers.cpython-36.pyc,, twisted/conch/test/__pycache__/test_ckeygen.cpython-36.pyc,, twisted/conch/test/__pycache__/test_conch.cpython-36.pyc,, twisted/conch/test/__pycache__/test_connection.cpython-36.pyc,, twisted/conch/test/__pycache__/test_default.cpython-36.pyc,, twisted/conch/test/__pycache__/test_endpoints.cpython-36.pyc,, twisted/conch/test/__pycache__/test_filetransfer.cpython-36.pyc,, twisted/conch/test/__pycache__/test_forwarding.cpython-36.pyc,, twisted/conch/test/__pycache__/test_helper.cpython-36.pyc,, twisted/conch/test/__pycache__/test_insults.cpython-36.pyc,, twisted/conch/test/__pycache__/test_keys.cpython-36.pyc,, twisted/conch/test/__pycache__/test_knownhosts.cpython-36.pyc,, twisted/conch/test/__pycache__/test_manhole.cpython-36.pyc,, twisted/conch/test/__pycache__/test_manhole_tap.cpython-36.pyc,, twisted/conch/test/__pycache__/test_mixin.cpython-36.pyc,, twisted/conch/test/__pycache__/test_openssh_compat.cpython-36.pyc,, twisted/conch/test/__pycache__/test_recvline.cpython-36.pyc,, twisted/conch/test/__pycache__/test_scripts.cpython-36.pyc,, twisted/conch/test/__pycache__/test_session.cpython-36.pyc,, twisted/conch/test/__pycache__/test_ssh.cpython-36.pyc,, twisted/conch/test/__pycache__/test_tap.cpython-36.pyc,, twisted/conch/test/__pycache__/test_telnet.cpython-36.pyc,, twisted/conch/test/__pycache__/test_text.cpython-36.pyc,, twisted/conch/test/__pycache__/test_transport.cpython-36.pyc,, twisted/conch/test/__pycache__/test_unix.cpython-36.pyc,, twisted/conch/test/__pycache__/test_userauth.cpython-36.pyc,, twisted/conch/test/__pycache__/test_window.cpython-36.pyc,, twisted/conch/test/keydata.py,sha256=kKR2HtebOfEYUJoitfE2f5WP0tLTfiX8T1Y-LuoSzDU,34462 twisted/conch/test/loopback.py,sha256=qV37tzWIsclzzTBSMiJfZP7-QDu9uBss82vNd926vZk,757 twisted/conch/test/test_address.py,sha256=OCDd05QbekjIIAMIeTlD39FfFc74TOUScnJSB1fHtQs,1629 twisted/conch/test/test_agent.py,sha256=9c_mMNa6OesLxvEblONmufuLKgkbngt9hKYZOA4KzAY,13086 twisted/conch/test/test_cftp.py,sha256=qfSE0uqVjEUqqNGZ24lm4bE3cl4KlisT_k5gT7NQP9Q,50866 twisted/conch/test/test_channel.py,sha256=xCt_cPTjQdHtu9kMNRBY5v3ZHOZnsiVRsmQaVBNcrO8,12099 twisted/conch/test/test_checkers.py,sha256=3bQSxiqv_91SAa55bfPKEVsLYccdJGAkQP2W7R2jm2A,31498 twisted/conch/test/test_ckeygen.py,sha256=Sk0IG-BX77iJfnnwJ6WVOA-1djeDec202WXtIYkL6Es,20158 twisted/conch/test/test_conch.py,sha256=OOjekhD7uE_VVi-4ShrO8Phss8nQJTbuoyLl2jzqKb0,25140 twisted/conch/test/test_connection.py,sha256=Bo-o57TFu_HJyD7YSS7L_WPg045bzl7dpoiHfr5F8pY,28729 twisted/conch/test/test_default.py,sha256=QPDy8v9neuR_q5y2l2-eRk2m7h70ZRX4vl26giyGTJI,11584 twisted/conch/test/test_endpoints.py,sha256=zEsFSKwShr_D70T5EGPplmldNq5vhKzpwngK-U8FhZE,54561 twisted/conch/test/test_filetransfer.py,sha256=DNiffEU0csVUwrLHq0kOqRmaRoGzDAgVvKYMh88MuDg,29239 twisted/conch/test/test_forwarding.py,sha256=DUUceXTLnXBPdEiEdnsRCFr_1mYnDprxgphXXQ3vW5g,2216 twisted/conch/test/test_helper.py,sha256=Fyl1gfsQbJMwzJN1OgyId5bEVW3rB1wWJdB5KCHpeZ4,20492 twisted/conch/test/test_insults.py,sha256=8TlCDalzJMnIsXm1nqMuGbkvdzHq9TkfIiR3Jlmtjf0,32330 twisted/conch/test/test_keys.py,sha256=Cp8SAlEUXm6ExJIo4yzodsDdVLdlnzDNn6DwZnQDwhk,50732 twisted/conch/test/test_knownhosts.py,sha256=hLDWLTA5UhVFW4kHGjUdXhlviG9ORD0SS0Y8zQy2x2w,49398 twisted/conch/test/test_manhole.py,sha256=7vznZ_Cye7YcnXUpxvDEMkxug_klwNSAIfiRbfva30U,13462 twisted/conch/test/test_manhole_tap.py,sha256=MzFrW10USUMe4tR2E7MpIGU94XPQogeSEg9_p6x9bM8,4235 twisted/conch/test/test_mixin.py,sha256=4_kOBOFf8gbWXEUuPPoggf5e2XBhdrZEa-dcnDoyWM4,1055 twisted/conch/test/test_openssh_compat.py,sha256=JoSP23u_ITcTvXju4mT_C7iHG3Aad0-R_C9Y7GQxnQM,4630 twisted/conch/test/test_recvline.py,sha256=81zKYJBYoxwPdr8Mm_yUXMgR4qykVGVaIitDGtK0pUU,25406 twisted/conch/test/test_scripts.py,sha256=hpbHxsJy4mC9Zn4qH_NVYUhKWaZ85o-9oKPzPppEwq4,1887 twisted/conch/test/test_session.py,sha256=O9EcNItOWoHaSIs18gzpzzuriKvZ-aQZF2hDpFj3vE8,39464 twisted/conch/test/test_ssh.py,sha256=XGM-BvVl_kK4bW9NFerqyZUeSso2cmDkxyyxCZbPrG0,32377 twisted/conch/test/test_tap.py,sha256=UDKmRhcEtFtV3G2D7WTyObP3z9QL1yBremFGxSBY7oc,4951 twisted/conch/test/test_telnet.py,sha256=-RCx8XJzNvSeygjJVco-RxyK-VYlTnVt29vbjfRGrK8,26524 twisted/conch/test/test_text.py,sha256=QvJbWCZTTLyAd87Cti2HmZPbDt9QECENq2nrNUvr-bk,3943 twisted/conch/test/test_transport.py,sha256=8QGS8Fp7bv5WoWEcXMXuvcBH1o_qBvJDNtSepffFzCg,94204 twisted/conch/test/test_unix.py,sha256=P5M6yUwDYz9x5mbbpO2KW13D-5I4aL2lpyRZ7PMr-9M,2533 twisted/conch/test/test_userauth.py,sha256=FHck9BxouYpJB42vth9xTCrfUQ2D0TaLwt1RBPuu8m8,32604 twisted/conch/test/test_window.py,sha256=2Qzq_paXugLOlUWEel3p79g71OuAOPahtQV_1d87mnU,2115 twisted/conch/ttymodes.py,sha256=J0Z95i2ljFJi9Wrclw_h7RvudTQp5TWXY_QerE8gY8Q,2239 twisted/conch/ui/__init__.py,sha256=RizFn8MwYiNGvqshvLD3SPhUGafTcMZ-o8U9EkwSF8k,167 twisted/conch/ui/__pycache__/__init__.cpython-36.pyc,, twisted/conch/ui/__pycache__/ansi.cpython-36.pyc,, twisted/conch/ui/__pycache__/tkvt100.cpython-36.pyc,, twisted/conch/ui/ansi.py,sha256=ZMh5UAKbHP55G8nKJcWzdrrQO9wWj8bBMbTRA1c2zZY,7181 twisted/conch/ui/tkvt100.py,sha256=q3a8r-97Qya7ompsc2wxVHS55uNY_FPe-5vNzOBzoZY,7052 twisted/conch/unix.py,sha256=dbOqv_-62mWg-6LwfscElkY5ZWvRZIB0AfEry4k6lEk,16307 twisted/copyright.py,sha256=_BzTp6ekKVHGxy_igsXo4e4Y7TkQiRkGFglIjK0PHkQ,1531 twisted/cred/__init__.py,sha256=W4NhTuZj7C95wT9UlvVbCa37jcHD_QJCyo5CImBK8Pg,189 twisted/cred/__pycache__/__init__.cpython-36.pyc,, twisted/cred/__pycache__/_digest.cpython-36.pyc,, twisted/cred/__pycache__/checkers.cpython-36.pyc,, twisted/cred/__pycache__/credentials.cpython-36.pyc,, twisted/cred/__pycache__/error.cpython-36.pyc,, twisted/cred/__pycache__/portal.cpython-36.pyc,, twisted/cred/__pycache__/strcred.cpython-36.pyc,, twisted/cred/_digest.py,sha256=sSpPeBMKKWYmYrW_fJ-5OwRUykFMVTsUAWHyonBbQ78,4114 twisted/cred/checkers.py,sha256=cAUY_9xiu8Fmrl1uMbvrkbxgaf137IOYQE8O5dYzKfQ,9219 twisted/cred/credentials.py,sha256=Q47WuA1omb0v5NoxIenOJV2sTUu_oFk1Ogfmlc2WMqU,16220 twisted/cred/error.py,sha256=Cpk_fR1EETu-HUAX7pbZakS-gw5nT8IADPbfdPMCt3Q,1037 twisted/cred/portal.py,sha256=-oz18ZO9qFnWGmTE4bqXmFIvjqJYKJBjebVhjkTuyh4,5406 twisted/cred/strcred.py,sha256=7_LkVWPalXkU5aTeU-KhNbnQs4Ov0wkM3fhW8xwRLIY,8385 twisted/cred/test/__init__.py,sha256=dJnJovocFbB0NlnMradQkTYnlhmluUFWNL3_wFUzJek,157 twisted/cred/test/__pycache__/__init__.cpython-36.pyc,, twisted/cred/test/__pycache__/test_cramauth.cpython-36.pyc,, twisted/cred/test/__pycache__/test_cred.cpython-36.pyc,, twisted/cred/test/__pycache__/test_digestauth.cpython-36.pyc,, twisted/cred/test/__pycache__/test_simpleauth.cpython-36.pyc,, twisted/cred/test/__pycache__/test_strcred.cpython-36.pyc,, twisted/cred/test/test_cramauth.py,sha256=8t4EMvxjl2iJBwSFEjppRO_VOunyzd_BWT5qGsJhLyM,2878 twisted/cred/test/test_cred.py,sha256=ikCGIkSBUkzXqNmqrX3PCJ2dsmAs8FN7FfG2Br3RYXM,13589 twisted/cred/test/test_digestauth.py,sha256=hJq6Zb5ZUY8FsOLf39tFSSpZxNFJ_0wq3W-DNfTsssU,24353 twisted/cred/test/test_simpleauth.py,sha256=9RuqcmpS17hEE6le1S5i44AO4PLYhKVhDVLsa5s0AyQ,2953 twisted/cred/test/test_strcred.py,sha256=CYIaHDkPqfD3lt-w2FPQNdDXZO0Q4CdSrYiDTniV9Z8,26359 twisted/enterprise/__init__.py,sha256=GnETu2_bpAushHQriI67GNeToHIqtrGNqOjXqg-cGsY,162 twisted/enterprise/__pycache__/__init__.cpython-36.pyc,, twisted/enterprise/__pycache__/adbapi.cpython-36.pyc,, twisted/enterprise/adbapi.py,sha256=-sHE2s0wLHiIEmModgIc8LfxZRjpG_Ljzv0h4D-rXp4,16883 twisted/internet/__init__.py,sha256=ickB0k1GfdghN-mprceL4YNhZOqOJTSbTssukmcHhyw,521 twisted/internet/__pycache__/__init__.cpython-36.pyc,, twisted/internet/__pycache__/_baseprocess.cpython-36.pyc,, twisted/internet/__pycache__/_dumbwin32proc.cpython-36.pyc,, twisted/internet/__pycache__/_glibbase.cpython-36.pyc,, twisted/internet/__pycache__/_idna.cpython-36.pyc,, twisted/internet/__pycache__/_newtls.cpython-36.pyc,, twisted/internet/__pycache__/_pollingfile.cpython-36.pyc,, twisted/internet/__pycache__/_posixserialport.cpython-36.pyc,, twisted/internet/__pycache__/_posixstdio.cpython-36.pyc,, twisted/internet/__pycache__/_producer_helpers.cpython-36.pyc,, twisted/internet/__pycache__/_resolver.cpython-36.pyc,, twisted/internet/__pycache__/_signals.cpython-36.pyc,, twisted/internet/__pycache__/_sslverify.cpython-36.pyc,, twisted/internet/__pycache__/_threadedselect.cpython-36.pyc,, twisted/internet/__pycache__/_win32serialport.cpython-36.pyc,, twisted/internet/__pycache__/_win32stdio.cpython-36.pyc,, twisted/internet/__pycache__/abstract.cpython-36.pyc,, twisted/internet/__pycache__/address.cpython-36.pyc,, twisted/internet/__pycache__/asyncioreactor.cpython-36.pyc,, twisted/internet/__pycache__/base.cpython-36.pyc,, twisted/internet/__pycache__/cfreactor.cpython-36.pyc,, twisted/internet/__pycache__/default.cpython-36.pyc,, twisted/internet/__pycache__/defer.cpython-36.pyc,, twisted/internet/__pycache__/endpoints.cpython-36.pyc,, twisted/internet/__pycache__/epollreactor.cpython-36.pyc,, twisted/internet/__pycache__/error.cpython-36.pyc,, twisted/internet/__pycache__/fdesc.cpython-36.pyc,, twisted/internet/__pycache__/gireactor.cpython-36.pyc,, twisted/internet/__pycache__/glib2reactor.cpython-36.pyc,, twisted/internet/__pycache__/gtk2reactor.cpython-36.pyc,, twisted/internet/__pycache__/gtk3reactor.cpython-36.pyc,, twisted/internet/__pycache__/inotify.cpython-36.pyc,, twisted/internet/__pycache__/interfaces.cpython-36.pyc,, twisted/internet/__pycache__/kqreactor.cpython-36.pyc,, twisted/internet/__pycache__/main.cpython-36.pyc,, twisted/internet/__pycache__/pollreactor.cpython-36.pyc,, twisted/internet/__pycache__/posixbase.cpython-36.pyc,, twisted/internet/__pycache__/process.cpython-36.pyc,, twisted/internet/__pycache__/protocol.cpython-36.pyc,, twisted/internet/__pycache__/pyuisupport.cpython-36.pyc,, twisted/internet/__pycache__/reactor.cpython-36.pyc,, twisted/internet/__pycache__/selectreactor.cpython-36.pyc,, twisted/internet/__pycache__/serialport.cpython-36.pyc,, twisted/internet/__pycache__/ssl.cpython-36.pyc,, twisted/internet/__pycache__/stdio.cpython-36.pyc,, twisted/internet/__pycache__/task.cpython-36.pyc,, twisted/internet/__pycache__/tcp.cpython-36.pyc,, twisted/internet/__pycache__/testing.cpython-36.pyc,, twisted/internet/__pycache__/threads.cpython-36.pyc,, twisted/internet/__pycache__/tksupport.cpython-36.pyc,, twisted/internet/__pycache__/udp.cpython-36.pyc,, twisted/internet/__pycache__/unix.cpython-36.pyc,, twisted/internet/__pycache__/utils.cpython-36.pyc,, twisted/internet/__pycache__/win32eventreactor.cpython-36.pyc,, twisted/internet/__pycache__/wxreactor.cpython-36.pyc,, twisted/internet/__pycache__/wxsupport.cpython-36.pyc,, twisted/internet/_baseprocess.py,sha256=oA5Yr481sEDg4UgsRyPDdwgz7RXJmasV6-jfuiSxlbE,1913 twisted/internet/_dumbwin32proc.py,sha256=7v0Zi003NzCWLE755g8cxr5ymcV2tN7R2B0Vdqc2WiI,13107 twisted/internet/_glibbase.py,sha256=UYNKRhHRPS9Qz8xmBIdDzZvYW9_-yQIy94P12O6pqGs,12813 twisted/internet/_idna.py,sha256=gYjexNDtZN1i0h6qoM161lGgOJrJHuBa1eP53oRr2jw,1397 twisted/internet/_newtls.py,sha256=NOCNH8CX-3CplooDfnprvg9o6qkUyt8QaMwN2r8_IKY,9332 twisted/internet/_pollingfile.py,sha256=qJAGGqXSJ6WYX6EyYe9wb-7OogZ_8DckKmTWjruyJDE,8982 twisted/internet/_posixserialport.py,sha256=gg1KrS3F4k33mULmkxekoM80XE8nhrZ-_oQxq27uTm8,1995 twisted/internet/_posixstdio.py,sha256=6vMt5L3wPA0c-rsTMyqDA583yVzsiR5o6lQ5FwmHkF8,4687 twisted/internet/_producer_helpers.py,sha256=eOqBQC5NsjBWT41oxQLwkyBQBh819uACCq-fIYDWRAs,3788 twisted/internet/_resolver.py,sha256=XjW_CQC8HxeWs7RvZXLLL6F4vN111Z1JC6uTbRK-skc,8530 twisted/internet/_signals.py,sha256=632Qy-EUB5v5RmhhhyntSkziY4jbb-kr2OhRDIHIrVQ,2718 twisted/internet/_sslverify.py,sha256=0wkJdmFhwHg4bA6iLSxRUU_hUZalgL0z5eT8WdrSrPk,72643 twisted/internet/_threadedselect.py,sha256=kYBjTox4Izt0jwTay-zrijjPN1PBZsOcbF1Q2HmsKi0,11764 twisted/internet/_win32serialport.py,sha256=BG-J2A18t-OWpFgRb0O3kN4KX6YPxVBq7q2knVA9muU,4744 twisted/internet/_win32stdio.py,sha256=XEF95KvNvyAThHvO3xBBR1ZZSRxyuuAnbWexYFN35Gc,3204 twisted/internet/abstract.py,sha256=64vN7f-4wT0SjMvZWxGbL0gLCagly7K_jfTJbhhylSU,19274 twisted/internet/address.py,sha256=etExPe2zLdiMZLMMPdl4sKw-b14-z4qk-es5AjR44P0,5246 twisted/internet/asyncioreactor.py,sha256=RgqUpwhb9Oj4wuj5S1YSZDcvDD0qfnIGeQ3Dl1T7djA,10553 twisted/internet/base.py,sha256=YosxpOp73JRDyuUFe6F86Vw5jbxfKkm3UJHgcsw71tE,44807 twisted/internet/cfreactor.py,sha256=XD3vxoojc4ol__9m-l1UjI7_8x_iy1mS91qK7rrFxDE,17501 twisted/internet/default.py,sha256=Kaer40mBJZh2FNUjdwkcjLx0H4otwVjSxGJAjah1PeA,1942 twisted/internet/defer.py,sha256=7tVf05OEL9ZeHi_fbEE5NhsP0e1KCFkt4eOIObyKEi0,71538 twisted/internet/endpoints.py,sha256=5w7doQW1XUaZeYCXovxOSEZKIun6ZZs8onbe-4p1sAA,77326 twisted/internet/epollreactor.py,sha256=C88W-ZnEGxH7rLHOyyZEVdjLqA0N4yeprhpMax3gTXc,8493 twisted/internet/error.py,sha256=sGIWVe03xkrfFv3B3y6oCfxxbvchBZFJg0bU5gPoJ6I,12930 twisted/internet/fdesc.py,sha256=nVL6TE6JBUJW-Yfyh7uaWBv-NHqE_Uc1qIT2Myz30qk,3223 twisted/internet/gireactor.py,sha256=CtgJNXQymPyihhiqrWHZqT89g65hSXXZHrITwypVQjI,6123 twisted/internet/glib2reactor.py,sha256=_fHgbRRmABRTuLZ9hGia_cf5WsKYUoUfn7G3Ue6r8oY,1115 twisted/internet/gtk2reactor.py,sha256=otOVjJ41g2XqlSkv917z_XjoXtxYku1G6Qu6OrkLCXA,3614 twisted/internet/gtk3reactor.py,sha256=j_m-9nnTk267VQpfE-SVRplkJTEQGmsRz-dZMQz5kZA,2252 twisted/internet/inotify.py,sha256=X4mQASe4bdY2_hyh80JdHQYElzqYmsH7I6GMHcJhXxM,14691 twisted/internet/interfaces.py,sha256=CQTA8orAZHIXl4SLOaPklIHBbplfF7qMT6W0JT_gX2g,96841 twisted/internet/iocpreactor/__init__.py,sha256=27qHsOLp9irn3pKHUwlAOyJdu9khir4tTTPLj8djNIg,191 twisted/internet/iocpreactor/__pycache__/__init__.cpython-36.pyc,, twisted/internet/iocpreactor/__pycache__/abstract.cpython-36.pyc,, twisted/internet/iocpreactor/__pycache__/const.cpython-36.pyc,, twisted/internet/iocpreactor/__pycache__/interfaces.cpython-36.pyc,, twisted/internet/iocpreactor/__pycache__/reactor.cpython-36.pyc,, twisted/internet/iocpreactor/__pycache__/setup.cpython-36.pyc,, twisted/internet/iocpreactor/__pycache__/tcp.cpython-36.pyc,, twisted/internet/iocpreactor/__pycache__/udp.cpython-36.pyc,, twisted/internet/iocpreactor/abstract.py,sha256=I9NG1gYeV_qM2GK0OQOsnATXo4mfbGov3KsMZuFKgVU,13140 twisted/internet/iocpreactor/const.py,sha256=t66XJONPOmxAo65y--PGT3hGuCuzW0hkZSYPn3_rxM0,524 twisted/internet/iocpreactor/interfaces.py,sha256=QjNOs3GrwNkJDhXno7a6t8cmYPYYZimfzAcolyW5APM,942 twisted/internet/iocpreactor/notes.txt,sha256=M0nci0EaspffjVOb52oxwbdcCldjBd861kJYbCtOpAg,890 twisted/internet/iocpreactor/reactor.py,sha256=ljIs-BjzYA4WdWWDuAeWq_FHOis4OhIsZxviOK0tDpE,9190 twisted/internet/iocpreactor/setup.py,sha256=cDNm15Q783-ma3x24dn_AskmZKzcw_Lm6kSTsb_5kXE,588 twisted/internet/iocpreactor/tcp.py,sha256=jpM9wcpgvuVvABk8pdWFd52IFOdVEZxG4u_ug_-6wIs,20143 twisted/internet/iocpreactor/udp.py,sha256=PDN_RpvDmk3P4wr_0NbUjB0c6d3_JWE99_BqIR7QZMA,14016 twisted/internet/kqreactor.py,sha256=q6rBYkifSJRLgvHM8_DG9yUxfIMrWD8GqXR3IhFOzI0,10292 twisted/internet/main.py,sha256=Be-vOTGwAjtJp4ClfJS_YcFNi4K6OD5MRZbPAdf1z0c,1054 twisted/internet/pollreactor.py,sha256=-8iCPvvAmFdrppsUmVi0Y3YB13shYVx5Butm804ECp8,6026 twisted/internet/posixbase.py,sha256=gqF-AR9g5fuZFuTYgE_bBomw15nf6wayV7T2w2PE0LY,26357 twisted/internet/process.py,sha256=xjwiddhe5gc77KuNaoJ_wvaoJHuB0PNpD7q32ELzvG4,37757 twisted/internet/protocol.py,sha256=4H2pC8sMBybJp91_1WEHMELsdndtydqnMIwzgyNnHmA,27134 twisted/internet/pyuisupport.py,sha256=v265CibEt7gJzS295Gp8krpqWi-6LQc8jOSuKPwILWs,817 twisted/internet/reactor.py,sha256=MKC3G2suikAAo6jxm2HTVRWizJ6aIoDUp4BBlG_TZ2Q,1863 twisted/internet/selectreactor.py,sha256=_4uNzRQ1pId94vFgYAILlfMNEC81P5OFjXfY4tXCBkE,6215 twisted/internet/serialport.py,sha256=6h2KSqB_U1GfduHwNO-XWVQ7deZdIaT9izwyI_OCQf0,2317 twisted/internet/ssl.py,sha256=p_eXSk4crn1yS9659veU9y-d0npj-61xKwdrLl7Lees,8444 twisted/internet/stdio.py,sha256=kbU3W7OTnXOvsHGgis2AeX13vzIgmzrgeS3DLRxlUnY,1045 twisted/internet/task.py,sha256=YwT9EXKh8X9W4UTnwDDVVWMbRQ755HfNc5Vd5sQ-pxs,31157 twisted/internet/tcp.py,sha256=jBDVMB8PVj2QvvwAgBkRgCLFCkhYT8hmW7X-0qI70EY,54908 twisted/internet/test/__init__.py,sha256=R0XCXlTn2bvT1mHPrDoQkW4y-WEXFq_jVBO83Nax7jY,112 twisted/internet/test/__pycache__/__init__.cpython-36.pyc,, twisted/internet/test/__pycache__/_posixifaces.cpython-36.pyc,, twisted/internet/test/__pycache__/_win32ifaces.cpython-36.pyc,, twisted/internet/test/__pycache__/connectionmixins.cpython-36.pyc,, twisted/internet/test/__pycache__/fakeendpoint.cpython-36.pyc,, twisted/internet/test/__pycache__/modulehelpers.cpython-36.pyc,, twisted/internet/test/__pycache__/process_cli.cpython-36.pyc,, twisted/internet/test/__pycache__/process_connectionlost.cpython-36.pyc,, twisted/internet/test/__pycache__/process_gireactornocompat.cpython-36.pyc,, twisted/internet/test/__pycache__/process_helper.cpython-36.pyc,, twisted/internet/test/__pycache__/reactormixins.cpython-36.pyc,, twisted/internet/test/__pycache__/test_abstract.cpython-36.pyc,, twisted/internet/test/__pycache__/test_address.cpython-36.pyc,, twisted/internet/test/__pycache__/test_asyncioreactor.cpython-36.pyc,, twisted/internet/test/__pycache__/test_base.cpython-36.pyc,, twisted/internet/test/__pycache__/test_baseprocess.cpython-36.pyc,, twisted/internet/test/__pycache__/test_core.cpython-36.pyc,, twisted/internet/test/__pycache__/test_coroutines.cpython-36.pyc,, twisted/internet/test/__pycache__/test_default.cpython-36.pyc,, twisted/internet/test/__pycache__/test_endpoints.cpython-36.pyc,, twisted/internet/test/__pycache__/test_epollreactor.cpython-36.pyc,, twisted/internet/test/__pycache__/test_error.cpython-36.pyc,, twisted/internet/test/__pycache__/test_fdset.cpython-36.pyc,, twisted/internet/test/__pycache__/test_filedescriptor.cpython-36.pyc,, twisted/internet/test/__pycache__/test_gireactor.cpython-36.pyc,, twisted/internet/test/__pycache__/test_glibbase.cpython-36.pyc,, twisted/internet/test/__pycache__/test_inlinecb.cpython-36.pyc,, twisted/internet/test/__pycache__/test_inotify.cpython-36.pyc,, twisted/internet/test/__pycache__/test_iocp.cpython-36.pyc,, twisted/internet/test/__pycache__/test_kqueuereactor.cpython-36.pyc,, twisted/internet/test/__pycache__/test_main.cpython-36.pyc,, twisted/internet/test/__pycache__/test_newtls.cpython-36.pyc,, twisted/internet/test/__pycache__/test_pollingfile.cpython-36.pyc,, twisted/internet/test/__pycache__/test_posixbase.cpython-36.pyc,, twisted/internet/test/__pycache__/test_posixprocess.cpython-36.pyc,, twisted/internet/test/__pycache__/test_process.cpython-36.pyc,, twisted/internet/test/__pycache__/test_protocol.cpython-36.pyc,, twisted/internet/test/__pycache__/test_resolver.cpython-36.pyc,, twisted/internet/test/__pycache__/test_serialport.cpython-36.pyc,, twisted/internet/test/__pycache__/test_sigchld.cpython-36.pyc,, twisted/internet/test/__pycache__/test_socket.cpython-36.pyc,, twisted/internet/test/__pycache__/test_stdio.cpython-36.pyc,, twisted/internet/test/__pycache__/test_tcp.cpython-36.pyc,, twisted/internet/test/__pycache__/test_testing.cpython-36.pyc,, twisted/internet/test/__pycache__/test_threads.cpython-36.pyc,, twisted/internet/test/__pycache__/test_time.cpython-36.pyc,, twisted/internet/test/__pycache__/test_tls.cpython-36.pyc,, twisted/internet/test/__pycache__/test_udp.cpython-36.pyc,, twisted/internet/test/__pycache__/test_udp_internals.cpython-36.pyc,, twisted/internet/test/__pycache__/test_unix.cpython-36.pyc,, twisted/internet/test/__pycache__/test_win32events.cpython-36.pyc,, twisted/internet/test/__pycache__/test_win32serialport.cpython-36.pyc,, twisted/internet/test/_awaittests.py.3only,sha256=651lYVAeyzETW_iKSUSuSC5e4PhbsA-wWTtTg_j8cKY,6175 twisted/internet/test/_posixifaces.py,sha256=xL3pSciwjrgsc2vDGnDKHOvE4mdrgcl7bn8k0Ntv_VU,4689 twisted/internet/test/_win32ifaces.py,sha256=vVJB50tK-ld9Dl4twObaEmKkPVUJ33aXGoR3_D-PJdA,3883 twisted/internet/test/_yieldfromtests.py.3only,sha256=cF9nuNuy-83kpGw7EaIbqZLWyopXSCI_VWNtLl3fZUM,4333 twisted/internet/test/connectionmixins.py,sha256=Pue7N7q7eKo3YmhcnAofG6Ywqm6qlg0aM-PEVyUo8zw,20442 twisted/internet/test/fake_CAs/chain.pem,sha256=3oISrpA2Sb0kD6NysWF0imvVJL3B27li6fhvN0f8NWQ,2090 twisted/internet/test/fake_CAs/not-a-certificate,sha256=GJS9_LOIDdjtHP_M9HZVBli__V-Drd2i_sWSMUyfzlg,84 twisted/internet/test/fake_CAs/thing1.pem,sha256=RWz-DQyE72AFJo6awm6JarF4NAtDdryvmlYCL1hgkEA,1339 twisted/internet/test/fake_CAs/thing2-duplicate.pem,sha256=jl9GaNBh32s56E8BGhxhvX9g-VcLFE9bmrcYh-ONyXU,1339 twisted/internet/test/fake_CAs/thing2.pem,sha256=jl9GaNBh32s56E8BGhxhvX9g-VcLFE9bmrcYh-ONyXU,1339 twisted/internet/test/fakeendpoint.py,sha256=WyT9ss1Fc_2yeLLgJYkHuunArjULjxP_vzq1NSJUIHQ,1555 twisted/internet/test/modulehelpers.py,sha256=mA3sU_zQ42YObsSffwtei1JaiB3vZHOQwJG864Nj3pU,1726 twisted/internet/test/process_cli.py,sha256=SJl3N3-wknNAZsd7gpLVSLNHAbd8XaoGxCgyczRkbE8,664 twisted/internet/test/process_connectionlost.py,sha256=aDGj_l1QlH2pSmwWRPQbW-YSqjgy-3pVm7tEjmveRVE,119 twisted/internet/test/process_gireactornocompat.py,sha256=2p8sOZbMzmzI3XsEF5KmG7f09fkNNIL9WSBl1B_5V6o,721 twisted/internet/test/process_helper.py,sha256=rTonb5m0GZ7SEHdD--OBxitBvOurLo_KXSewArnznos,1081 twisted/internet/test/reactormixins.py,sha256=bQDbUUhazlVO9ZAsFGD10WNicNlKxC_7MdgfWznPMQo,14054 twisted/internet/test/test_abstract.py,sha256=mxQNphfzUEaFw24JSP0EXE9DeSwqqoaxPY8u4xS6jc0,2032 twisted/internet/test/test_address.py,sha256=s2SRx7zOIfNzHsdyyd-Up54C1--5yPgYK_bifGpsCzg,8598 twisted/internet/test/test_asyncioreactor.py,sha256=AvqcLlFgGKeoMAH_KT0v09v0Kz1-Q-f2JBR6jsf57tg,1331 twisted/internet/test/test_base.py,sha256=ppOqFt_1MBBG6Gyod47GTwqIhwTiM_y2cyMPfRz8ISc,13369 twisted/internet/test/test_baseprocess.py,sha256=Z9RUmCFPJ8P75H0rnY7bpXor2ziJ3SG0dWcwYk3FYAM,2613 twisted/internet/test/test_core.py,sha256=Qvk9lprgYzWgLmGppftwu8VxG6m4trqIbohsRag8Oq4,11262 twisted/internet/test/test_coroutines.py,sha256=h7mJtgpmxyufah9lGIuobxR9zWZq021YtMhDbJW9dSg,1787 twisted/internet/test/test_default.py,sha256=Nzy-gVFdIG-jSuaLy79QryRBKKj7yCJN0cb5P2c0L1s,3540 twisted/internet/test/test_endpoints.py,sha256=cAEAumCdQvM7Hzsgv0zxVKe4-nyHZvvJUxifWKVCaRs,148715 twisted/internet/test/test_epollreactor.py,sha256=d4AYzKsTlX3vltXsYeuLs1_izD_SDlLppzZu3r8mkok,7336 twisted/internet/test/test_error.py,sha256=oDVs6B66RlGVry9EUFcB3veY6F7XKbP8ollJtzl3Vls,1117 twisted/internet/test/test_fdset.py,sha256=4nb3OZQ4IkvxdctWv9D7aqHt9Q2oG2AEnk96id_je8g,13501 twisted/internet/test/test_filedescriptor.py,sha256=n5dk7wBEBkdEHkdVoP8giao8TuNozXXhuo4u7Rck_Fc,2808 twisted/internet/test/test_gireactor.py,sha256=nKg_WP2t7Px0qLG0OWwYctQPNFA6umxPB8apJS4cJec,9042 twisted/internet/test/test_glibbase.py,sha256=cy_fhIkPU1hWGR7X7HCHdxyttwsCW9znx6TfkUx3Ydw,2284 twisted/internet/test/test_inlinecb.py,sha256=EVvSMw9_P-S6ZPFsvxTl_T1dDsqoa10mrY1ZmxK6pPI,11599 twisted/internet/test/test_inotify.py,sha256=iNsOQCxh7STqv6UyFVM3CPCUcMGHHoHj5lH9bR-sV-I,16686 twisted/internet/test/test_iocp.py,sha256=ToWR8uGVP-xRi95rLrgg3XihthvR5vbiJXd0KlRaM-E,5170 twisted/internet/test/test_kqueuereactor.py,sha256=gwI-cGpRR9clo65AT2O5hJ_ywk4Aa2s3fC5dQ8N5R-o,1916 twisted/internet/test/test_main.py,sha256=GTjenqA-4z9NgFjkol_umHmFT9yJPc7_hRZm5qvhOgM,1436 twisted/internet/test/test_newtls.py,sha256=lRPyRBQB23xjyYl26xsHmk3DNvRAXrGq8MGzu0IEMnk,6693 twisted/internet/test/test_pollingfile.py,sha256=Q9lXthu2zLgpSx8-0JxxRWso3rYy2KzTMS4oYefBKIU,1278 twisted/internet/test/test_posixbase.py,sha256=yViBaItENJAHROGogmQfYLcCpr214vxRb3Xs6hn-OhE,9536 twisted/internet/test/test_posixprocess.py,sha256=MAx23Bu8oDxxLD4wsiH8r8U0dG6mwzOC4Hoaxg3F-jQ,11166 twisted/internet/test/test_process.py,sha256=N7DsHIzbIHA2fQrPeuUKyFonWLOmC3u-yUkek08xWVU,32045 twisted/internet/test/test_protocol.py,sha256=FYOzV9o1sfU0f9mX-sqmnGRBTIqMFC0AX2VHxXfTkc8,18727 twisted/internet/test/test_resolver.py,sha256=XelBnCD7C7407RoIi_pmjejNkP7lKvYopFHoXI-ulzw,20153 twisted/internet/test/test_serialport.py,sha256=61zuFJtDV9_UTAbWWHqFN1X84q5lweVB9hswsjs_b8Q,1948 twisted/internet/test/test_sigchld.py,sha256=STT-nfEsm4n1Y2NJVkHzQhbQNc-6RnZlu3sXvbL65DU,3935 twisted/internet/test/test_socket.py,sha256=mYp89LTUAPIHQ-hk0dwBV07WY-jGHaT_xT47dshgLzs,9329 twisted/internet/test/test_stdio.py,sha256=rcuJcxmqTy253faCcKn5IOb4H37FA9-zD-WmRwRvSLk,6449 twisted/internet/test/test_tcp.py,sha256=eu263u3jtvHW8NJSMiWZ1D6cRwSznVIUXzGxclWLCGo,108446 twisted/internet/test/test_testing.py,sha256=3piwz-YZPbta29JSQ35u-gjJIJIB8LvhealU1nO9vGY,16676 twisted/internet/test/test_threads.py,sha256=QHJlDT8yrt2p694J73OyYuyaQbfoE5JFGhVY11PBrBA,8582 twisted/internet/test/test_time.py,sha256=mkm9Dzb7WGfSLrGKrO2H_FWYcj9Hd2N23sutQrZM9uY,3717 twisted/internet/test/test_tls.py,sha256=6B_p8wgbLtiREd7RC7bq91d6Nq3Ttu9EnMFiMxQXbns,13459 twisted/internet/test/test_udp.py,sha256=xG2LDYVIUDAt9GKo017kkIk2rZV2uDDSMg2Z6zOuaWc,17140 twisted/internet/test/test_udp_internals.py,sha256=W3KXCY9AGz_BCwSEP86XPmNfHBRPqLwHA1rS2oeXh0Q,4909 twisted/internet/test/test_unix.py,sha256=uImznrC0H-zKauZsH8EWD_ByLYc3Qc8bZZMj0k2u_yo,35712 twisted/internet/test/test_win32events.py,sha256=9mDXR-8OVTXow8hgR9F9ygn42NoWPtQjpcLA_RWRmjE,6500 twisted/internet/test/test_win32serialport.py,sha256=5--jrNIeK1Q5268i1qFlTyj8rvAHKuos53muqidCaNE,5282 twisted/internet/testing.py,sha256=3k4bJWjcekOwK1N7mT3A-R_IWYXa89gFpgRcv_MOTLc,29106 twisted/internet/threads.py,sha256=9iwvudl1ROPFollGPXuD7vHLHzZFajNO4QR-9C_apr8,3953 twisted/internet/tksupport.py,sha256=th9iaGhbwYdurBXmOHfqjagRvi3vKMF-f30FPMne_fk,2045 twisted/internet/udp.py,sha256=HUJClZLNANFQpmaWqRRV_zM8jbEhHNY7JT3dx8L4ljI,18569 twisted/internet/unix.py,sha256=i7213Texp8VocUlaFtSp0P75XMmYFkKjJ0Se3sNoOvU,21965 twisted/internet/utils.py,sha256=38YGqBFgj4aqWuXq6Zme3sAPIYoNB42kBF0qiejJtmc,8347 twisted/internet/win32eventreactor.py,sha256=XgPo4hKF0a1hLbOVCxRWspGUoB5DtTBQVzNBtV_Dkkc,15193 twisted/internet/wxreactor.py,sha256=Bj43Qo8v0tm1SDiehiFEZO81wn2vVBdSifKGH3LZuq4,5290 twisted/internet/wxsupport.py,sha256=gNrChXmxkAVv_ANnVWYIXM7_MHYztDrZXoP8GVGIDqA,1363 twisted/logger/__init__.py,sha256=wua2tX8Am7sKMFTGoIMhFzT6b6HJRZ46sV9zEVLOzKU,3318 twisted/logger/__pycache__/__init__.cpython-36.pyc,, twisted/logger/__pycache__/_buffer.cpython-36.pyc,, twisted/logger/__pycache__/_capture.cpython-36.pyc,, twisted/logger/__pycache__/_file.cpython-36.pyc,, twisted/logger/__pycache__/_filter.cpython-36.pyc,, twisted/logger/__pycache__/_flatten.cpython-36.pyc,, twisted/logger/__pycache__/_format.cpython-36.pyc,, twisted/logger/__pycache__/_global.cpython-36.pyc,, twisted/logger/__pycache__/_io.cpython-36.pyc,, twisted/logger/__pycache__/_json.cpython-36.pyc,, twisted/logger/__pycache__/_legacy.cpython-36.pyc,, twisted/logger/__pycache__/_levels.cpython-36.pyc,, twisted/logger/__pycache__/_logger.cpython-36.pyc,, twisted/logger/__pycache__/_observer.cpython-36.pyc,, twisted/logger/__pycache__/_stdlib.cpython-36.pyc,, twisted/logger/__pycache__/_util.cpython-36.pyc,, twisted/logger/_buffer.py,sha256=Ey_2hKMColHaD4hmmSAfeWx54_y6k2NN05ZtAlSSObg,1484 twisted/logger/_capture.py,sha256=gkkka_YA9mivTlOakGk1svO39-0z-PgaIyDAM1S_bZU,459 twisted/logger/_file.py,sha256=cTcmdYkAUG6ZXvSoPUEw6DCjWM9SeHR--KzSy0uoDtg,2485 twisted/logger/_filter.py,sha256=hFxcx_Zj2MXUdNqjCtxLdFQbd8LMJdtPrUfBxB6Jfgk,6986 twisted/logger/_flatten.py,sha256=4IHEykWLzF7ETajOPemB-SPJYWsnKlcjjDmiM2tbovA,5091 twisted/logger/_format.py,sha256=oL_JqJcitW7oB_qUkKNcoJdexU0vQahK8k8otQi4kDM,12436 twisted/logger/_global.py,sha256=vulnbrNmcfWWArNLjApYasXFt0qiH97w1_Ngu3khvqk,8787 twisted/logger/_io.py,sha256=nBp4WrTrb7QS2UL4rm8tIEXgBjOHq1pay6jcSWPC2PU,4459 twisted/logger/_json.py,sha256=8mWj_DOABHynHDSvUBEBqUMVHYZ-O4deVwKJGKx0TqE,10069 twisted/logger/_legacy.py,sha256=IGc2gfq-FFYz5gJwz-XpLuhHdGrpL0CNvyWiYTNJS2U,5237 twisted/logger/_levels.py,sha256=EHzcJgMG3TyKV0hnUqX1LIExbPlvXwlEbxQmca0qfLI,3772 twisted/logger/_logger.py,sha256=htbvVZ-uTQPgu_6SdH2G_S7-0QB6Ui6mcUrYYLHrWz8,9548 twisted/logger/_observer.py,sha256=3R7RC7t1HQzzoPPLsst76vAqAc8821ofXdL9qQrlcJw,4991 twisted/logger/_stdlib.py,sha256=FjMeA8N4BzrQL4F-ldsap8nIdBvYOXfYwDPr-39L5gI,4611 twisted/logger/_util.py,sha256=tjt6KwCfV4aCTZrKgTFhunTgMKsAY19JTUIBgSmDDZM,1328 twisted/logger/test/__init__.py,sha256=cGAk-ROeAJboDWOal_3es3XGNfc2Krzid7s4tD6zC40,161 twisted/logger/test/__pycache__/__init__.cpython-36.pyc,, twisted/logger/test/__pycache__/test_buffer.cpython-36.pyc,, twisted/logger/test/__pycache__/test_capture.cpython-36.pyc,, twisted/logger/test/__pycache__/test_file.cpython-36.pyc,, twisted/logger/test/__pycache__/test_filter.cpython-36.pyc,, twisted/logger/test/__pycache__/test_flatten.cpython-36.pyc,, twisted/logger/test/__pycache__/test_format.cpython-36.pyc,, twisted/logger/test/__pycache__/test_global.cpython-36.pyc,, twisted/logger/test/__pycache__/test_io.cpython-36.pyc,, twisted/logger/test/__pycache__/test_json.cpython-36.pyc,, twisted/logger/test/__pycache__/test_legacy.cpython-36.pyc,, twisted/logger/test/__pycache__/test_levels.cpython-36.pyc,, twisted/logger/test/__pycache__/test_logger.cpython-36.pyc,, twisted/logger/test/__pycache__/test_observer.cpython-36.pyc,, twisted/logger/test/__pycache__/test_stdlib.cpython-36.pyc,, twisted/logger/test/__pycache__/test_util.cpython-36.pyc,, twisted/logger/test/test_buffer.py,sha256=1aktli9DYcJNP6RoSP9UEGWFOZPRkt7X-JjXIp8Yodg,1642 twisted/logger/test/test_capture.py,sha256=RY6MlSSxV3t2CQfpSL4Bw22lAntqkv3_S9rdUav2vzs,1083 twisted/logger/test/test_file.py,sha256=cheG1k5tukraq-D69-YkpyYLVuCRwDZBxSJ6Vq_7AtE,5623 twisted/logger/test/test_filter.py,sha256=eKTEDG9D3A40xean4VURrDqt1E6ahW9zMH4c4M_SPeI,12010 twisted/logger/test/test_flatten.py,sha256=ED2GgB3lbdSPquZa05sp1A8C2V-vEfIjqIeSgg_ZiMs,9137 twisted/logger/test/test_format.py,sha256=Ai0fX0tiug5XeFwKkSC0KS5A1Il0zLSONSU6SAymhiA,22563 twisted/logger/test/test_global.py,sha256=ASCp2U2HY9pxX5mVxezfDf-AlI4Sz92p_DfE1z3_TqM,12049 twisted/logger/test/test_io.py,sha256=23iLbLF5LW6NNtl1OUF1cewOhahXANuzJdYnDg8zL5c,7212 twisted/logger/test/test_json.py,sha256=7b4vPpSA_rDvU4odC18GWgHNkGQd-424eENIv-vc4WA,18584 twisted/logger/test/test_legacy.py,sha256=1UunwkcS4wNj55U4UbI_ju9Ode_AEIP9rO0hERfFchQ,14395 twisted/logger/test/test_levels.py,sha256=tOk3LKjszhlzyL1Yf9mWDli7JnP3KokbFEk8hH2KSAM,875 twisted/logger/test/test_logger.py,sha256=DpDTOl2Uunn9MndN7eqxVEU4xZ0rOV7rs8wOJ2XrjoU,7354 twisted/logger/test/test_observer.py,sha256=gJxSYGkZDddedE5bRufQP6WZqOaVwpmQIykEPemRHEo,5253 twisted/logger/test/test_stdlib.py,sha256=0jMzZ7VT2KwXKqxmzycArG9FKzmOg6wwuktMJtodgk4,8639 twisted/logger/test/test_util.py,sha256=dyGJWIINUYI2MeIPEG-NntOByrg6eQ0IeZZhrcdt2K8,2671 twisted/mail/__init__.py,sha256=TTwDhFQPpKH_2LKY6Bcc1_eBoua-VUIeuY2S1-P22JI,142 twisted/mail/__pycache__/__init__.cpython-36.pyc,, twisted/mail/__pycache__/_cred.cpython-36.pyc,, twisted/mail/__pycache__/_except.cpython-36.pyc,, twisted/mail/__pycache__/imap4.cpython-36.pyc,, twisted/mail/__pycache__/interfaces.cpython-36.pyc,, twisted/mail/__pycache__/pop3.cpython-36.pyc,, twisted/mail/__pycache__/pop3client.cpython-36.pyc,, twisted/mail/__pycache__/protocols.cpython-36.pyc,, twisted/mail/__pycache__/relay.cpython-36.pyc,, twisted/mail/__pycache__/smtp.cpython-36.pyc,, twisted/mail/_cred.py,sha256=V-98-Kn5dWa1_6UboZEr77FgshnyFQSdPVcFypXcnZ4,2786 twisted/mail/_except.py,sha256=2bhvABOlSg_b2rwyyNIgAI4TpaNIsz0mkSVqHv0qn9o,8763 twisted/mail/imap4.py,sha256=Oa2_Utr0ojbY-cMuaQmGLowZ8_rm4rmalTqrz2W3aug,211261 twisted/mail/interfaces.py,sha256=RpN6ZHGZ34n2O7R4__AnVXyavlFdxF0hO20HG9-_Elc,32153 twisted/mail/pop3.py,sha256=IRFvrotm_YB7E3DXGXIn0rpRz4yVBgF4jxQt6TDfYWE,54946 twisted/mail/pop3client.py,sha256=dWHzCuiijPz2mm9p0AFGCVHzZccjcf2KN5wy6aF4yBY,46706 twisted/mail/protocols.py,sha256=OdMKy9HSqLjPfma78rFtu5UaHz_SzCBCV9vFucSjOOc,12644 twisted/mail/relay.py,sha256=DoGtkPnwEL6N9nutaWn4EmV8pxBTFrz_Mnh2tWwvQsY,5361 twisted/mail/scripts/__pycache__/mailmail.cpython-36.pyc,, twisted/mail/scripts/mailmail.py,sha256=grFSxZpUjZvcegj2OkwUkfDunUGpAYv-c75nGY2JfT0,10581 twisted/mail/smtp.py,sha256=4t5MEHp3_1oaicOO1OQBHhKb-nDdha1FVhZrAu2USQA,71612 twisted/mail/test/__init__.py,sha256=p5MeYvSnUTo_P8vZfiYhJ1KXeI-Y090YiJfedQFqvkE,24 twisted/mail/test/__pycache__/__init__.cpython-36.pyc,, twisted/mail/test/__pycache__/pop3testserver.cpython-36.pyc,, twisted/mail/test/__pycache__/test_imap.cpython-36.pyc,, twisted/mail/test/__pycache__/test_mailmail.cpython-36.pyc,, twisted/mail/test/__pycache__/test_pop3.cpython-36.pyc,, twisted/mail/test/__pycache__/test_pop3client.cpython-36.pyc,, twisted/mail/test/__pycache__/test_smtp.cpython-36.pyc,, twisted/mail/test/pop3testserver.py,sha256=GC8MrFuOEWCA55VkGuZ0cl5eQ8iL7lYj12PzegNhE6w,8249 twisted/mail/test/rfc822.message,sha256=0nsnccDczctGjuZaRUBDgJ29EViOh-lRVFvgy8Mhwwg,3834 twisted/mail/test/test_imap.py,sha256=903XJQbfxHo2QOvarhxi5k5vm6-dfTVQAZV3KK8AtX4,265738 twisted/mail/test/test_mailmail.py,sha256=DzcZrQr7HS_Mpkxtt5UQpIDyX5KwgauTQEbe1tvmHus,12930 twisted/mail/test/test_pop3.py,sha256=EC0-NqaECqKBEVC0-3vartbdySYWyzTf6w4wNhp5y9E,42094 twisted/mail/test/test_pop3client.py,sha256=sLFvUs8SEvR79eLVEOLos4ebYuw3xUZvc6_rxVs-pyQ,21986 twisted/mail/test/test_smtp.py,sha256=j8TwKunZaHIhY7sfS5VtnNRKjEYbp0HRKyojAiChDvc,63927 twisted/names/__init__.py,sha256=pn-zinHevqxkH0Ww1O7gdT7u_xNISy_is4ODYmO071E,135 twisted/names/__pycache__/__init__.cpython-36.pyc,, twisted/names/__pycache__/_rfc1982.cpython-36.pyc,, twisted/names/__pycache__/authority.cpython-36.pyc,, twisted/names/__pycache__/cache.cpython-36.pyc,, twisted/names/__pycache__/client.cpython-36.pyc,, twisted/names/__pycache__/common.cpython-36.pyc,, twisted/names/__pycache__/dns.cpython-36.pyc,, twisted/names/__pycache__/error.cpython-36.pyc,, twisted/names/__pycache__/hosts.cpython-36.pyc,, twisted/names/__pycache__/resolve.cpython-36.pyc,, twisted/names/__pycache__/root.cpython-36.pyc,, twisted/names/__pycache__/secondary.cpython-36.pyc,, twisted/names/__pycache__/server.cpython-36.pyc,, twisted/names/__pycache__/srvconnect.cpython-36.pyc,, twisted/names/__pycache__/tap.cpython-36.pyc,, twisted/names/_rfc1982.py,sha256=m4BrYSy8VRvdlg4io8DeMB5wzF5v6c2hePVueBnN7Ec,9113 twisted/names/authority.py,sha256=_wFwPeeSsyMvhtvlCXdOm1CZRlYEhN-nHEO5tw0EHis,16530 twisted/names/cache.py,sha256=vRGMwuE4lFhf4W2BodlwD8u8SSaMpAOYmTtl8zH1AAE,3804 twisted/names/client.py,sha256=PDqrkmpwagwzKXGLw5vsisfnCt_YQaxbYpBFWbY1nhw,24549 twisted/names/common.py,sha256=nFbHZKgxS2m9mv4oOYYTTTxa2XR-Wf0UZ3wqlpTJfCA,7860 twisted/names/dns.py,sha256=7t4GaYbIOmPx7s54BPEjlktRPQ2lPF89fxsQbJ4-RqM,96976 twisted/names/error.py,sha256=02_cTkNE6K1Gahwpxwors_qd9gr5ts3x0PghidZejMQ,2056 twisted/names/hosts.py,sha256=RQlExFaZGDTLvFhRoBH85KeeRI8Eq7UtxcpECBpMF98,4521 twisted/names/resolve.py,sha256=-zMAKlRaex2DuUXGw7-o2RxYRRrxAGNNa5o_x0Dxrdc,3361 twisted/names/root.py,sha256=-Q17Eu87jHN8V1V2xkyS5Jk-rn-11Nd5jUvxPoMZ_Uw,12448 twisted/names/secondary.py,sha256=Rzwbf-PCbzePioyR5AArHoS7ua_qXOz5GwkYNOJhmP4,6085 twisted/names/server.py,sha256=jtcUz8H2GW3a0XeUrpmkhmlF7GVJZHd8u9Rei06BDJY,22305 twisted/names/srvconnect.py,sha256=uGSBa0VzKQJgi-E4NbyB0MQgDNiX2BUSgPqJGPF5rW8,9144 twisted/names/tap.py,sha256=Jls1yZyObp10LUj9DdWFDXniWfju5JbXG8qMJYBHrCY,4832 twisted/names/test/__init__.py,sha256=d3JTIolomvO_PAkMM5Huipo6vc06Zyp3zhfeAuu_rEQ,26 twisted/names/test/__pycache__/__init__.cpython-36.pyc,, twisted/names/test/__pycache__/test_cache.cpython-36.pyc,, twisted/names/test/__pycache__/test_client.cpython-36.pyc,, twisted/names/test/__pycache__/test_common.cpython-36.pyc,, twisted/names/test/__pycache__/test_dns.cpython-36.pyc,, twisted/names/test/__pycache__/test_examples.cpython-36.pyc,, twisted/names/test/__pycache__/test_hosts.cpython-36.pyc,, twisted/names/test/__pycache__/test_names.cpython-36.pyc,, twisted/names/test/__pycache__/test_resolve.cpython-36.pyc,, twisted/names/test/__pycache__/test_rfc1982.cpython-36.pyc,, twisted/names/test/__pycache__/test_rootresolve.cpython-36.pyc,, twisted/names/test/__pycache__/test_server.cpython-36.pyc,, twisted/names/test/__pycache__/test_srvconnect.cpython-36.pyc,, twisted/names/test/__pycache__/test_tap.cpython-36.pyc,, twisted/names/test/__pycache__/test_util.cpython-36.pyc,, twisted/names/test/test_cache.py,sha256=YNu7OeMpeNNFPJbzvE9a6OxDMybG_hU3xd466ZM_ztM,4916 twisted/names/test/test_client.py,sha256=nbfVm1Zep5DpKtXhKASpaqXDrH1NbsQwVYC6WcWN1wc,41764 twisted/names/test/test_common.py,sha256=3iP0IAmfWr-RKQdCmCKNvJw5k8U6DhII6BIN1zvOR7c,4206 twisted/names/test/test_dns.py,sha256=Y-8t2MAVHOijV_zNx_5aaNr4C8Ac0ALOrg7LGa7ppow,158849 twisted/names/test/test_examples.py,sha256=-VKU30q-Jkfw2ucz0so0hyyjrH1fJOpcKD1u7NcS6yY,5349 twisted/names/test/test_hosts.py,sha256=c5cs0ksd5N6s9qa0gxC-rnKd7baJVSiehvSB46EnlDg,8547 twisted/names/test/test_names.py,sha256=KLblh3uylJ30Fr8Ku83qOwoCKdIg8v9D9JkEN7lMUNE,43096 twisted/names/test/test_resolve.py,sha256=A3KYPzouCKlR5UOcUz0NATHYhey8QnVLL_398BXQaCo,1075 twisted/names/test/test_rfc1982.py,sha256=Ib4CocE0s8JAEqp_TvaZH6EjweB_QnrTuuDPmBEmkDo,13992 twisted/names/test/test_rootresolve.py,sha256=1Cp_QKpBToYSyjW8R3EdJRvbfbHcvvnVMwKeQyNAG8Q,25643 twisted/names/test/test_server.py,sha256=JQYGRbPoW6Hk5Sq9vsinlehP3KSToh2nRoZdVc3RSFA,41234 twisted/names/test/test_srvconnect.py,sha256=XSatW9AjCca_uL60AhXrPpOLlosV0AkW733r6kw-iVc,10124 twisted/names/test/test_tap.py,sha256=kLMsChF8IiCt5l0FQNZeVxoOIG7FlIupb17q6Ld3Q_U,4961 twisted/names/test/test_util.py,sha256=IGGlPKZ5Wn5L0A_Jj0MdN3_r_xghj_X4J0VLAqR8LTQ,3915 twisted/pair/__init__.py,sha256=69Cr0TdbaWqxKH2AEB9jxdRNydRnbWwx4kHzYlAFs7c,315 twisted/pair/__pycache__/__init__.cpython-36.pyc,, twisted/pair/__pycache__/ethernet.cpython-36.pyc,, twisted/pair/__pycache__/ip.cpython-36.pyc,, twisted/pair/__pycache__/raw.cpython-36.pyc,, twisted/pair/__pycache__/rawudp.cpython-36.pyc,, twisted/pair/__pycache__/testing.cpython-36.pyc,, twisted/pair/__pycache__/tuntap.cpython-36.pyc,, twisted/pair/ethernet.py,sha256=ZKLmhJ9rqPsDVFFgcYqjtnyQf8gkGL-G7jnMNaXc2jo,1698 twisted/pair/ip.py,sha256=Kb5HfbLZ0wikbfIaKPLgGQHkPHcba5GlbGad3s5932k,2595 twisted/pair/raw.py,sha256=NJOSZ0D9qp78r3B_T9jivDozAGPaUagg8xtQOogtbAo,811 twisted/pair/rawudp.py,sha256=F67B2yZ0IqpW9bMNWk3-4gvQ1YtW9DZyBL6ZeWwzG8Q,1813 twisted/pair/test/__init__.py,sha256=mAc-2NR8lrqRyWN-YI4kn9LUZ7So6ae3xJ2RzldDQ1w,13 twisted/pair/test/__pycache__/__init__.cpython-36.pyc,, twisted/pair/test/__pycache__/test_ethernet.cpython-36.pyc,, twisted/pair/test/__pycache__/test_ip.cpython-36.pyc,, twisted/pair/test/__pycache__/test_rawudp.cpython-36.pyc,, twisted/pair/test/__pycache__/test_tuntap.cpython-36.pyc,, twisted/pair/test/test_ethernet.py,sha256=iWxYX0e65w5Nq6r_cthyLSpAwvWjVW7AX-UVhfBpR_c,6653 twisted/pair/test/test_ip.py,sha256=euftwHEBKqvwaQQpta9jvKS5de49tz3oqtLC10p2xlg,15148 twisted/pair/test/test_rawudp.py,sha256=yze31pPb0eKWsfRUrHOFBIr6jC9tTgGvekw42Gk-T5M,13074 twisted/pair/test/test_tuntap.py,sha256=S2OTUrXwu1-ku_dEM6MHjmTlKpuRsajQuUgn9XJKnpo,47567 twisted/pair/testing.py,sha256=MZRPms9JY-FTQX8k91gND5MNd23Esz_RDLBLqNZodp0,17307 twisted/pair/tuntap.py,sha256=TxshMXYq2GYTWyxxjaNPpIPggigozJ0PFLkAnG-z8GA,12538 twisted/persisted/__init__.py,sha256=zyAGR02ZdUO8fNoKHf602wUApt3DvnnfD-B4iJ1QJqI,136 twisted/persisted/__pycache__/__init__.cpython-36.pyc,, twisted/persisted/__pycache__/aot.cpython-36.pyc,, twisted/persisted/__pycache__/crefutil.cpython-36.pyc,, twisted/persisted/__pycache__/dirdbm.cpython-36.pyc,, twisted/persisted/__pycache__/sob.cpython-36.pyc,, twisted/persisted/__pycache__/styles.cpython-36.pyc,, twisted/persisted/aot.py,sha256=9J-HHadGM8z7jDH37peHqP1WdgZ9roqmAnqycOeB-n8,18605 twisted/persisted/crefutil.py,sha256=Xp3-vK0OeOroNd2NJH1vJhiXUHsmBZ6_9r_uDK9FE8g,4375 twisted/persisted/dirdbm.py,sha256=JU8ZwO7ZF2lIhc6H-T6lCvAsgXxiydYc31JRkLqbj_8,10141 twisted/persisted/sob.py,sha256=-yhIm6Ah6UhGRTs3v6l6ZWHJMU8DorDuadg34YztWHs,5197 twisted/persisted/styles.py,sha256=wD9iJHv7hIH6GUTP9s5HuREfNzCA4yguaRHeWacFzc4,13495 twisted/persisted/test/__init__.py,sha256=C5rPf38HFfuGrl35BEIrhxgs9HtwoEMpxPvNdNHNELk,113 twisted/persisted/test/__pycache__/__init__.cpython-36.pyc,, twisted/persisted/test/__pycache__/test_styles.cpython-36.pyc,, twisted/persisted/test/test_styles.py,sha256=0s26icbUsYU1v4FLhTpxaT49vLuYDhr4Y6etvTru1JQ,3388 twisted/plugin.py,sha256=1ZW0wvUbQ0GYV0ry7JX2qu2LTH35b6WzfPRTG9HhwDo,8407 twisted/plugins/__init__.py,sha256=lk9vXST0ZZip_WzApTLgsFmWKA0SDJLHe5HyNBFDers,590 twisted/plugins/__pycache__/__init__.cpython-36.pyc,, twisted/plugins/__pycache__/cred_anonymous.cpython-36.pyc,, twisted/plugins/__pycache__/cred_file.cpython-36.pyc,, twisted/plugins/__pycache__/cred_memory.cpython-36.pyc,, twisted/plugins/__pycache__/cred_sshkeys.cpython-36.pyc,, twisted/plugins/__pycache__/cred_unix.cpython-36.pyc,, twisted/plugins/__pycache__/twisted_conch.cpython-36.pyc,, twisted/plugins/__pycache__/twisted_core.cpython-36.pyc,, twisted/plugins/__pycache__/twisted_ftp.cpython-36.pyc,, twisted/plugins/__pycache__/twisted_inet.cpython-36.pyc,, twisted/plugins/__pycache__/twisted_names.cpython-36.pyc,, twisted/plugins/__pycache__/twisted_portforward.cpython-36.pyc,, twisted/plugins/__pycache__/twisted_reactors.cpython-36.pyc,, twisted/plugins/__pycache__/twisted_runner.cpython-36.pyc,, twisted/plugins/__pycache__/twisted_socks.cpython-36.pyc,, twisted/plugins/__pycache__/twisted_trial.cpython-36.pyc,, twisted/plugins/__pycache__/twisted_web.cpython-36.pyc,, twisted/plugins/__pycache__/twisted_words.cpython-36.pyc,, twisted/plugins/cred_anonymous.py,sha256=vpl3-TdqBrPcPYEMnuDPcI0ZfWDmvxS6n0W6rt9dS-Q,1017 twisted/plugins/cred_file.py,sha256=EbDvh1Sgf5BcoTD5k9-sJey43wiJpJNmypHUVWD4TcA,1875 twisted/plugins/cred_memory.py,sha256=8rRWaV93xIOIY5sXnUCpFsvD2va0v_iqs3dDO7KAUp0,2387 twisted/plugins/cred_sshkeys.py,sha256=0bSoTYESFswyRdGxSsmr5q9LZs4JL0sAnAzXMeLeecc,1498 twisted/plugins/cred_unix.py,sha256=xUlXtGd6RPEpWrO5J1cB6Cw6URJ1cSEtdcq1Xe5vBYc,5905 twisted/plugins/twisted_conch.py,sha256=5uZ8DxMkL9ZoajHKqTCxOGEMarZIeomKgfY9JfGA2LA,519 twisted/plugins/twisted_core.py,sha256=UYnNWMLp3tMpbWjzQYDNYGyQeO6CKhrum7-Qo_wUnos,589 twisted/plugins/twisted_ftp.py,sha256=2YITyfTb3iAUnJoEfMCh0jVjnGjO6O_nHR_SAS4auGs,229 twisted/plugins/twisted_inet.py,sha256=VBtuyAPilMxsjykF4rVLyGgtr0R_Q3dXB8E-SBFztVk,260 twisted/plugins/twisted_names.py,sha256=8dMOvdQzlVu6etrsLKGFcj4LJlbg9N2FFqzTZais7bg,247 twisted/plugins/twisted_portforward.py,sha256=f3tDxoFwoJV0BfW8b1jXrYjr72GQIKcgGykaxkUBcpg,275 twisted/plugins/twisted_reactors.py,sha256=bZjUWLDKFMRW5kReCWCyPTb6zYiPCSyZ4_dJJ0vgTH0,1880 twisted/plugins/twisted_runner.py,sha256=4onfqhfRsx2XnBn7c4bWt8dxMmQyrpALUYeB9ZZ20EQ,278 twisted/plugins/twisted_socks.py,sha256=M8G4xLBbk3S-klsY0HNwWIA2xXhy4VQpjsLRM_bIvLE,247 twisted/plugins/twisted_trial.py,sha256=hpii1iu8KvcTz6basUtpz0VfZ3b6TLCINYpLjy2l78I,2084 twisted/plugins/twisted_web.py,sha256=ef7vqQPmVigdoowgJWR3zAwgPs9ANV9ezC5cEQOuaQc,312 twisted/plugins/twisted_words.py,sha256=Qf1p7QsLjl0uqGAm-MvricGjyZE-Ceq3PqjwwrJokYo,1029 twisted/positioning/__init__.py,sha256=y_fhSJlC3z4GeB-rC3z2tiprb3JxxGvlYv-GHmuhv1Q,223 twisted/positioning/__pycache__/__init__.cpython-36.pyc,, twisted/positioning/__pycache__/_sentence.cpython-36.pyc,, twisted/positioning/__pycache__/base.cpython-36.pyc,, twisted/positioning/__pycache__/ipositioning.cpython-36.pyc,, twisted/positioning/__pycache__/nmea.cpython-36.pyc,, twisted/positioning/_sentence.py,sha256=G8vKaSb_8T-khzyGeeDht6PWtQYugU4_kQr4-VdET8A,4004 twisted/positioning/base.py,sha256=H83JCeCxX0V3GGN0sEyHiEDeuM1GyDOMAgf6ngnl4LQ,28410 twisted/positioning/ipositioning.py,sha256=hxGOOrFK0Hqj0gvNA5lTU0J6sbQr-zN4ErVh8gRnffA,3013 twisted/positioning/nmea.py,sha256=1rcMypYwWD6A468USl9lbOb80Qxla6_VVsSTTOqXPyY,35975 twisted/positioning/test/__init__.py,sha256=Ekrh30kyy4hMgeFG33jFNP-S209JCflSF7hTan4MKEo,125 twisted/positioning/test/__pycache__/__init__.cpython-36.pyc,, twisted/positioning/test/__pycache__/receiver.cpython-36.pyc,, twisted/positioning/test/__pycache__/test_base.cpython-36.pyc,, twisted/positioning/test/__pycache__/test_nmea.cpython-36.pyc,, twisted/positioning/test/__pycache__/test_sentence.cpython-36.pyc,, twisted/positioning/test/receiver.py,sha256=eLkfrggQVEPHfpB12vC1E8T3oud5tvAYK4gEejC4wjE,1166 twisted/positioning/test/test_base.py,sha256=FbsYzs122PkztgjDKxCb44Lb626UAqOyJBwwLXQjn6g,28897 twisted/positioning/test/test_nmea.py,sha256=mTs_PNwZv-DmMJC_QIibP_kbSazNXl2DY14BaheHKAw,39925 twisted/positioning/test/test_sentence.py,sha256=REOT5BUY-vUz_FEbmWrapgel9-dmcH41fIpeNo4peJE,4770 twisted/protocols/__init__.py,sha256=11Pa7Emr3WMc3VvzbjfrTydeVl4rpQJ587BWXZD125w,391 twisted/protocols/__pycache__/__init__.cpython-36.pyc,, twisted/protocols/__pycache__/amp.cpython-36.pyc,, twisted/protocols/__pycache__/basic.cpython-36.pyc,, twisted/protocols/__pycache__/dict.cpython-36.pyc,, twisted/protocols/__pycache__/finger.cpython-36.pyc,, twisted/protocols/__pycache__/ftp.cpython-36.pyc,, twisted/protocols/__pycache__/htb.cpython-36.pyc,, twisted/protocols/__pycache__/ident.cpython-36.pyc,, twisted/protocols/__pycache__/loopback.cpython-36.pyc,, twisted/protocols/__pycache__/memcache.cpython-36.pyc,, twisted/protocols/__pycache__/pcp.cpython-36.pyc,, twisted/protocols/__pycache__/policies.cpython-36.pyc,, twisted/protocols/__pycache__/portforward.cpython-36.pyc,, twisted/protocols/__pycache__/postfix.cpython-36.pyc,, twisted/protocols/__pycache__/sip.cpython-36.pyc,, twisted/protocols/__pycache__/socks.cpython-36.pyc,, twisted/protocols/__pycache__/stateful.cpython-36.pyc,, twisted/protocols/__pycache__/tls.cpython-36.pyc,, twisted/protocols/__pycache__/wire.cpython-36.pyc,, twisted/protocols/amp.py,sha256=y_Nvxa4lOQpx3D3qrWIB_XkY3AiMCG7OQPSm5lBwI1Y,97898 twisted/protocols/basic.py,sha256=aJGgFcI8hRVuqcXJrp5aPCgUx-U73SKUYhOSprEK4LQ,32061 twisted/protocols/dict.py,sha256=osi8Fjn7QALiRTtuFyDdZymRtdjxceO5CxwIaQBeqSk,10762 twisted/protocols/finger.py,sha256=MHoysns-8Wi3QfrZNIvoUQVyASQSzx-t3GzjYp9MPK0,1220 twisted/protocols/ftp.py,sha256=DzUEKyf9NmVXtOrzOZbV0IPkpR96WSvcRRW1REM8CEk,106132 twisted/protocols/haproxy/__init__.py,sha256=TyD3qy2qDa2p6zw0Q3DkPeWS5ChiAEzX0JZfAfFdtYg,251 twisted/protocols/haproxy/__pycache__/__init__.cpython-36.pyc,, twisted/protocols/haproxy/__pycache__/_exceptions.cpython-36.pyc,, twisted/protocols/haproxy/__pycache__/_info.cpython-36.pyc,, twisted/protocols/haproxy/__pycache__/_interfaces.cpython-36.pyc,, twisted/protocols/haproxy/__pycache__/_parser.cpython-36.pyc,, twisted/protocols/haproxy/__pycache__/_v1parser.cpython-36.pyc,, twisted/protocols/haproxy/__pycache__/_v2parser.cpython-36.pyc,, twisted/protocols/haproxy/__pycache__/_wrapper.cpython-36.pyc,, twisted/protocols/haproxy/_exceptions.py,sha256=SW9Zeft6X9W2HtPY9Mfh2AIbQVuoX8UNs7l4eOz0Izo,1085 twisted/protocols/haproxy/_info.py,sha256=OB180dloGeTnpjxeVBObB6P-e3VU223ZK4ImHsBNvZM,929 twisted/protocols/haproxy/_interfaces.py,sha256=bDsfV4TKelDi5vW_dig0vmh8grcM7R6KZJrb7kTnlO0,1794 twisted/protocols/haproxy/_parser.py,sha256=AT7MMzwMx8kaMbVjDjLiJSt8MiuzApbwu7LFn5vxTOI,2051 twisted/protocols/haproxy/_v1parser.py,sha256=LAM2OeeV-vC5b85ohEPk1mcUnqMOQJgnUvA0NF7kUKk,4326 twisted/protocols/haproxy/_v2parser.py,sha256=JkSl8VWd7YMw5V6JNJ6LhunnWf_DVl_jde6isu7_VF4,6307 twisted/protocols/haproxy/_wrapper.py,sha256=4lA_nXL-pdzgXJ_5DXPwrnqvfOSC9gWLuovOdlMJ6jA,3323 twisted/protocols/haproxy/test/__init__.py,sha256=gxu5b7Qz4fM2tMbIm4VeUfMY4NthR3rzZlnX1VO_JUU,183 twisted/protocols/haproxy/test/__pycache__/__init__.cpython-36.pyc,, twisted/protocols/haproxy/test/__pycache__/test_parser.cpython-36.pyc,, twisted/protocols/haproxy/test/__pycache__/test_v1parser.cpython-36.pyc,, twisted/protocols/haproxy/test/__pycache__/test_v2parser.cpython-36.pyc,, twisted/protocols/haproxy/test/__pycache__/test_wrapper.cpython-36.pyc,, twisted/protocols/haproxy/test/test_parser.py,sha256=k7RipRqyta7A4XySeBDQQrNBTqWO3nMr7ZgTgHpYLy4,3467 twisted/protocols/haproxy/test/test_v1parser.py,sha256=4hUm8u_vbAwPrrdRouAN1bDephjikVn5yFrB3e6b1H8,4694 twisted/protocols/haproxy/test/test_v2parser.py,sha256=PuyYjAYyLho-M8iOU1znggWjEvowhFTFVemblipH-EE,11777 twisted/protocols/haproxy/test/test_wrapper.py,sha256=8vRib0ifsoeAeeefQN0y5r0lo0_sTEMpoMzKUx6W4c4,13035 twisted/protocols/htb.py,sha256=NAiAptbEWvk46eDOlvLi1NjDfgkhSAFzNdS46mPjqsM,9327 twisted/protocols/ident.py,sha256=KV78Gj7IguHGpsOzEgkgIFPAqaiUNlXoiRSGBUChZcc,7781 twisted/protocols/loopback.py,sha256=xRPWLdrukRJth5yp8TWXspLofVR_HApqfk65pE7UJ4s,11928 twisted/protocols/memcache.py,sha256=98KnhDWuVDj_FBiNiM5MAsQrQg6xCrjkIko_rxqigTM,23693 twisted/protocols/pcp.py,sha256=sZWqAcibTFdsZnep-2Ml9lZwtT86z8FL6QCr-UH7-eU,7088 twisted/protocols/policies.py,sha256=SIp1MDpyhZTf7296XGiJHP_OC2WmMFS0G3Dwo9wOWl8,21327 twisted/protocols/portforward.py,sha256=Ob19TUzNKwq5OACeTBe35ZthfaGtu0o96gAbGBMGTNo,2383 twisted/protocols/postfix.py,sha256=2erA8Ap2nKF9W6t25TXk3ozG9wsW7ynDcjkN5BLwFQE,3953 twisted/protocols/sip.py,sha256=BSc-8qrcrx7gpz0Ku1vqX_wkdrZssi9huD1nDVEsoWs,37794 twisted/protocols/socks.py,sha256=kYGCYSO_K4YcSW3eG2iij9qye45-sokhMHz6h5gSejw,7816 twisted/protocols/stateful.py,sha256=6r-k3nLKMIa4M_9x1NRn5LWJ2BUPrn4jRh1TP8Jqltw,1640 twisted/protocols/test/__init__.py,sha256=QMkwFc9QOiSDp4ZU06wLjPDi3iw0y3ysUgdjOPceMu0,118 twisted/protocols/test/__pycache__/__init__.cpython-36.pyc,, twisted/protocols/test/__pycache__/test_basic.cpython-36.pyc,, twisted/protocols/test/__pycache__/test_tls.cpython-36.pyc,, twisted/protocols/test/test_basic.py,sha256=2LqruAhTDMjhjP_afc018EQ2SwxmeBY6KXjS0KMBhZY,43214 twisted/protocols/test/test_tls.py,sha256=zSTdoAeXZEyNBM8yuMD07rBJSgGsoPJFjdCp7WQ_dyA,75552 twisted/protocols/tls.py,sha256=GmaSZCckJRo1W-winsYwf_uHfOeg-2wl1CveH5PgEWU,32620 twisted/protocols/wire.py,sha256=47h5tn358eT-T_c-QULiRm8CavhH74TxdLFKx-B1mUg,2556 twisted/python/__init__.py,sha256=59IqUE-1fknNPjKnfvC46EWCIdUeqEcUxAofVFiPSSU,674 twisted/python/__pycache__/__init__.cpython-36.pyc,, twisted/python/__pycache__/_appdirs.cpython-36.pyc,, twisted/python/__pycache__/_inotify.cpython-36.pyc,, twisted/python/__pycache__/_oldstyle.cpython-36.pyc,, twisted/python/__pycache__/_release.cpython-36.pyc,, twisted/python/__pycache__/_setup.cpython-36.pyc,, twisted/python/__pycache__/_shellcomp.cpython-36.pyc,, twisted/python/__pycache__/_textattributes.cpython-36.pyc,, twisted/python/__pycache__/_tzhelper.cpython-36.pyc,, twisted/python/__pycache__/_url.cpython-36.pyc,, twisted/python/__pycache__/compat.cpython-36.pyc,, twisted/python/__pycache__/components.cpython-36.pyc,, twisted/python/__pycache__/constants.cpython-36.pyc,, twisted/python/__pycache__/context.cpython-36.pyc,, twisted/python/__pycache__/deprecate.cpython-36.pyc,, twisted/python/__pycache__/failure.cpython-36.pyc,, twisted/python/__pycache__/fakepwd.cpython-36.pyc,, twisted/python/__pycache__/filepath.cpython-36.pyc,, twisted/python/__pycache__/formmethod.cpython-36.pyc,, twisted/python/__pycache__/htmlizer.cpython-36.pyc,, twisted/python/__pycache__/lockfile.cpython-36.pyc,, twisted/python/__pycache__/log.cpython-36.pyc,, twisted/python/__pycache__/logfile.cpython-36.pyc,, twisted/python/__pycache__/modules.cpython-36.pyc,, twisted/python/__pycache__/monkey.cpython-36.pyc,, twisted/python/__pycache__/procutils.cpython-36.pyc,, twisted/python/__pycache__/randbytes.cpython-36.pyc,, twisted/python/__pycache__/rebuild.cpython-36.pyc,, twisted/python/__pycache__/reflect.cpython-36.pyc,, twisted/python/__pycache__/release.cpython-36.pyc,, twisted/python/__pycache__/roots.cpython-36.pyc,, twisted/python/__pycache__/runtime.cpython-36.pyc,, twisted/python/__pycache__/sendmsg.cpython-36.pyc,, twisted/python/__pycache__/shortcut.cpython-36.pyc,, twisted/python/__pycache__/syslog.cpython-36.pyc,, twisted/python/__pycache__/systemd.cpython-36.pyc,, twisted/python/__pycache__/text.cpython-36.pyc,, twisted/python/__pycache__/threadable.cpython-36.pyc,, twisted/python/__pycache__/threadpool.cpython-36.pyc,, twisted/python/__pycache__/url.cpython-36.pyc,, twisted/python/__pycache__/urlpath.cpython-36.pyc,, twisted/python/__pycache__/usage.cpython-36.pyc,, twisted/python/__pycache__/util.cpython-36.pyc,, twisted/python/__pycache__/versions.cpython-36.pyc,, twisted/python/__pycache__/win32.cpython-36.pyc,, twisted/python/__pycache__/zippath.cpython-36.pyc,, twisted/python/__pycache__/zipstream.cpython-36.pyc,, twisted/python/_appdirs.py,sha256=bw_i8btCVr-TH62QlcP-Gdt5v6R0hoCaiZyYk2ZvVxA,788 twisted/python/_inotify.py,sha256=aYbn1L_5MM62Gl60GzlkiwOHTc6mB0lUCr1tP-FsgPU,3455 twisted/python/_oldstyle.py,sha256=ksosHBxHm691H3HwaR1ORGMNC-7q2U-IwTMpcxqugZ0,2593 twisted/python/_pydoctortemplates/common.html,sha256=KxdAlEXi-ihLekHIh0t1VGHIRNv1QzOHLdU7F3jtuTY,3341 twisted/python/_pydoctortemplates/index.html,sha256=JecyxRLyBd8Z45KbYD_rQeTeRizrXIjlNslU3uLppjM,3565 twisted/python/_pydoctortemplates/summary.html,sha256=E_LjXUI4vwx8G7_5ZwAd6LndTeYxUTCrjGUOMiUtu1Y,1980 twisted/python/_release.py,sha256=xqUE9jUSx0rKKI00hFYfz7NXA8h7b9orFpWZODYRJek,18550 twisted/python/_setup.py,sha256=0qYzsSph8fvBU-XmVsCi6tTEz41Z2eva_N25E_1c78Q,14352 twisted/python/_shellcomp.py,sha256=9mb_W8t3VkpejPSNWyrkiT5fGLdTc4V6mi3uvS7Ej7k,24830 twisted/python/_textattributes.py,sha256=5HDokoRNMdRKmmKh1yrdymoOE7qTWkeNPOm8tOUePx8,9079 twisted/python/_tzhelper.py,sha256=YFN_nX1P-QvHzMUKKXcA9eQsUf2n9MHYr2lIecLqy70,3192 twisted/python/_url.py,sha256=7-vSoeXo3oMd6xDG3GvsDb7BXpRx8tnAc6HpPUk9zLQ,253 twisted/python/compat.py,sha256=NJEtYTaa_LA3j85-TkfyusjkRgk28CqpBy_3aDCvI0k,22907 twisted/python/components.py,sha256=jf9hOzQqetZfpDgBMELxCPdM6S8ALQYpBV-a2rVK4uc,14242 twisted/python/constants.py,sha256=GuTBebugkgjf4CkvJaOxy3GLYrV72Ftz_IFexC6dn2Y,544 twisted/python/context.py,sha256=2mPa-VtpamaSkfz5433svgisrVaT7mKPhQVgQ1i0SZY,4024 twisted/python/deprecate.py,sha256=EfkGx7d9K0st0vrsiNcvOIaD5_C2fQa8aWZbBCCloXI,26948 twisted/python/failure.py,sha256=2KBV5GN7gy-umIdziF1Mri_JCLlr6sL9fzx7Exp13i4,27564 twisted/python/fakepwd.py,sha256=26yDkt13tXXNTGv2Ua3qQ2t_0FJy0sesVge86O8ulAc,6138 twisted/python/filepath.py,sha256=rtd9HVtB_NZOWq3K2iZpaCw6_R-mjVlouVV6WylGljw,58887 twisted/python/formmethod.py,sha256=xpgE8EVYQQ_bgWySJp74ZT4ecY1SBL1hY4t5Oz_pDLg,11460 twisted/python/htmlizer.py,sha256=x91-QwzLlcF8Zfw3vG8NzzCabm7SF4m8EARO1v9llDI,3541 twisted/python/lockfile.py,sha256=ZgEOdSPnK3RFXTPz9cuvieQrp2uNvGV2bow8qiqSLmE,7718 twisted/python/log.py,sha256=etGKoolsiXr__IGZN9SG8YMd-JS3hMFIpphvvIRfNak,22472 twisted/python/logfile.py,sha256=TNbhiOp692oNKnQ9SCBz3oJAlfgbIYk1R6cnYFEYWRY,10083 twisted/python/modules.py,sha256=Zret5tlILxKbI05x4Rw_b0Qw0pBxcYIMn0ssSGQLaAs,27141 twisted/python/monkey.py,sha256=dTtT6kIz1vvSmIOUKOGGGlRAmpWS9UCzRGyc09hZHmE,2227 twisted/python/procutils.py,sha256=lkI5rWeD1iNyKsp9_L0XI8Lm3I4o7W6AzsiwdoFfLDU,1419 twisted/python/randbytes.py,sha256=dpPatxms22rgQwoLzuPYGWbWJc1ogVOyUrB_eAW1Fjs,3959 twisted/python/rebuild.py,sha256=9ro6DKmvmfQzMs7RKn3Tho2kL1pjmyyAwI1Rpm8mb2k,9268 twisted/python/reflect.py,sha256=ul_gpPzj1JhozrflHEW4UdRwysBtUd_N1fjSn8Wsn84,19477 twisted/python/release.py,sha256=fOCKs0fEKqLZduuDuBijZ0MDIkGEWliJApxEaAYlkEk,1192 twisted/python/roots.py,sha256=P98gPe16GCettjsnJCNPKAyeBJTyJOkvIKDx1-JMRu4,7404 twisted/python/runtime.py,sha256=XnzEnaDzX01aFGd-T-hw7sqP_yh30m56ttPALWNB9Fo,6216 twisted/python/sendmsg.py,sha256=V9Sxc2I2OI6iXS9Fy1GYR__nH8MiWEkLcxlhO6B3m24,3420 twisted/python/shortcut.py,sha256=HIlHg7G7u9jMhC09DrLPOv8zNnvF4wkz2AjBL-GKrn8,2253 twisted/python/syslog.py,sha256=Cu67zZN15N21NESUvs9RFQ4yQTdTzzn0ZTikKEhVDjA,3730 twisted/python/systemd.py,sha256=onsuaC2aPtrUS3DNeHMdoclD3v79vcm4jFmDU_pqBGE,2834 twisted/python/test/__init__.py,sha256=V0srj7fq1Y17ZVfFgUc0n5ueVkK0InJNIT90pWlEKLI,42 twisted/python/test/__pycache__/__init__.cpython-36.pyc,, twisted/python/test/__pycache__/deprecatedattributes.cpython-36.pyc,, twisted/python/test/__pycache__/modules_helpers.cpython-36.pyc,, twisted/python/test/__pycache__/pullpipe.cpython-36.pyc,, twisted/python/test/__pycache__/test_appdirs.cpython-36.pyc,, twisted/python/test/__pycache__/test_components.cpython-36.pyc,, twisted/python/test/__pycache__/test_constants.cpython-36.pyc,, twisted/python/test/__pycache__/test_deprecate.cpython-36.pyc,, twisted/python/test/__pycache__/test_dist3.cpython-36.pyc,, twisted/python/test/__pycache__/test_fakepwd.cpython-36.pyc,, twisted/python/test/__pycache__/test_htmlizer.cpython-36.pyc,, twisted/python/test/__pycache__/test_inotify.cpython-36.pyc,, twisted/python/test/__pycache__/test_release.cpython-36.pyc,, twisted/python/test/__pycache__/test_runtime.cpython-36.pyc,, twisted/python/test/__pycache__/test_sendmsg.cpython-36.pyc,, twisted/python/test/__pycache__/test_setup.cpython-36.pyc,, twisted/python/test/__pycache__/test_shellcomp.cpython-36.pyc,, twisted/python/test/__pycache__/test_syslog.cpython-36.pyc,, twisted/python/test/__pycache__/test_systemd.cpython-36.pyc,, twisted/python/test/__pycache__/test_textattributes.cpython-36.pyc,, twisted/python/test/__pycache__/test_tzhelper.cpython-36.pyc,, twisted/python/test/__pycache__/test_url.cpython-36.pyc,, twisted/python/test/__pycache__/test_urlpath.cpython-36.pyc,, twisted/python/test/__pycache__/test_util.cpython-36.pyc,, twisted/python/test/__pycache__/test_versions.cpython-36.pyc,, twisted/python/test/__pycache__/test_zippath.cpython-36.pyc,, twisted/python/test/__pycache__/test_zipstream.cpython-36.pyc,, twisted/python/test/_deprecatetests.py.3only,sha256=qSX82XTcTBq4SpzmvjFlf-fK64geLp0spny-mRM_Kms,1814 twisted/python/test/deprecatedattributes.py,sha256=oTFSMS8Xi6q4JUgh5nUlBsmH3WrPkANJcKkI8plLJ94,571 twisted/python/test/modules_helpers.py,sha256=Ugs47h2kBaWydzLUHEYJx5lBf2a4vvpZuPAU3qaH4Sc,1605 twisted/python/test/pullpipe.py,sha256=hyX-tJuVuAo3QK76Q4Z0-Ots3Jo8ia3-9HWUPexlnuM,1220 twisted/python/test/test_appdirs.py,sha256=IpWQQKEiFNFnZahLWJZvHmM3dr1RKA_JERpbNLh3wLY,1081 twisted/python/test/test_components.py,sha256=HNKATjfPnL5lIxVS1wCBGTIb4NYFPkZzo05xNpJLRY8,25974 twisted/python/test/test_constants.py,sha256=_k490Ijg6HpYx_jHTjSedSD555Ujz0FHbrvLV1xNuYs,38117 twisted/python/test/test_deprecate.py,sha256=_xNUpOwd8TAbTC39m_wVEmQrSU3DaBfDoyVb40RLoDY,38930 twisted/python/test/test_dist3.py,sha256=QoIwlgUmeEtwcfbp2BLpqIiqub97v2fAHLw77BEYKbE,1858 twisted/python/test/test_fakepwd.py,sha256=2ulp3433yk5zIYcmb96ZUd2VXc8X-Q07xGdC54_OLyQ,14107 twisted/python/test/test_htmlizer.py,sha256=mA0YLFeplomK31oADOCo8-woa8ALbgfEu1FVLGSmLGw,1266 twisted/python/test/test_inotify.py,sha256=TPSjt9OPRp4hyEk05ZUl4281yuUI_etJ5LETjEMXz6s,3639 twisted/python/test/test_release.py,sha256=sLrfF-SJYRnjwiwGtbBVICaRniIh8Q_7TB612gPm9wg,41046 twisted/python/test/test_runtime.py,sha256=W3p_U-4eBEWYb2pQPfFEelUoHP-j9H-whEYbvgZtRKo,7926 twisted/python/test/test_sendmsg.py,sha256=gmm-zG0rRwfTuy8ozGJ7xeBhDSCJezjyAHyf8djNm1s,25233 twisted/python/test/test_setup.py,sha256=EXT8DjgyTqS5_ecN150HzZi7eMGJQHLCihwwxbzA6cE,13699 twisted/python/test/test_shellcomp.py,sha256=6mHTIncdngMe5Nm42x9_oXH-H-O4BO7g3QzwdiwHQ18,21809 twisted/python/test/test_syslog.py,sha256=2f2Ik8tLD89X905NtsKczHQNw4ssMd9sDmwpI5WTZEA,4948 twisted/python/test/test_systemd.py,sha256=lC5l4suhb6cQGnXlcxUyx5ZR7MUAAq0Zrci-f9pneCs,6401 twisted/python/test/test_textattributes.py,sha256=3tIa0LITcWGQraaeuu1S3Ai1v8rnGiNnRYnpRuDvBUE,712 twisted/python/test/test_tzhelper.py,sha256=qbJVrzd42-2SmiGTXBbDYbLLuSD1i1F4IkbLuT2X124,3984 twisted/python/test/test_url.py,sha256=mwDdEvACowrPyxYNPqCR_b32s93sN7DzvpR73SqEMZM,29313 twisted/python/test/test_urlpath.py,sha256=j7qCw-4PNgHeoYmIplna8zzt5EvrnluRFH8wf0d14Gs,10328 twisted/python/test/test_util.py,sha256=x5clz1UK59zQ1pETP-mKj5L2S8WUYRUjnieY1q-jl6k,36460 twisted/python/test/test_versions.py,sha256=xCTFjXPc8r6DujRCDzavd9qkzL1hwzcxwyDcT5fOAS8,5400 twisted/python/test/test_zippath.py,sha256=LRDWmsm8shSxYiw2QOs4NFjXFef1hsCUIzxmOhCn0f0,3474 twisted/python/test/test_zipstream.py,sha256=ai-XdQAlvQ6uUAmm5ikIjIpj7WU4KhWTj50tgbN_lRg,12308 twisted/python/text.py,sha256=bI7CKqBudIqueU7lduVKsQqzTZipPdSoZoa0lR9IklI,5482 twisted/python/threadable.py,sha256=yx-911e3S7loq9svlCLbqrFtLbATJd-IrXtFyC1FzKI,3297 twisted/python/threadpool.py,sha256=SfnPhHyfbfzB8IBu2p_qyHbA5PKqfEesMhNBKqz0ctQ,9840 twisted/python/twisted-completion.zsh,sha256=DkNZis_hXXFAxUutigSn6gDRk8i70ylRrJ7ZBy-8NZo,1371 twisted/python/url.py,sha256=0vJfs6hgMrWkIR2ZgovyPASQlYHh2afVCFaQaGSLA2c,244 twisted/python/urlpath.py,sha256=GV2oT4B_QwtKVOfKjOZC5J_bIxVzblHGtP7-2aCqxXk,9084 twisted/python/usage.py,sha256=PmukwnG15RZjJwCwX4Z5moDUShWKwBVHwj1jocLVDZY,35002 twisted/python/util.py,sha256=4Pz0IZzKDqY9UFwqb-RU4HJoCUgrAO_h2-sLBMNR58o,27931 twisted/python/versions.py,sha256=VV-6OHSdnxuUPrfZ0tfb1kIxwU_nIIUA8Isedy1wYxc,322 twisted/python/win32.py,sha256=i2e7daTFnZVYWpmGjlPBH97IsXQKm5kiwX7Zy1vY2S4,4317 twisted/python/zippath.py,sha256=3iNAMvf_shM4KMaIHttR5HsBawMmHJy_h1z0emsvGPQ,9237 twisted/python/zipstream.py,sha256=yZb1fdWj1YHXrK9_sG4auyiQbZYrZsf2tsbTE65fT08,9757 twisted/runner/__init__.py,sha256=ahzGC9cYnSf0DSsEzBgV1oK-AyD_jb3jvVfEZA6mJZ0,124 twisted/runner/__pycache__/__init__.cpython-36.pyc,, twisted/runner/__pycache__/inetd.cpython-36.pyc,, twisted/runner/__pycache__/inetdconf.cpython-36.pyc,, twisted/runner/__pycache__/inetdtap.cpython-36.pyc,, twisted/runner/__pycache__/procmon.cpython-36.pyc,, twisted/runner/__pycache__/procmontap.cpython-36.pyc,, twisted/runner/inetd.py,sha256=EHkgH-8dYHD75CUaby9dkui4zGFToR6HhOpOxd5c7os,1962 twisted/runner/inetdconf.py,sha256=hHz7QpqQGJtg5YQ2KRj_IdmfmasiYnvw4ZXK4nRy98w,4917 twisted/runner/inetdtap.py,sha256=3EfntNfqiEBApmNjyXv10v9DZ0u4pk8EUbaf2hPEbX8,3558 twisted/runner/procmon.py,sha256=e7Rr8ANff3jDDirWYHQxTGm_F5sH24eKQBRZRulrkjg,12675 twisted/runner/procmontap.py,sha256=3S6LdXV2qIzUrWyNvHlk8ZMpc2Pri79PXjBIB0p6oEw,2298 twisted/runner/test/__init__.py,sha256=tjveH1kCFEM9rVaT_bsWV8TURsUKAgqn9p3zHZdDK40,114 twisted/runner/test/__pycache__/__init__.cpython-36.pyc,, twisted/runner/test/__pycache__/test_inetdconf.cpython-36.pyc,, twisted/runner/test/__pycache__/test_procmon.cpython-36.pyc,, twisted/runner/test/__pycache__/test_procmontap.cpython-36.pyc,, twisted/runner/test/test_inetdconf.py,sha256=r-HcBqvSvDbqcyc6viHoBdCfLrP0Pqm-ptALYU-kjFU,1785 twisted/runner/test/test_procmon.py,sha256=juFE0_OW7YLTIr9Ohe35EK84T7NVB0NXGrz4UsuqWNg,23346 twisted/runner/test/test_procmontap.py,sha256=f237F_JUHlqJQ0IDXoVBB9C_Qu2FZHJGTGOduSXWyNM,2520 twisted/scripts/__init__.py,sha256=TSubMCp4NhcXtFvbrOT9boiIzXpbSvATakl3yGBQwQY,261 twisted/scripts/__pycache__/__init__.cpython-36.pyc,, twisted/scripts/__pycache__/_twistd_unix.cpython-36.pyc,, twisted/scripts/__pycache__/_twistw.cpython-36.pyc,, twisted/scripts/__pycache__/htmlizer.cpython-36.pyc,, twisted/scripts/__pycache__/trial.cpython-36.pyc,, twisted/scripts/__pycache__/twistd.cpython-36.pyc,, twisted/scripts/_twistd_unix.py,sha256=oxV8dzXcxZe-kwzQLUoBT9TFrOSUmnJnaQvqh0ZL0q4,16380 twisted/scripts/_twistw.py,sha256=DR_MP8Ij2fqlYNTACS384RPuNHdOdIhrHsO0mDfUJG0,1562 twisted/scripts/htmlizer.py,sha256=HSlaUZZ5O7Lxnay2tNm-eFq6sqh7pKhvysixJdyGY_s,1868 twisted/scripts/test/__init__.py,sha256=p8A4Q5FXoU8Mch55_ANwPbv5-vTZikEVox_gvZELTHg,118 twisted/scripts/test/__pycache__/__init__.cpython-36.pyc,, twisted/scripts/test/__pycache__/test_scripts.cpython-36.pyc,, twisted/scripts/test/test_scripts.py,sha256=zsK4xm834A3KBsx6qUlbjfNWOiqw4iK1AmY4Ktf7dzg,4880 twisted/scripts/trial.py,sha256=vlKgrnUIuBmmMB5uAQjv1MYUARKc5EF54bVfQ-XDggY,21132 twisted/scripts/twistd.py,sha256=1UX9uFucre3pMc5VqLD-QrIfNbLgkF8FQ_Swr0D2wn4,867 twisted/spread/__init__.py,sha256=gfxmcnrYlpVRF5hdBZ3WUCItFEAc6DNSQw6D8e_f3RE,159 twisted/spread/__pycache__/__init__.cpython-36.pyc,, twisted/spread/__pycache__/banana.cpython-36.pyc,, twisted/spread/__pycache__/flavors.cpython-36.pyc,, twisted/spread/__pycache__/interfaces.cpython-36.pyc,, twisted/spread/__pycache__/jelly.cpython-36.pyc,, twisted/spread/__pycache__/pb.cpython-36.pyc,, twisted/spread/__pycache__/publish.cpython-36.pyc,, twisted/spread/__pycache__/util.cpython-36.pyc,, twisted/spread/banana.py,sha256=ofAgyONvTiJ5H5AaGhLxK8mnAo-6u7sgo00KqwMrxGY,12334 twisted/spread/flavors.py,sha256=n2_9c16yhkbpDAk6SkbN6UBVmmQ4_QU2YeUkIW_WgAQ,23455 twisted/spread/interfaces.py,sha256=A7UjlK03QoQ5KnPMUkvlpSnYqe5pdt7hUKv6MTLWa30,686 twisted/spread/jelly.py,sha256=aCq16IuReZ7btYNcO2zBGHZwfUDqWJ3YY0AEdmPVMwU,36468 twisted/spread/pb.py,sha256=BUR4Cf3snqevg95aH3yri__uN1cda5K2WNGeman8ZoU,52385 twisted/spread/publish.py,sha256=G4n2VvafpTtx7S8eEZtHC8s6naDBdwmLWNG4itifat8,4480 twisted/spread/test/__init__.py,sha256=67HyXbsJ4DIBtcMcUWJqGMHdQc2Z-NLinUz2MVUEplI,110 twisted/spread/test/__pycache__/__init__.cpython-36.pyc,, twisted/spread/test/__pycache__/test_banana.cpython-36.pyc,, twisted/spread/test/__pycache__/test_jelly.cpython-36.pyc,, twisted/spread/test/__pycache__/test_pb.cpython-36.pyc,, twisted/spread/test/__pycache__/test_pbfailure.cpython-36.pyc,, twisted/spread/test/test_banana.py,sha256=wV0I1JtZvg1VJZEZVPvfFEUQYSNS2eL-irtqarZyb_k,15456 twisted/spread/test/test_jelly.py,sha256=tVs3Ph0cGjO6lU9uqqe6qHTVASoUuPhi5N2Oa1FwFP8,19990 twisted/spread/test/test_pb.py,sha256=dy7mom3-TD89U_qz2NdnC1RTfwBwA4glz4QwvXxniuw,63874 twisted/spread/test/test_pbfailure.py,sha256=292uqxxnW0nLSWfubBnW3INJWksGImoECepvAC_h554,15433 twisted/spread/util.py,sha256=OWm_8dRgzKEvGVWxutxhdWOkupoc1sLj0FSuwX8JW1w,6387 twisted/tap/__init__.py,sha256=cWvA7ICrsBPoK11cax2E9a3OhvuDMYXRBvj_7tKXMDI,162 twisted/tap/__pycache__/__init__.cpython-36.pyc,, twisted/tap/__pycache__/ftp.cpython-36.pyc,, twisted/tap/__pycache__/portforward.cpython-36.pyc,, twisted/tap/__pycache__/socks.cpython-36.pyc,, twisted/tap/ftp.py,sha256=JmF1-GN5eoEYen773DBg0_-hSyHnFE94q1XrsG1Lz9Y,2002 twisted/tap/portforward.py,sha256=ZMY42wPvX5yfi1A3Ug_XLEOM7F5-UWhgzq2nY2WVNa8,795 twisted/tap/socks.py,sha256=uF0OnqGl16jcW6vtT7BvRImqsxSZPeJ8GPnUCoKghrc,1292 twisted/test/__init__.py,sha256=P8kgU78nKls3dRPDEW7-PYoYrm2J_hYMiYB6eJUHNbI,477 twisted/test/__pycache__/__init__.cpython-36.pyc,, twisted/test/__pycache__/crash_test_dummy.cpython-36.pyc,, twisted/test/__pycache__/iosim.cpython-36.pyc,, twisted/test/__pycache__/mock_win32process.cpython-36.pyc,, twisted/test/__pycache__/myrebuilder1.cpython-36.pyc,, twisted/test/__pycache__/myrebuilder2.cpython-36.pyc,, twisted/test/__pycache__/plugin_basic.cpython-36.pyc,, twisted/test/__pycache__/plugin_extra1.cpython-36.pyc,, twisted/test/__pycache__/plugin_extra2.cpython-36.pyc,, twisted/test/__pycache__/process_cmdline.cpython-36.pyc,, twisted/test/__pycache__/process_echoer.cpython-36.pyc,, twisted/test/__pycache__/process_fds.cpython-36.pyc,, twisted/test/__pycache__/process_getargv.cpython-36.pyc,, twisted/test/__pycache__/process_getenv.cpython-36.pyc,, twisted/test/__pycache__/process_linger.cpython-36.pyc,, twisted/test/__pycache__/process_reader.cpython-36.pyc,, twisted/test/__pycache__/process_signal.cpython-36.pyc,, twisted/test/__pycache__/process_stdinreader.cpython-36.pyc,, twisted/test/__pycache__/process_tester.cpython-36.pyc,, twisted/test/__pycache__/process_tty.cpython-36.pyc,, twisted/test/__pycache__/process_twisted.cpython-36.pyc,, twisted/test/__pycache__/proto_helpers.cpython-36.pyc,, twisted/test/__pycache__/reflect_helper_IE.cpython-36.pyc,, twisted/test/__pycache__/reflect_helper_VE.cpython-36.pyc,, twisted/test/__pycache__/reflect_helper_ZDE.cpython-36.pyc,, twisted/test/__pycache__/ssl_helpers.cpython-36.pyc,, twisted/test/__pycache__/stdio_test_consumer.cpython-36.pyc,, twisted/test/__pycache__/stdio_test_halfclose.cpython-36.pyc,, twisted/test/__pycache__/stdio_test_hostpeer.cpython-36.pyc,, twisted/test/__pycache__/stdio_test_lastwrite.cpython-36.pyc,, twisted/test/__pycache__/stdio_test_loseconn.cpython-36.pyc,, twisted/test/__pycache__/stdio_test_producer.cpython-36.pyc,, twisted/test/__pycache__/stdio_test_write.cpython-36.pyc,, twisted/test/__pycache__/stdio_test_writeseq.cpython-36.pyc,, twisted/test/__pycache__/test_abstract.cpython-36.pyc,, twisted/test/__pycache__/test_adbapi.cpython-36.pyc,, twisted/test/__pycache__/test_amp.cpython-36.pyc,, twisted/test/__pycache__/test_application.cpython-36.pyc,, twisted/test/__pycache__/test_compat.cpython-36.pyc,, twisted/test/__pycache__/test_context.cpython-36.pyc,, twisted/test/__pycache__/test_cooperator.cpython-36.pyc,, twisted/test/__pycache__/test_defer.cpython-36.pyc,, twisted/test/__pycache__/test_defgen.cpython-36.pyc,, twisted/test/__pycache__/test_dict.cpython-36.pyc,, twisted/test/__pycache__/test_dirdbm.cpython-36.pyc,, twisted/test/__pycache__/test_error.cpython-36.pyc,, twisted/test/__pycache__/test_factories.cpython-36.pyc,, twisted/test/__pycache__/test_failure.cpython-36.pyc,, twisted/test/__pycache__/test_fdesc.cpython-36.pyc,, twisted/test/__pycache__/test_finger.cpython-36.pyc,, twisted/test/__pycache__/test_formmethod.cpython-36.pyc,, twisted/test/__pycache__/test_ftp.cpython-36.pyc,, twisted/test/__pycache__/test_ftp_options.cpython-36.pyc,, twisted/test/__pycache__/test_htb.cpython-36.pyc,, twisted/test/__pycache__/test_ident.cpython-36.pyc,, twisted/test/__pycache__/test_internet.cpython-36.pyc,, twisted/test/__pycache__/test_iosim.cpython-36.pyc,, twisted/test/__pycache__/test_iutils.cpython-36.pyc,, twisted/test/__pycache__/test_lockfile.cpython-36.pyc,, twisted/test/__pycache__/test_log.cpython-36.pyc,, twisted/test/__pycache__/test_logfile.cpython-36.pyc,, twisted/test/__pycache__/test_loopback.cpython-36.pyc,, twisted/test/__pycache__/test_main.cpython-36.pyc,, twisted/test/__pycache__/test_memcache.cpython-36.pyc,, twisted/test/__pycache__/test_modules.cpython-36.pyc,, twisted/test/__pycache__/test_monkey.cpython-36.pyc,, twisted/test/__pycache__/test_nooldstyle.cpython-36.pyc,, twisted/test/__pycache__/test_paths.cpython-36.pyc,, twisted/test/__pycache__/test_pcp.cpython-36.pyc,, twisted/test/__pycache__/test_persisted.cpython-36.pyc,, twisted/test/__pycache__/test_plugin.cpython-36.pyc,, twisted/test/__pycache__/test_policies.cpython-36.pyc,, twisted/test/__pycache__/test_postfix.cpython-36.pyc,, twisted/test/__pycache__/test_process.cpython-36.pyc,, twisted/test/__pycache__/test_protocols.cpython-36.pyc,, twisted/test/__pycache__/test_randbytes.cpython-36.pyc,, twisted/test/__pycache__/test_rebuild.cpython-36.pyc,, twisted/test/__pycache__/test_reflect.cpython-36.pyc,, twisted/test/__pycache__/test_roots.cpython-36.pyc,, twisted/test/__pycache__/test_shortcut.cpython-36.pyc,, twisted/test/__pycache__/test_sip.cpython-36.pyc,, twisted/test/__pycache__/test_sob.cpython-36.pyc,, twisted/test/__pycache__/test_socks.cpython-36.pyc,, twisted/test/__pycache__/test_ssl.cpython-36.pyc,, twisted/test/__pycache__/test_sslverify.cpython-36.pyc,, twisted/test/__pycache__/test_stateful.cpython-36.pyc,, twisted/test/__pycache__/test_stdio.cpython-36.pyc,, twisted/test/__pycache__/test_strerror.cpython-36.pyc,, twisted/test/__pycache__/test_strports.cpython-36.pyc,, twisted/test/__pycache__/test_task.cpython-36.pyc,, twisted/test/__pycache__/test_tcp.cpython-36.pyc,, twisted/test/__pycache__/test_tcp_internals.cpython-36.pyc,, twisted/test/__pycache__/test_text.cpython-36.pyc,, twisted/test/__pycache__/test_threadable.cpython-36.pyc,, twisted/test/__pycache__/test_threadpool.cpython-36.pyc,, twisted/test/__pycache__/test_threads.cpython-36.pyc,, twisted/test/__pycache__/test_tpfile.cpython-36.pyc,, twisted/test/__pycache__/test_twistd.cpython-36.pyc,, twisted/test/__pycache__/test_twisted.cpython-36.pyc,, twisted/test/__pycache__/test_udp.cpython-36.pyc,, twisted/test/__pycache__/test_unix.cpython-36.pyc,, twisted/test/__pycache__/test_usage.cpython-36.pyc,, twisted/test/__pycache__/testutils.cpython-36.pyc,, twisted/test/cert.pem.no_trailing_newline,sha256=zo_jqLPMFx4ihV8QxkdwD-_wT9WIC-zRDZcH23okXgk,1414 twisted/test/crash_test_dummy.py,sha256=e_KrrGBFmaXSLCLxq59VklPym1tY8UvzcCqZ-6xHzWU,543 twisted/test/iosim.py,sha256=HTAEcEPxQePmaPoMqBKBs4nS_J062aEyyKvOKax44II,17843 twisted/test/key.pem.no_trailing_newline,sha256=6ChUJWC8C3KXcoX1BBidlFOglMqHtYS-ul9cr6UMiHk,1707 twisted/test/mock_win32process.py,sha256=EeeQqdYC2ka1pqW10xDOblWBBuYGuIZc4OSIBRY9Czk,1499 twisted/test/myrebuilder1.py,sha256=IIZN_g1GPNIFVon6tbvPJmIHId7okkkY6P3QWQxKc1E,158 twisted/test/myrebuilder2.py,sha256=jCXJikyxA9P65EeQBypSXO5EPvPJ6tFhSfG2tuleLQI,158 twisted/test/plugin_basic.py,sha256=8xNGvfT0iGqQJoQlXNgV5MZBPh7kckLiCa75WOLPmZY,943 twisted/test/plugin_extra1.py,sha256=OfoMucKmCvgMRHL3YLhwU_Xi2CL4f862-44Au-SHe7c,407 twisted/test/plugin_extra2.py,sha256=EznTfuePvwBnCDi6eeth5bbUe41eS-LjLYmy516ynRU,579 twisted/test/process_cmdline.py,sha256=BimXPJAOrI7p6yeI__pflO_Jalk5y6tlgr-n2zgkaDo,162 twisted/test/process_echoer.py,sha256=USXd05oAkfmRKITVYXjpQ9lFouVEQbyA_a9mudWELpU,214 twisted/test/process_fds.py,sha256=id3GJEGB_uv9AmOPIC-yGvLehIRQDKrTEn5UDq_VSx4,945 twisted/test/process_getargv.py,sha256=WYk6DVL_Zviy160-eNWq263-i4nXAJpezsjpxBbDpUE,283 twisted/test/process_getenv.py,sha256=3micUPcws3OHsrbz6FvudJmAULuL7QxZQaPQL3yBddA,268 twisted/test/process_linger.py,sha256=g151drgjRfbI61dKYG0KYi8F8HxXRE3muWxBuzGVp4Q,286 twisted/test/process_reader.py,sha256=UbbRXJzTl8c6e_lGvFFlGsobtZUxkZovHPTUbfowDjg,188 twisted/test/process_signal.py,sha256=3HFQ8y72n9abUQHG0m_VuHddGePPgmZbjbCkkIbCpVc,214 twisted/test/process_stdinreader.py,sha256=2SQ9WN-X_qZPBc65dUBWEHVl1TtK_vOTKGzfbMwaRa4,857 twisted/test/process_tester.py,sha256=ahvvBnJv2a0z2X4FRXRkiYVrtgaWlotD2OaHHzAgR5I,1035 twisted/test/process_tty.py,sha256=hLLXgrwy_SF-dq2_moeGQSnpRJwyjgVMW7_z9ejXXvQ,130 twisted/test/process_twisted.py,sha256=MwDbDERsvFxRFkkuL48g-VJPVkUqI6GKl4skYpy14hg,1206 twisted/test/proto_helpers.py,sha256=O8Nwlhyg-0o7YmWyGk_0acecBlfbDAYjgXA3IB9CeAs,1009 twisted/test/raiser.cpython-36m-x86_64-linux-gnu.so,sha256=kLerOiQ3s3gyR_0He4TwA10Et2QImqI--T0CLU4r9OU,99619 twisted/test/reflect_helper_IE.py,sha256=D7N7dob70tx6BCuf2mTOVON-9iclUwWtKUTfvsU3F3M,61 twisted/test/reflect_helper_VE.py,sha256=VLu_9ughD3FOfYWMKw6N521vzp6YErR-d5IGnvVINzk,82 twisted/test/reflect_helper_ZDE.py,sha256=6eJjOrxytcz6G1a-NT3rz5fpIyof7ejuk4ZqxkXTAR0,47 twisted/test/server.pem,sha256=bAB7jzd2KxoBpd5VYhzgdmuPDKH9_XV_su2nNq6-xlI,4444 twisted/test/ssl_helpers.py,sha256=ZXyuxzyOz3eoedcTplun835Gru7UI1hj_tsZGGjHH5w,1032 twisted/test/stdio_test_consumer.py,sha256=UcpBNu9jRBjjplwDMFBvISaKV1G-MoZGpmdEN3y-AB0,1216 twisted/test/stdio_test_halfclose.py,sha256=1ULDASakPelEWZTmTEiGP_2yoqADEh_uO3NAtvf9f3w,1938 twisted/test/stdio_test_hostpeer.py,sha256=S4iym1eUrhSTI9q0_NyNFsU2vOt73kM80wQXAZPYiKc,1021 twisted/test/stdio_test_lastwrite.py,sha256=ja24d-ofVHcBwS-zQfZhepBu2DEMY10ESGNOc7NPiG0,1206 twisted/test/stdio_test_loseconn.py,sha256=4MuY6FhUQjVUOxJ-Da_oz87uAESTA2eqpOFjz36PbY8,1548 twisted/test/stdio_test_producer.py,sha256=OChDgtN-lKe4wv5afQiUngvvzJN-5ovdkNwDfsSooEQ,1507 twisted/test/stdio_test_write.py,sha256=ZzHl8uDvAuN987XKwHeU7huFJeUhkH2m7llj0_lb1TM,923 twisted/test/stdio_test_writeseq.py,sha256=KjDrpNrGdy6Ao66bUHuRlxk4r1hUxbf9z-q_YQPrrJQ,915 twisted/test/test_abstract.py,sha256=u1sJ3MqObQNQirOIL9KBdEK5GmHY-hfoX9MaaNbG7JQ,3497 twisted/test/test_adbapi.py,sha256=YZY7rTrIeImJlW852LbG19mMR_gPHq0gJyOCqBhh618,26148 twisted/test/test_amp.py,sha256=YsKFvd1aaugyD_lBDG0w6IPnDCKDjtcNPFO7YNmNBck,110553 twisted/test/test_application.py,sha256=vjgnjo4Q-IQ8NPZT8DH_hgyT2m0nrniw4nLEMpe4DOI,34210 twisted/test/test_compat.py,sha256=GKXSsM1F11qkVT0pPM6CPfVc1fugOMCUSB9EuBG0PJk,28527 twisted/test/test_context.py,sha256=zsV4fhj0VCrTLbzhjOdcr2gxG3kAOYCOwRjUvIs1ap4,1515 twisted/test/test_cooperator.py,sha256=vW_NFZ5arXXHquIBUeBwqUqb8cpLUP6ftFoDi6G-EXQ,21467 twisted/test/test_defer.py,sha256=3mNCERZAqGEP63g3dlCzJ4RGc-A2bD48zRaIM6_uyi8,104143 twisted/test/test_defer.py.3only,sha256=VUYRAxF1fFS6HBFPEmgQJF5cbF0T7hXMyuZI6ZOXqLM,2500 twisted/test/test_defgen.py,sha256=FcjjeYL5N9BbAnSf0rgTD36dN-zKTq2SR3pTKfBlBr0,10701 twisted/test/test_dict.py,sha256=GCmGM7c6XlVwIsQpkPJxeAW_Nyjy_kR2C6TsqXVruCU,1442 twisted/test/test_dirdbm.py,sha256=cPN4kXEgtG20KChbnVDwGfrRUCEiuvp8fSxY8UfBTM4,6695 twisted/test/test_error.py,sha256=3qPMbLZfUo_qvJx3E0m6mbXx-DYE_uP9mhkapMDix8g,8593 twisted/test/test_factories.py,sha256=i_dbiMVIhvx7f47BQK9I_Y8vdloV-9k33-0h2iX3uQ8,4637 twisted/test/test_failure.py,sha256=5G91yYuoSJ4-pwQlPTQIF3yMowcr7XFKFmSGA1vN09Q,32814 twisted/test/test_fdesc.py,sha256=DDqHNCrc5Q_gnDLyqGKI_ReNFjR1Qv79GQLjaWysIO0,7371 twisted/test/test_finger.py,sha256=lE5o_NacakzRCt5yYkCh-z_SktcXwK4FXhI5GXg9E0s,1997 twisted/test/test_formmethod.py,sha256=9aSzdUJSAzdrUhYGe-cf7nvDPU1L3JZCDIpYlSlrjjA,3645 twisted/test/test_ftp.py,sha256=Dmre2zNP4odYzKmK6KPzutLsv3T8zVS40eKmBkXvA80,130321 twisted/test/test_ftp_options.py,sha256=eGD8-ot2TGhcMTeP79EGhpmo-HfxmH3by_KzopdHNDw,2685 twisted/test/test_htb.py,sha256=nT0xU1fTt5TawiOd53Q7mQOkbSybNXa5Hdud74KO-bs,3190 twisted/test/test_ident.py,sha256=27hHDLdWQjZj_3511PpJ9jk-GKK8gRUOtmCzRLNMspw,7015 twisted/test/test_internet.py,sha256=WBPCf4NPaNWtDB9fIJ6Efwlel8QIn5DDC4BeBc2k3D0,46803 twisted/test/test_iosim.py,sha256=ZaDyIAoVKKjmmpZCugfrT6sKp0lVcgIrfGxqjvpqHL8,9060 twisted/test/test_iutils.py,sha256=Kv3t0iIi9u9fgzluaU2SVxVPGCQbcp3gwQfpkai0Spk,14384 twisted/test/test_lockfile.py,sha256=PsCJl1pA0K-aA-SIwW_i7VyN-43xTfxtmcmkPqDNQ3k,15506 twisted/test/test_log.py,sha256=0rlzX1ua_ZSqfDNsHc2tih12QZxsodgG4Ht4ELNpLzQ,36330 twisted/test/test_logfile.py,sha256=MPFH14kANpfxPbokwn9sZU4bK984kR6D1anoFJy_r58,18227 twisted/test/test_loopback.py,sha256=PTSDXS5TFz6L1GEkdXLWBHRrp3CJ0ds2WDodMrLWtLE,14486 twisted/test/test_main.py,sha256=F3x8NqO0CxZvfnmm6H2-x5Z4UsLH0htWUe0nwO_v4Qk,2501 twisted/test/test_memcache.py,sha256=lTdDfwGIOUIYv3nWC4TOpuY2oZ8D3--d6Z78a-5Spb4,25143 twisted/test/test_modules.py,sha256=VWkroMXc5duBPTOTtJnHgJDFSHUBmK2TfaJwvfa7w88,17888 twisted/test/test_monkey.py,sha256=D37NHborDX663mPE3vnYQP2OA8Ey37YDpuHCuXu4Gu4,5637 twisted/test/test_nooldstyle.py,sha256=hwfH8G2l4KJrHqUCmH__iUjhoFW34aGVy_WOE2iXi5g,5955 twisted/test/test_paths.py,sha256=j_0l5igUqehcYqvFfBG9KU0ZZlQKnho36ysoBNHxv64,74357 twisted/test/test_pcp.py,sha256=k13lppisnl5WYCS5BD-kAbyUzM1CZBLxbQ0rG_S3a-M,12551 twisted/test/test_persisted.py,sha256=KHfsZlx2feaihD0Ja5KBq_-h56CQ2ilxWDQ32xq-JnA,14624 twisted/test/test_plugin.py,sha256=r20OZv-hMr9DjMyk9tJxDykMV_g1seLgyDfp3eVz6Ww,26113 twisted/test/test_policies.py,sha256=KtUlbJZRqmqOpQT4E20PHb3V_6gvBa45DzkFZEr3Hck,33499 twisted/test/test_postfix.py,sha256=CrDVuSkr18QQDVhJ5lCCy07Fy6RQjOaMffUKmno0nZM,4243 twisted/test/test_process.py,sha256=Y5ntI0AwGXEsxuiViOB8bdVIyyFLUO3Efw3O9fs4vJk,86120 twisted/test/test_protocols.py,sha256=ZIk1-7OhE-04Oytmr9-ScYWBi_PrsBDh-aUFiiUYqgY,7450 twisted/test/test_randbytes.py,sha256=MkUMH7zYTdJ4Ln8J9VJDLueHFcZ4HR1Qz2aNPVFHKnw,3357 twisted/test/test_rebuild.py,sha256=iscBE4IMkfOmEGkHlyjCZC8ioXjnwNi5kQwmf19eduk,8495 twisted/test/test_reflect.py,sha256=riIAjcwwIq4ZeM4rGZIaxuDFLkrKtqr315-xM-j7ANw,26085 twisted/test/test_roots.py,sha256=4TzR1qugGrfLdjwO34KO0SAweOxOMHqkJtMwkWtbmm4,1812 twisted/test/test_shortcut.py,sha256=NkA5ho-Rvhhu9Dj_JD5N6VZS4lzNWHInPe2J4Clv-L4,1991 twisted/test/test_sip.py,sha256=wFVIuH_XqHAGlenbvtswDjBFZpo3E4RnIRAxEel_AEI,25284 twisted/test/test_sob.py,sha256=ttrn_p7OpR2ikvTm8oNxgxrxnQ4xMdT7YdIc02egl58,5632 twisted/test/test_socks.py,sha256=ImzFJie1KZesqrTM1LyhhCSD_WLXB-_eRrWWpAzw31c,17738 twisted/test/test_ssl.py,sha256=kqOXu-IGJKW4HuCSdTs4U2rORO-P4SrGBby5stQfmOE,22923 twisted/test/test_sslverify.py,sha256=iAjE3Zo6FKDhCaRE_PiyIFwVOGbAJ58ZAQcvsSisAJY,116121 twisted/test/test_stateful.py,sha256=-X78ROUUyb5c6-jzJ4DIi_NYf0t8xmLegEOSqrQSxnE,2021 twisted/test/test_stdio.py,sha256=M7agWsEf2cC2tpHrtqXEVn9jQXIqYYzYEW2eQ5RoB5U,13156 twisted/test/test_strerror.py,sha256=4lT14E-7oGKDHpsAoJ4Es6WDPa9h6fK3FS92B51w3s8,5183 twisted/test/test_strports.py,sha256=oM-EGX3x5WWQIMTXYWUy7fgscvVuhoaoKdxCqHTgSLE,1797 twisted/test/test_task.py,sha256=-7MgKjHCcIclp6DmwOegRo-C5Ury2lF4i3W5xBJRbLA,39683 twisted/test/test_tcp.py,sha256=ywEI3OaF7iJfY4l7eA6ZYBuem-TIegIiF1yEg8Bpuak,66192 twisted/test/test_tcp_internals.py,sha256=DCBr5-a2W12EvX9gWBlf8vIGc8YEizQ1Uodcdu5tfqk,13255 twisted/test/test_text.py,sha256=ZDBTmtLnIGkYwL08uX0MJ4Xq-B1oPgt8rAzO1_FT62o,6456 twisted/test/test_threadable.py,sha256=85oUaY3J3Cg7Y-uvm6Wk4f5cQ-RhYi5SCLIbS8fb7ZQ,3738 twisted/test/test_threadpool.py,sha256=1qoaUY1zYLmeW4M0ZRRNfvzH0CUwAkdPjQ-5L_Q0lEk,22204 twisted/test/test_threads.py,sha256=bLzBn98GjVgBCylKpps1oLFwpJKaGV9Q_79_6jDT_uc,13268 twisted/test/test_tpfile.py,sha256=f3apHS3fbcoNspvqJ4d3Tljtv44lHU3FcWgJIoyy4Gk,1601 twisted/test/test_twistd.py,sha256=BYTWg5qB6NVwGjIkM6qWUd54U6pj308SVQPfAA1Pw_Y,74201 twisted/test/test_twisted.py,sha256=JFiWXtkK0Si6NLrh1i3iLLplxie2_zZNb6DHB-tmAjo,9214 twisted/test/test_udp.py,sha256=K6uHGFmp7pLUpIjmfjNNFtyiFQmNHyO6XVVO783b3zU,24992 twisted/test/test_unix.py,sha256=sxRkpz0NzS98bXy1ZlfN_p3J2GRk2BbLg8aGGLv5vnM,15157 twisted/test/test_usage.py,sha256=E3vSRYqzzUbjWg3CZW4bFYAK8eoAtiuUGdb9jJH9JeY,23645 twisted/test/testutils.py,sha256=VWozf8WzYsiwRA8LCR7jIaLyi9x0dE2HOHJaJQTmtwc,5321 twisted/trial/__init__.py,sha256=2ib2sy-amXD8irsLolFFjjeNur8BnaXwBWaOCASmsFU,2040 twisted/trial/__main__.py,sha256=noqg0SgiYqvgjWVTPJCyrxZDdpR-l1p666wuE4a5388,249 twisted/trial/__pycache__/__init__.cpython-36.pyc,, twisted/trial/__pycache__/__main__.cpython-36.pyc,, twisted/trial/__pycache__/_asyncrunner.cpython-36.pyc,, twisted/trial/__pycache__/_asynctest.cpython-36.pyc,, twisted/trial/__pycache__/_synctest.cpython-36.pyc,, twisted/trial/__pycache__/itrial.cpython-36.pyc,, twisted/trial/__pycache__/reporter.cpython-36.pyc,, twisted/trial/__pycache__/runner.cpython-36.pyc,, twisted/trial/__pycache__/unittest.cpython-36.pyc,, twisted/trial/__pycache__/util.cpython-36.pyc,, twisted/trial/_asyncrunner.py,sha256=oNL10LsWsYgfPDZhAzO9Hes-yKZa17M6PF-JyAFamuw,4530 twisted/trial/_asynctest.py,sha256=qUGroPSQz4SPywueE4vxXnk8JtkbwopGFqA6D1J9-UA,14634 twisted/trial/_dist/__init__.py,sha256=0v2hhp_DnNSlYu4-6rS6SzWwFTqcl_1DCqPrWxKdEXc,1941 twisted/trial/_dist/__pycache__/__init__.cpython-36.pyc,, twisted/trial/_dist/__pycache__/distreporter.cpython-36.pyc,, twisted/trial/_dist/__pycache__/disttrial.cpython-36.pyc,, twisted/trial/_dist/__pycache__/managercommands.cpython-36.pyc,, twisted/trial/_dist/__pycache__/options.cpython-36.pyc,, twisted/trial/_dist/__pycache__/worker.cpython-36.pyc,, twisted/trial/_dist/__pycache__/workercommands.cpython-36.pyc,, twisted/trial/_dist/__pycache__/workerreporter.cpython-36.pyc,, twisted/trial/_dist/__pycache__/workertrial.cpython-36.pyc,, twisted/trial/_dist/distreporter.py,sha256=4oiCkv6AZOIfBfZt8qDKyKSERZtx5S7r9AA170DAeYU,2495 twisted/trial/_dist/disttrial.py,sha256=T-QHOl0r5MztVjVBbfCyGtERQQs1ixeLqkYjOvtSXEM,8711 twisted/trial/_dist/managercommands.py,sha256=FDoWQMJXMu1UIzYseCtS4t2A7yKyZFfEM_Zc3U9qs7E,1897 twisted/trial/_dist/options.py,sha256=7GLbC2y5zGM3IwimCBg7H26AOlwiPb2dkoebWQFezzE,739 twisted/trial/_dist/test/__init__.py,sha256=IOS3XedcenVmIEF2Dn-7IhLiGyeN1IG33V51Pk_iS7o,118 twisted/trial/_dist/test/__pycache__/__init__.cpython-36.pyc,, twisted/trial/_dist/test/__pycache__/test_distreporter.cpython-36.pyc,, twisted/trial/_dist/test/__pycache__/test_disttrial.cpython-36.pyc,, twisted/trial/_dist/test/__pycache__/test_options.cpython-36.pyc,, twisted/trial/_dist/test/__pycache__/test_worker.cpython-36.pyc,, twisted/trial/_dist/test/__pycache__/test_workerreporter.cpython-36.pyc,, twisted/trial/_dist/test/__pycache__/test_workertrial.cpython-36.pyc,, twisted/trial/_dist/test/test_distreporter.py,sha256=wrXX0UllZZRgCAArA8gdKHipm9JLi0cFMzdgk_pn2DU,2051 twisted/trial/_dist/test/test_disttrial.py,sha256=aJ7-xg5Ew1uwyoFq5F0T_YMK5u-JfZfbdAdYGJE3a9M,16757 twisted/trial/_dist/test/test_options.py,sha256=8cMl8nKBeXvnfuRDwL6oTluwnbtJ3GR9HZl45YEiAyA,1312 twisted/trial/_dist/test/test_worker.py,sha256=Lu4I8xl0i3kgyrpBTinEAgxrpDBX43vRF9otsDrZH4c,14784 twisted/trial/_dist/test/test_workerreporter.py,sha256=lNGGrJoiWsu58wVMAY9lF6twFISQgMyoRh60HT9ww80,5390 twisted/trial/_dist/test/test_workertrial.py,sha256=StZMQYWknt0nVg2F4KaJ9ZPUNFX-JVh0-5uF6d1kHB0,5014 twisted/trial/_dist/worker.py,sha256=uuzghTilXOwfiNHjKkgYUppJNkqzo4_VBEqwKNIXkR8,9153 twisted/trial/_dist/workercommands.py,sha256=GerNCLGPNP8asXy22Cl8qAKQYJ9sKiXDo729Lc1AbbE,641 twisted/trial/_dist/workerreporter.py,sha256=ysGwtY-e6c_sSTR3IGhy7f8kqgqOQI46EnJysD2LJxk,4856 twisted/trial/_dist/workertrial.py,sha256=BQDJ2KHnHQ6MtPwOq_pU428h2zvT7k-JYVnsc1Z62VY,2859 twisted/trial/_synctest.py,sha256=HgxTQKu4jMXjUjJyC48yNX7LVw4f8nEynMi3VyDdGtk,50017 twisted/trial/itrial.py,sha256=EmbbuIA4WItHcgQKEOGhfORSTxTuWX-DrRezBrcbj9k,6857 twisted/trial/reporter.py,sha256=peShSfUXXNGxHTQyxY-1WXuTEAaEhaWrUqRDh0YaPxI,40105 twisted/trial/runner.py,sha256=mzT5AVFYlBL97jCK8CjJLZjKor9zysNV-yff7bLX7OQ,36720 twisted/trial/test/__init__.py,sha256=uWFvjebi50_v57TkFDrFhvUS5oUq8Jo5y_vRBvpP9o4,130 twisted/trial/test/__pycache__/__init__.cpython-36.pyc,, twisted/trial/test/__pycache__/detests.cpython-36.pyc,, twisted/trial/test/__pycache__/erroneous.cpython-36.pyc,, twisted/trial/test/__pycache__/mockcustomsuite.cpython-36.pyc,, twisted/trial/test/__pycache__/mockcustomsuite2.cpython-36.pyc,, twisted/trial/test/__pycache__/mockcustomsuite3.cpython-36.pyc,, twisted/trial/test/__pycache__/mockdoctest.cpython-36.pyc,, twisted/trial/test/__pycache__/moduleself.cpython-36.pyc,, twisted/trial/test/__pycache__/moduletest.cpython-36.pyc,, twisted/trial/test/__pycache__/novars.cpython-36.pyc,, twisted/trial/test/__pycache__/ordertests.cpython-36.pyc,, twisted/trial/test/__pycache__/packages.cpython-36.pyc,, twisted/trial/test/__pycache__/sample.cpython-36.pyc,, twisted/trial/test/__pycache__/scripttest.cpython-36.pyc,, twisted/trial/test/__pycache__/skipping.cpython-36.pyc,, twisted/trial/test/__pycache__/suppression.cpython-36.pyc,, twisted/trial/test/__pycache__/test_assertions.cpython-36.pyc,, twisted/trial/test/__pycache__/test_asyncassertions.cpython-36.pyc,, twisted/trial/test/__pycache__/test_deferred.cpython-36.pyc,, twisted/trial/test/__pycache__/test_doctest.cpython-36.pyc,, twisted/trial/test/__pycache__/test_keyboard.cpython-36.pyc,, twisted/trial/test/__pycache__/test_loader.cpython-36.pyc,, twisted/trial/test/__pycache__/test_log.cpython-36.pyc,, twisted/trial/test/__pycache__/test_output.cpython-36.pyc,, twisted/trial/test/__pycache__/test_plugins.cpython-36.pyc,, twisted/trial/test/__pycache__/test_pyunitcompat.cpython-36.pyc,, twisted/trial/test/__pycache__/test_reporter.cpython-36.pyc,, twisted/trial/test/__pycache__/test_runner.cpython-36.pyc,, twisted/trial/test/__pycache__/test_script.cpython-36.pyc,, twisted/trial/test/__pycache__/test_suppression.cpython-36.pyc,, twisted/trial/test/__pycache__/test_testcase.cpython-36.pyc,, twisted/trial/test/__pycache__/test_tests.cpython-36.pyc,, twisted/trial/test/__pycache__/test_util.cpython-36.pyc,, twisted/trial/test/__pycache__/test_warning.cpython-36.pyc,, twisted/trial/test/__pycache__/weird.cpython-36.pyc,, twisted/trial/test/detests.py,sha256=7uYBWdLD-Slpq6cXrgtdJyalwCvAZzhJGL0KX2jhbUA,5368 twisted/trial/test/erroneous.py,sha256=fM-kSxh_M7QfB0Oc9bIIQDX-r_29ZdJIrabqUqjxZhc,4829 twisted/trial/test/mockcustomsuite.py,sha256=pNEnsIgTTx-fp2hYS4GxkAenBER6uPot11VbkDzqQgM,535 twisted/trial/test/mockcustomsuite2.py,sha256=GPSbV-Ou5XCACyVF_DgD2SXDH3Ekvzab9rQiC0roUuQ,532 twisted/trial/test/mockcustomsuite3.py,sha256=zc_roFFRqTPwVGto3VL7_Ic15nGm4WvCEG-w5rHiYlw,675 twisted/trial/test/mockdoctest.py,sha256=f89ND666XnQnUuvIyR4begtzQWM_mBxzRWs5F9AeWvE,2645 twisted/trial/test/moduleself.py,sha256=UWx4cOBRU6OlGdjfjgEgNQPpfbp-biul5WCAtI30GD4,170 twisted/trial/test/moduletest.py,sha256=Yx-H7C4qwBgzKFkp1B_JYyq2D8CCiSEpE9qS2jwfD7A,310 twisted/trial/test/novars.py,sha256=asKIwzyfBjiDqHi8zeTzcHHdLYGBk1JQf1QvbZl25zc,189 twisted/trial/test/ordertests.py,sha256=ZZm2zhvHrEtN7hVXH49vVTOB7dEsXfuargd_8M1d0wM,867 twisted/trial/test/packages.py,sha256=lnN006Agb_-kEkNrKGus38S-ePaIl4JT8azwJFhTGRg,4927 twisted/trial/test/sample.py,sha256=nWBJwh0ZAu3tpLhV8N5RoNUI7HUQQWrkLIbVHrDDGbk,2155 twisted/trial/test/scripttest.py,sha256=1wey0lWic-hQv_NZ4YR6BS-GHFqcJaxf8CHGitkdosY,466 twisted/trial/test/skipping.py,sha256=y1Pkj2IMNGfVdrtwBEkPzRWh_zBia3srnkHySEbszPg,5356 twisted/trial/test/suppression.py,sha256=rHQuaV53Au_YXyYw0zZC4UToHp-o5_uQUB_vbmiS9GI,2497 twisted/trial/test/test_assertions.py,sha256=rIbGSAeiouJh_20HJZUib8D4u-wHN8rIVnUXIyFZYvI,46630 twisted/trial/test/test_asyncassertions.py,sha256=f-OE4xvhJ9jZmVUd74azvoUKgYcUW-BLHwRbYjIcCB8,2571 twisted/trial/test/test_deferred.py,sha256=d-iLD-GqYvAq2IvFUhmr8eVtOwGeP4X9bFg_BoqMAeY,8889 twisted/trial/test/test_doctest.py,sha256=p5fpDtW76E461ltTr5vrrz0V3Gas5nGz7lUypOvi90U,1766 twisted/trial/test/test_keyboard.py,sha256=Zc3E7yyNElQ9bI2E8wlsRj_1V5jOXFv_ylTi3FW9db8,4036 twisted/trial/test/test_loader.py,sha256=b6r0-_40GUTMZ2svo58Q_NBMXkxY3HmE5ffBb2mp4n8,26783 twisted/trial/test/test_log.py,sha256=4KbBgmQwI7IjFnZ8W8ZNdtb5RcSLoPGov7QL2Znxjmw,7969 twisted/trial/test/test_output.py,sha256=zQ94RkuSX1FOLTxlt7VqSAueSWmvpsYrGIHeTDINo8M,5299 twisted/trial/test/test_plugins.py,sha256=9KUuBPPm05bO1a7RxQP6fMRDr23S7_FKf81ssYL3GHo,1451 twisted/trial/test/test_pyunitcompat.py,sha256=HkGUKXAp9hfYOqjPY_DVWBvxpTVm-QC2qPAZXJHfUII,7670 twisted/trial/test/test_reporter.py,sha256=3vFYKFQSF5g_Gf21MN99PNiUAUdE9Xwq5-Wxp86Lpzw,57428 twisted/trial/test/test_runner.py,sha256=pRK1B-bIjTn9pCu2gSte_IVP_3i0OMitwasxQYBuptQ,34074 twisted/trial/test/test_script.py,sha256=YaO9q-4fH_9T6yhSTeEm0ciGv5ivM1DBdAlIDWa9U3I,29717 twisted/trial/test/test_suppression.py,sha256=vw8R3i_EaZgtdcGNxrzSbVI7gvLVm2baHh348g_yVvc,6089 twisted/trial/test/test_testcase.py,sha256=f2xpFykUxZoW8T5HzSiw7dc0pqOAh5ZswK4u1eC9ZOw,2043 twisted/trial/test/test_tests.py,sha256=koXRAKkmWDMXElmy87uPQCuIspyeYr4VeO4dbf1XPpc,50030 twisted/trial/test/test_util.py,sha256=faNL8ZBaOR83bcNQV7x7pNtXUofSSvj8h9gbq1m6o0s,24709 twisted/trial/test/test_warning.py,sha256=aZZSrMvdCvAf_EALAvTSBpQozfSpef_5GyelC7qpCgk,16770 twisted/trial/test/weird.py,sha256=apD_gjh7qeK_gEi9r3WErMHYvPuf0PIk_BoJZNAbvCA,721 twisted/trial/unittest.py,sha256=JQAudPGd--a9KNzsaGRCnzbQ2H_JzMSQFC-nMVJ4Xng,978 twisted/trial/util.py,sha256=FjW69s1ttgn3MHUXkv7HmhK2JXzceiE0BgTiAQnNgHw,13410 twisted/web/__init__.py,sha256=XDcQGn3KmRxndOIDTJZcSWGhxPALqHLMxbzsRhqsra4,384 twisted/web/__pycache__/__init__.cpython-36.pyc,, twisted/web/__pycache__/_element.cpython-36.pyc,, twisted/web/__pycache__/_flatten.cpython-36.pyc,, twisted/web/__pycache__/_http2.cpython-36.pyc,, twisted/web/__pycache__/_newclient.cpython-36.pyc,, twisted/web/__pycache__/_responses.cpython-36.pyc,, twisted/web/__pycache__/_stan.cpython-36.pyc,, twisted/web/__pycache__/client.cpython-36.pyc,, twisted/web/__pycache__/demo.cpython-36.pyc,, twisted/web/__pycache__/distrib.cpython-36.pyc,, twisted/web/__pycache__/domhelpers.cpython-36.pyc,, twisted/web/__pycache__/error.cpython-36.pyc,, twisted/web/__pycache__/guard.cpython-36.pyc,, twisted/web/__pycache__/html.cpython-36.pyc,, twisted/web/__pycache__/http.cpython-36.pyc,, twisted/web/__pycache__/http_headers.cpython-36.pyc,, twisted/web/__pycache__/iweb.cpython-36.pyc,, twisted/web/__pycache__/microdom.cpython-36.pyc,, twisted/web/__pycache__/proxy.cpython-36.pyc,, twisted/web/__pycache__/resource.cpython-36.pyc,, twisted/web/__pycache__/rewrite.cpython-36.pyc,, twisted/web/__pycache__/script.cpython-36.pyc,, twisted/web/__pycache__/server.cpython-36.pyc,, twisted/web/__pycache__/static.cpython-36.pyc,, twisted/web/__pycache__/sux.cpython-36.pyc,, twisted/web/__pycache__/tap.cpython-36.pyc,, twisted/web/__pycache__/template.cpython-36.pyc,, twisted/web/__pycache__/twcgi.cpython-36.pyc,, twisted/web/__pycache__/util.cpython-36.pyc,, twisted/web/__pycache__/vhost.cpython-36.pyc,, twisted/web/__pycache__/wsgi.cpython-36.pyc,, twisted/web/__pycache__/xmlrpc.cpython-36.pyc,, twisted/web/_auth/__init__.py,sha256=GD_euhqqSJj1fv_srRt5Yl5RfcExpzifR-PYLNTKIwI,190 twisted/web/_auth/__pycache__/__init__.cpython-36.pyc,, twisted/web/_auth/__pycache__/basic.cpython-36.pyc,, twisted/web/_auth/__pycache__/digest.cpython-36.pyc,, twisted/web/_auth/__pycache__/wrapper.cpython-36.pyc,, twisted/web/_auth/basic.py,sha256=S3KTEXHVdz8EFnrR3Un3kulhOO_kOUitt0D1cleHIzg,1689 twisted/web/_auth/digest.py,sha256=Cr3akmx_l73w-yZxUqB3CcF1DFNc9R41Ibpw63MIfHc,1770 twisted/web/_auth/wrapper.py,sha256=QjwuVhM9rwMcxiV1oF8u9YmH7YEy3EPC4BfzGsQy4U8,8566 twisted/web/_element.py,sha256=7vBEF4yTwCUsmeAsBCjSwYbutvNrLS4Bp-9PA0ae7mU,5947 twisted/web/_flatten.py,sha256=obSfnAN4wJ0n3DK_e1fxlj5qiVc_CwLkyMFKAI0QzdI,15912 twisted/web/_http2.py,sha256=mlomwH5LyFPIl3wZ1GE60BtIAx1mls-x54wagPni5AA,45545 twisted/web/_newclient.py,sha256=bsD00poQNKPGLeFY0pXkxZ1yaDV20Xe9sH5oc0x-KAg,63973 twisted/web/_responses.py,sha256=IuFI3g88Klz01-6AGus3FDu4ifFiSZcGpH_7xQFKv8U,3655 twisted/web/_stan.py,sha256=hr8FW8_qo-wFShnq3iGUmALNVew2k0is5YbRnuXliJ4,10790 twisted/web/client.py,sha256=wf2N3Rzn4lZ_lLc-DPc-euuiI0O7l35e1QxO2eeJLOg,76971 twisted/web/demo.py,sha256=g3JC8qhso0-sYmmRVjT_di_F2_-J09kdsM9Z5kH7u3g,554 twisted/web/distrib.py,sha256=ky8W3tDRSsVXmarhx3z7Ys9oKmho0UtNIKd0gv72LVE,11881 twisted/web/domhelpers.py,sha256=JJor6qQbzybg-D9rVX-9Q3vTvJZUDNbzp9HyaACvPc0,8645 twisted/web/error.py,sha256=z_QFN-l4gy370GEWXuue3MIliddbNa1VXroIRcfsfHA,12537 twisted/web/guard.py,sha256=2vGjNL9ZxbPxHZWuqXwJ1UFXGHfFgAxdD7kQ90I0OqU,630 twisted/web/html.py,sha256=7uKIiee9Sg6vKlV5juUTHoTSwLPVa6jXLSKTOkg6SKs,1557 twisted/web/http.py,sha256=xTllJJrr8PWDEmyvpkBNSVqsdrZo_ovErRz4fG8tEAc,104055 twisted/web/http_headers.py,sha256=L9yz-tM4HUP_xDU7fqvnNIuiEzj6yYRp6O766HDsYLA,8853 twisted/web/iweb.py,sha256=KYQqCnUp6ebvwa5BNCogYjKpdrY2p7_flVDbCa8A9rE,26778 twisted/web/microdom.py,sha256=a-LdI_UIIXFLMfFdHDVKYnAM8vTEfKhSkPAqeK_PC34,36197 twisted/web/proxy.py,sha256=u_LqSCDNuFKjs_K85LNzimWcsxrvtRuMe5ZHs3QO6lU,9837 twisted/web/resource.py,sha256=kpKqmCAWKXwNvokIGYM2pCCWM4AevSOgklRX20Oy3-8,13610 twisted/web/rewrite.py,sha256=ezcoNJcAy-ET1WmS2UF3JzTNhhNR1bGoyDK0dl_q9Fg,1852 twisted/web/script.py,sha256=pIQ-kiryhNxUjZlJUQyd2knXWjdzO_VZFm8-weXDIh0,5745 twisted/web/server.py,sha256=eDdTtMBs2fANGFR0oL5UWJLLrdRdClpIdAUJ0kbw0ic,28329 twisted/web/static.py,sha256=3iCMORPZXIwcujH1D4lwU7R-vISY-2RbBqUiC11vNHc,38007 twisted/web/sux.py,sha256=ue2_D9mzOOOPpPvJNTL-31jWbnAgsG-EimiuAIJQx2Q,20892 twisted/web/tap.py,sha256=nMnaXPp8dEHhOLDj_L6ogXyulXR387_-3hMVucoX5Vg,10331 twisted/web/template.py,sha256=IZMkl-eBtxot8sFb96C2xHBXMcHwwgvjE8egjy30pKo,17631 twisted/web/test/__init__.py,sha256=fUhYepItGqSYT0CsZLxIbU9lDRjUkJ0pGsdsr8GRp0c,108 twisted/web/test/__pycache__/__init__.cpython-36.pyc,, twisted/web/test/__pycache__/_util.cpython-36.pyc,, twisted/web/test/__pycache__/injectionhelpers.cpython-36.pyc,, twisted/web/test/__pycache__/requesthelper.cpython-36.pyc,, twisted/web/test/__pycache__/test_agent.cpython-36.pyc,, twisted/web/test/__pycache__/test_cgi.cpython-36.pyc,, twisted/web/test/__pycache__/test_client.cpython-36.pyc,, twisted/web/test/__pycache__/test_distrib.cpython-36.pyc,, twisted/web/test/__pycache__/test_domhelpers.cpython-36.pyc,, twisted/web/test/__pycache__/test_error.cpython-36.pyc,, twisted/web/test/__pycache__/test_flatten.cpython-36.pyc,, twisted/web/test/__pycache__/test_html.cpython-36.pyc,, twisted/web/test/__pycache__/test_http.cpython-36.pyc,, twisted/web/test/__pycache__/test_http2.cpython-36.pyc,, twisted/web/test/__pycache__/test_http_headers.cpython-36.pyc,, twisted/web/test/__pycache__/test_httpauth.cpython-36.pyc,, twisted/web/test/__pycache__/test_newclient.cpython-36.pyc,, twisted/web/test/__pycache__/test_proxy.cpython-36.pyc,, twisted/web/test/__pycache__/test_resource.cpython-36.pyc,, twisted/web/test/__pycache__/test_script.cpython-36.pyc,, twisted/web/test/__pycache__/test_stan.cpython-36.pyc,, twisted/web/test/__pycache__/test_static.cpython-36.pyc,, twisted/web/test/__pycache__/test_tap.cpython-36.pyc,, twisted/web/test/__pycache__/test_template.cpython-36.pyc,, twisted/web/test/__pycache__/test_util.cpython-36.pyc,, twisted/web/test/__pycache__/test_vhost.cpython-36.pyc,, twisted/web/test/__pycache__/test_web.cpython-36.pyc,, twisted/web/test/__pycache__/test_web__responses.cpython-36.pyc,, twisted/web/test/__pycache__/test_webclient.cpython-36.pyc,, twisted/web/test/__pycache__/test_wsgi.cpython-36.pyc,, twisted/web/test/__pycache__/test_xml.cpython-36.pyc,, twisted/web/test/__pycache__/test_xmlrpc.cpython-36.pyc,, twisted/web/test/_util.py,sha256=6pb3RDrdZoJ1DaELSW8PdaXUywANty8JN8j8AUwOKAM,2568 twisted/web/test/injectionhelpers.py,sha256=V2QQTamzKkOjypM7qdt2Y2iVHzQi4c83mZTesOt2_JU,5627 twisted/web/test/requesthelper.py,sha256=oP_zp0MkntT7TKvJPMIg6_7LlyQiuQ0-izoHRiYNIB0,13702 twisted/web/test/test_agent.py,sha256=ghnRnHIpSsrvi7ilIqdFU4a1MENBBzJ-PItrw6IAVQY,116623 twisted/web/test/test_cgi.py,sha256=fPZPDFG8JAOUJD2pXr7H_FOenrzy-RLdLW3FOTmM4L8,13761 twisted/web/test/test_client.py,sha256=rnMgKFRmeVFgtKTjnyAhJL2LvOI8P6WIjXJa--Juv5M,1372 twisted/web/test/test_distrib.py,sha256=SAHzSQyQa3IoYGi1dc0csEvSl69hSnBzRZGzKbfSIoI,18288 twisted/web/test/test_domhelpers.py,sha256=ir_GSEC4Y5eJUIP4mKi9GzFUdwLXvuDuBEHiUmSC2go,11103 twisted/web/test/test_error.py,sha256=a-KtTSqsH05SlDijTSPA50C7m-dgPhZH3Avc9uKs3uE,16210 twisted/web/test/test_flatten.py,sha256=TJTlohdbkYUC6OLIprKuYQrHoUh2aY86kVgzIQyp9Nk,18259 twisted/web/test/test_html.py,sha256=BBbAgc2B9f8-PmYvcyGDbhjKDUpBQTiuikNgaNpKaGo,1264 twisted/web/test/test_http.py,sha256=4IrPhkpFTHNSXbjQu9cjrOi6c-3X4LFGz6DYXIMah6k,131929 twisted/web/test/test_http2.py,sha256=LLlY0PSmFovpGoGe05bfTFrM8UetVZIhGrwCX4V_RUc,99939 twisted/web/test/test_http_headers.py,sha256=c3uv_Zbs5hDJQ64eGEErzs4iCVSnDdDCTp8sY3hbs0g,22177 twisted/web/test/test_httpauth.py,sha256=VyOB2BQqn2SEjXUsSUUc9OLHFgesUwjCvQD0U87XMSg,24128 twisted/web/test/test_newclient.py,sha256=rq4_W0WxH4NhCozadpy3gudGsD4zZTUDkdib1MMUSCY,110593 twisted/web/test/test_proxy.py,sha256=DW2jc_1elz_bPp4eU7qLK5peNTc_WM39p1TDnIMBaC8,20346 twisted/web/test/test_resource.py,sha256=EgBRDWfHTO01PNJgDbbAnUv9Pp_C5NmC2ZUOHiL-buI,9243 twisted/web/test/test_script.py,sha256=rQilL-H4VzO-NGU6_2Dv9h32VA3j4pZSPtwMW30e86E,3784 twisted/web/test/test_stan.py,sha256=5IqsRlFv_yp7HVZXFaqlFR1g79H2etwtPriydZkjaFE,5667 twisted/web/test/test_static.py,sha256=PqkZKWxhQ3GGmlMqwx2oDfrY_RlNc8ZPE5oaWLL74XU,67858 twisted/web/test/test_tap.py,sha256=w1GFPg5RbSWryvvp1wf7HleTz0EJHSoxHN3oMGpvzuc,12200 twisted/web/test/test_template.py,sha256=tVpMImaRl2wZQo1m-CPR1EfnApPSxhZedkLT4xTEsww,25977 twisted/web/test/test_util.py,sha256=pGxkGSoNPuWmunh_xqVJ8k4z97rMcZafvTgz6VOC770,12590 twisted/web/test/test_vhost.py,sha256=lF3ch-BlKMRqwug79z-y_dmFyJwQjVwLqhziruVeZz4,7398 twisted/web/test/test_web.py,sha256=CsyyQrdvYh-_r12YjuYXMS2z21hMR_bMZrXvqjfBgx8,64296 twisted/web/test/test_web__responses.py,sha256=Hsq7CDGZoxE9Iq78xaYuhZxqoN58qNuKsoaR4cgAMK0,877 twisted/web/test/test_webclient.py,sha256=Ww5dnXrDvtTsTwUAXtchL1vgKbQMrK_3Lbw4X9UtUMM,59615 twisted/web/test/test_wsgi.py,sha256=WAsGDXhOATeEIdDj-PPimPdrSoMVRKUl8EgCWVRcegw,78210 twisted/web/test/test_xml.py,sha256=zEnd97a1PSltKUfNyobziKKt7laDLWJV3jdfxJw3caw,42357 twisted/web/test/test_xmlrpc.py,sha256=6OL77o-ZcYUGS80cu5cyrbZA89DOkIB98xceNIOmQeA,30302 twisted/web/twcgi.py,sha256=_BIZTsI0soo5v7tf4gx25bqhbJhwNB8ZZCoDIdIgCr0,11343 twisted/web/util.py,sha256=Nwt-k63WLnLLhfA7vOh-10EkBboLhZehTM2oHpkFfjE,12412 twisted/web/vhost.py,sha256=9Y-li_wuLQmTJKPJWs4KOiT_WTVqhrnbfdcobtpbQnk,4463 twisted/web/wsgi.py,sha256=bjbeVJI5DrrhHlB1VFK-DVrOknosC_uRB6B4HGIMPDw,21879 twisted/web/xmlrpc.py,sha256=H5mFDI1rk1-dmj8QPijFyd34K5T7gKxTv8i-XMNFwak,20203 twisted/words/__init__.py,sha256=ffiFEwEz9RTE5rrSHV9jzhWhuomlg-tT7RQAXhlpGNI,215 twisted/words/__pycache__/__init__.cpython-36.pyc,, twisted/words/__pycache__/ewords.cpython-36.pyc,, twisted/words/__pycache__/iwords.cpython-36.pyc,, twisted/words/__pycache__/service.cpython-36.pyc,, twisted/words/__pycache__/tap.cpython-36.pyc,, twisted/words/__pycache__/xmpproutertap.cpython-36.pyc,, twisted/words/ewords.py,sha256=XOOQe4IRjQrj-kRj8Hu07VhjT6gCJYXmJ5MeFDhMEpE,623 twisted/words/im/__init__.py,sha256=ojtUkusjr0Xe56X-Oo4kmcmDCRCsC9C5qwZQZ_7vyPc,129 twisted/words/im/__pycache__/__init__.cpython-36.pyc,, twisted/words/im/__pycache__/baseaccount.cpython-36.pyc,, twisted/words/im/__pycache__/basechat.cpython-36.pyc,, twisted/words/im/__pycache__/basesupport.cpython-36.pyc,, twisted/words/im/__pycache__/interfaces.cpython-36.pyc,, twisted/words/im/__pycache__/ircsupport.cpython-36.pyc,, twisted/words/im/__pycache__/locals.cpython-36.pyc,, twisted/words/im/__pycache__/pbsupport.cpython-36.pyc,, twisted/words/im/baseaccount.py,sha256=s4wY-BSOVxOpuY85qyWzAV_Jcf53V48gPs7MA4ODitc,1808 twisted/words/im/basechat.py,sha256=sa3FXpKVESXmoCATOAq781KzPg-02vpk_Om42UcN1es,16454 twisted/words/im/basesupport.py,sha256=AmZMFNSPJRqriDckFSRrx2Ae2DeZUMblNdzi_yIPTpY,7842 twisted/words/im/instancemessenger.glade,sha256=Scnco66vE3ByEHRbXpG4jkjW8wBquLjVrPtTRXurkRs,77126 twisted/words/im/interfaces.py,sha256=C8hxSNUyi-BDhC7uzGQFAoQMGEb2BiqTekob5cOe-8o,8675 twisted/words/im/ircsupport.py,sha256=ZBhiItd93QgRcXZvEcSygIBi0-QJs5sWfyVAUY2bfQM,9150 twisted/words/im/locals.py,sha256=JCVxJC5thNvnoTQ9VbrGtdXtGoYDBAm4u9ZhqqL8G0I,499 twisted/words/im/pbsupport.py,sha256=964WKGL-swV-24Y_JT1-5hvfZwBxixjP-aDq5BebcJ8,9676 twisted/words/iwords.py,sha256=YtWBU_LM980pJN6_MjMToSVkZteZXYtTgM-wg5S9kPM,8528 twisted/words/protocols/__init__.py,sha256=zmeNC2QVvHipjDnBJSx2CKRWMONswC98R2IlwuAhWBw,97 twisted/words/protocols/__pycache__/__init__.cpython-36.pyc,, twisted/words/protocols/__pycache__/irc.cpython-36.pyc,, twisted/words/protocols/irc.py,sha256=spjIqZTWOAecb1e8iP5yTCxt5ArerCjo1gRpkxY_54I,125664 twisted/words/protocols/jabber/__init__.py,sha256=yofokZPwf09uggpzpyRuUCZf_qAkzijZZCZnDpkEN90,167 twisted/words/protocols/jabber/__pycache__/__init__.cpython-36.pyc,, twisted/words/protocols/jabber/__pycache__/client.cpython-36.pyc,, twisted/words/protocols/jabber/__pycache__/component.cpython-36.pyc,, twisted/words/protocols/jabber/__pycache__/error.cpython-36.pyc,, twisted/words/protocols/jabber/__pycache__/ijabber.cpython-36.pyc,, twisted/words/protocols/jabber/__pycache__/jid.cpython-36.pyc,, twisted/words/protocols/jabber/__pycache__/jstrports.cpython-36.pyc,, twisted/words/protocols/jabber/__pycache__/sasl.cpython-36.pyc,, twisted/words/protocols/jabber/__pycache__/sasl_mechanisms.cpython-36.pyc,, twisted/words/protocols/jabber/__pycache__/xmlstream.cpython-36.pyc,, twisted/words/protocols/jabber/__pycache__/xmpp_stringprep.cpython-36.pyc,, twisted/words/protocols/jabber/client.py,sha256=L4rpVpZFzNGjaGw7nb4468ZIpPxzPdlRa6mjiJZIZ3U,14382 twisted/words/protocols/jabber/component.py,sha256=bcXoz0-mtxYrYjZy8m_BlFJhuiZk3TG5jQm_hLHx15o,15595 twisted/words/protocols/jabber/error.py,sha256=GsmBMFqyQ3dJMfMebbocmF1Dp_MFYWObsKswKoqiwLA,10802 twisted/words/protocols/jabber/ijabber.py,sha256=R2Y4N6jWJFb7Rqz5O_QelpHtbQpCA6yjGXNUWXe8xpE,5380 twisted/words/protocols/jabber/jid.py,sha256=xqT9MfeTo2YD2hqSmFJqkxmi6Fsf_3zdy423UWukFTE,7249 twisted/words/protocols/jabber/jstrports.py,sha256=RoATh0iNGE-qN1MoJKTd9TXN_51Sshoo80a7qlJQ2Nc,978 twisted/words/protocols/jabber/sasl.py,sha256=uEVeYQ9snoX4ODHQmxOQSC0-zIWEoA8Dnaki-vpxiFA,7461 twisted/words/protocols/jabber/sasl_mechanisms.py,sha256=rPBzN-_kiyIne3GDVHVyHi8tRoKoEeS2Nv2tD46un2U,8730 twisted/words/protocols/jabber/xmlstream.py,sha256=bExNRabsilWpyGLxjQeat4TJoHt7nE0OegMb4NBGLUg,36848 twisted/words/protocols/jabber/xmpp_stringprep.py,sha256=JaC22A1_c9_mR0RoxjHZ1oO_VKbRHE4h4kViPK9YcGQ,7221 twisted/words/service.py,sha256=gREUR1_Cq5kEUEDA9BnjWAM87nqYq_3JPUoIZf7VjTM,38173 twisted/words/tap.py,sha256=a0Q_SX7jt6adZYHX_sSkB16qwWqz-uLGTOYV-br54W8,2422 twisted/words/test/__init__.py,sha256=wDdSRMUVT0_hf5Fe36M3C6GiB4N1TOqgB41q9B-Ia04,14 twisted/words/test/__pycache__/__init__.cpython-36.pyc,, twisted/words/test/__pycache__/test_basechat.cpython-36.pyc,, twisted/words/test/__pycache__/test_basesupport.cpython-36.pyc,, twisted/words/test/__pycache__/test_domish.cpython-36.pyc,, twisted/words/test/__pycache__/test_irc.cpython-36.pyc,, twisted/words/test/__pycache__/test_irc_service.cpython-36.pyc,, twisted/words/test/__pycache__/test_ircsupport.cpython-36.pyc,, twisted/words/test/__pycache__/test_jabberclient.cpython-36.pyc,, twisted/words/test/__pycache__/test_jabbercomponent.cpython-36.pyc,, twisted/words/test/__pycache__/test_jabbererror.cpython-36.pyc,, twisted/words/test/__pycache__/test_jabberjid.cpython-36.pyc,, twisted/words/test/__pycache__/test_jabberjstrports.cpython-36.pyc,, twisted/words/test/__pycache__/test_jabbersasl.cpython-36.pyc,, twisted/words/test/__pycache__/test_jabbersaslmechanisms.cpython-36.pyc,, twisted/words/test/__pycache__/test_jabberxmlstream.cpython-36.pyc,, twisted/words/test/__pycache__/test_jabberxmppstringprep.cpython-36.pyc,, twisted/words/test/__pycache__/test_service.cpython-36.pyc,, twisted/words/test/__pycache__/test_tap.cpython-36.pyc,, twisted/words/test/__pycache__/test_xishutil.cpython-36.pyc,, twisted/words/test/__pycache__/test_xmlstream.cpython-36.pyc,, twisted/words/test/__pycache__/test_xmpproutertap.cpython-36.pyc,, twisted/words/test/__pycache__/test_xpath.cpython-36.pyc,, twisted/words/test/test_basechat.py,sha256=y01cIaQ3LrPRUbsdsiTt50w5WeRu-tQrDLHqZe9MQos,2504 twisted/words/test/test_basesupport.py,sha256=YtA2z8fxt1aP-AYSHpO3PCLNA9t-G5De5ibFH_JEEd8,3064 twisted/words/test/test_domish.py,sha256=QFHbVSG9SHOy0IJ2_Gx-hTD-KLHHGVeSMJC8IinO3xA,20172 twisted/words/test/test_irc.py,sha256=LNcjt-o8U2BSbxx6kNpBb-b5z5OTi1kbuM54pwfQIxU,103397 twisted/words/test/test_irc_service.py,sha256=X_pjwDVCfKBShdEHIiezZH4UFyoyxWaRkAWzP5yGEOM,9639 twisted/words/test/test_ircsupport.py,sha256=vhzh3PXjUynPnsf3NwZ5Nu67w-4ZBuC4u1Oiz4tBVgs,10702 twisted/words/test/test_jabberclient.py,sha256=22MQ-lfQCgrRe9r5qTmXuHluFa_pPaxSRHkONpAlj4E,16866 twisted/words/test/test_jabbercomponent.py,sha256=gw_WkkLLegqMjjWpnCJP59pSNlgBQB0Wbu7mLjpPDe0,14204 twisted/words/test/test_jabbererror.py,sha256=h97z_XCO11UhFw8Zkb2GH1y31uF6wcILTIdkTdqdsNU,11521 twisted/words/test/test_jabberjid.py,sha256=5WlXkppYf9H7y_zDOLpBaXAYo2Am2SB0SkvT4x2_LN0,7210 twisted/words/test/test_jabberjstrports.py,sha256=0SJ1Z8J27DcBHANt-7w6rgn34rlY65LNaTZcp2ysQuY,996 twisted/words/test/test_jabbersasl.py,sha256=2aTrH1bZXhmejB0ILDjcYHOrAvWN_nM6tMPaGOoBrTU,9432 twisted/words/test/test_jabbersaslmechanisms.py,sha256=uz_kmwx2T_sFGms27gZ7NGbGBPESRGy46HiWiP2o6mU,5758 twisted/words/test/test_jabberxmlstream.py,sha256=kasBxkHYAr22DwlscSsO9dNUk8xmFQQ9bphSgk0hnbA,45718 twisted/words/test/test_jabberxmppstringprep.py,sha256=9E7K3ji2kRRzTYU9NWqqjdSUyvT4iOxYJELgVZhDShk,5549 twisted/words/test/test_service.py,sha256=cH-DqZL7lV4_kTHlyF6_XzA3w9g4Zs8lbt0J2XdRqWw,28462 twisted/words/test/test_tap.py,sha256=rNN4d-kYxOe-6dUmRwHmJe1wjN74Px0v2MltP02_TB4,2180 twisted/words/test/test_xishutil.py,sha256=onFjooPZ3cM3r42-iw2H9ihBcXZ5q865C8p5JgpftgA,9396 twisted/words/test/test_xmlstream.py,sha256=YuCLqVj1s1Ccll11b7OG_bm8IaoNOlFjNZeNKeLIfJQ,6274 twisted/words/test/test_xmpproutertap.py,sha256=qROkHmUyHZ1kRwThHV9-28LOhR74lQJXM-g5NUIRMww,2398 twisted/words/test/test_xpath.py,sha256=m2Fvr_21iIKlBiWNWp-7Pf8YTJm6f9_e1t9Ga4XjMO4,11002 twisted/words/xish/__init__.py,sha256=XJs3sqZxj1QVTrrgkbVAUcpxMekKLPEKzuEXFJVwp0k,177 twisted/words/xish/__pycache__/__init__.cpython-36.pyc,, twisted/words/xish/__pycache__/domish.cpython-36.pyc,, twisted/words/xish/__pycache__/utility.cpython-36.pyc,, twisted/words/xish/__pycache__/xmlstream.cpython-36.pyc,, twisted/words/xish/__pycache__/xpath.cpython-36.pyc,, twisted/words/xish/__pycache__/xpathparser.cpython-36.pyc,, twisted/words/xish/domish.py,sha256=O41aNQaLjs5aAhleDGctdPOG5EU1r9QQJ_K6JHLEIlY,30564 twisted/words/xish/utility.py,sha256=bCnYogLhRc1BWprU8ewiPqiU9kCUUoDZQqcdZoXFuZI,13482 twisted/words/xish/xmlstream.py,sha256=p9zjmPIaBSDFIb8a4Cgi6ReOIeDO4GllurTclNLljJc,9189 twisted/words/xish/xpath.py,sha256=KLvSEWoNXnD7ruqsATQYIy70cMFD7uXE8B7mp6xV3bY,9556 twisted/words/xish/xpathparser.g,sha256=eJQMsCzdX76niIJm8hHiLNLLqq4G6uJl6TDx9iPx6qk,18122 twisted/words/xish/xpathparser.py,sha256=iPE2dtF79_SU2i0GDQR9jW2Gc2UP6yWeJ_EEgPLCHwk,22851 twisted/words/xmpproutertap.py,sha256=n9oc9f4xelocf6NGS0_BreuRGbe9YBMpsdKuMjPrd8E,820 ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/Twisted-19.7.0.dist-info/WHEEL ================================================ Wheel-Version: 1.0 Generator: bdist_wheel (0.33.4) Root-Is-Purelib: false Tag: cp36-cp36m-manylinux1_x86_64 ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/Twisted-19.7.0.dist-info/entry_points.txt ================================================ [console_scripts] cftp = twisted.conch.scripts.cftp:run ckeygen = twisted.conch.scripts.ckeygen:run conch = twisted.conch.scripts.conch:run mailmail = twisted.mail.scripts.mailmail:run pyhtmlizer = twisted.scripts.htmlizer:run tkconch = twisted.conch.scripts.tkconch:run trial = twisted.scripts.trial:run twist = twisted.application.twist._twist:Twist.main twistd = twisted.scripts.twistd:run ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/Twisted-19.7.0.dist-info/top_level.txt ================================================ twisted ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/attr/__init__.py ================================================ from __future__ import absolute_import, division, print_function from functools import partial from . import converters, exceptions, filters, validators from ._config import get_run_validators, set_run_validators from ._funcs import asdict, assoc, astuple, evolve, has from ._make import ( NOTHING, Attribute, Factory, attrib, attrs, fields, fields_dict, make_class, validate, ) from ._version_info import VersionInfo __version__ = "19.3.0" __version_info__ = VersionInfo._from_version_string(__version__) __title__ = "attrs" __description__ = "Classes Without Boilerplate" __url__ = "https://www.attrs.org/" __uri__ = __url__ __doc__ = __description__ + " <" + __uri__ + ">" __author__ = "Hynek Schlawack" __email__ = "hs@ox.cx" __license__ = "MIT" __copyright__ = "Copyright (c) 2015 Hynek Schlawack" s = attributes = attrs ib = attr = attrib dataclass = partial(attrs, auto_attribs=True) # happy Easter ;) __all__ = [ "Attribute", "Factory", "NOTHING", "asdict", "assoc", "astuple", "attr", "attrib", "attributes", "attrs", "converters", "evolve", "exceptions", "fields", "fields_dict", "filters", "get_run_validators", "has", "ib", "make_class", "s", "set_run_validators", "validate", "validators", ] ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/attr/__init__.pyi ================================================ from typing import ( Any, Callable, Dict, Generic, List, Optional, Sequence, Mapping, Tuple, Type, TypeVar, Union, overload, ) # `import X as X` is required to make these public from . import exceptions as exceptions from . import filters as filters from . import converters as converters from . import validators as validators from ._version_info import VersionInfo __version__: str __version_info__: VersionInfo __title__: str __description__: str __url__: str __uri__: str __author__: str __email__: str __license__: str __copyright__: str _T = TypeVar("_T") _C = TypeVar("_C", bound=type) _ValidatorType = Callable[[Any, Attribute[_T], _T], Any] _ConverterType = Callable[[Any], _T] _FilterType = Callable[[Attribute[_T], _T], bool] _ReprType = Callable[[Any], str] _ReprArgType = Union[bool, _ReprType] # FIXME: in reality, if multiple validators are passed they must be in a list or tuple, # but those are invariant and so would prevent subtypes of _ValidatorType from working # when passed in a list or tuple. _ValidatorArgType = Union[_ValidatorType[_T], Sequence[_ValidatorType[_T]]] # _make -- NOTHING: object # NOTE: Factory lies about its return type to make this possible: `x: List[int] = Factory(list)` # Work around mypy issue #4554 in the common case by using an overload. @overload def Factory(factory: Callable[[], _T]) -> _T: ... @overload def Factory( factory: Union[Callable[[Any], _T], Callable[[], _T]], takes_self: bool = ..., ) -> _T: ... class Attribute(Generic[_T]): name: str default: Optional[_T] validator: Optional[_ValidatorType[_T]] repr: _ReprArgType cmp: bool eq: bool order: bool hash: Optional[bool] init: bool converter: Optional[_ConverterType[_T]] metadata: Dict[Any, Any] type: Optional[Type[_T]] kw_only: bool # NOTE: We had several choices for the annotation to use for type arg: # 1) Type[_T] # - Pros: Handles simple cases correctly # - Cons: Might produce less informative errors in the case of conflicting TypeVars # e.g. `attr.ib(default='bad', type=int)` # 2) Callable[..., _T] # - Pros: Better error messages than #1 for conflicting TypeVars # - Cons: Terrible error messages for validator checks. # e.g. attr.ib(type=int, validator=validate_str) # -> error: Cannot infer function type argument # 3) type (and do all of the work in the mypy plugin) # - Pros: Simple here, and we could customize the plugin with our own errors. # - Cons: Would need to write mypy plugin code to handle all the cases. # We chose option #1. # `attr` lies about its return type to make the following possible: # attr() -> Any # attr(8) -> int # attr(validator=) -> Whatever the callable expects. # This makes this type of assignments possible: # x: int = attr(8) # # This form catches explicit None or no default but with no other arguments returns Any. @overload def attrib( default: None = ..., validator: None = ..., repr: _ReprArgType = ..., cmp: Optional[bool] = ..., hash: Optional[bool] = ..., init: bool = ..., metadata: Optional[Mapping[Any, Any]] = ..., type: None = ..., converter: None = ..., factory: None = ..., kw_only: bool = ..., eq: Optional[bool] = ..., order: Optional[bool] = ..., ) -> Any: ... # This form catches an explicit None or no default and infers the type from the other arguments. @overload def attrib( default: None = ..., validator: Optional[_ValidatorArgType[_T]] = ..., repr: _ReprArgType = ..., cmp: Optional[bool] = ..., hash: Optional[bool] = ..., init: bool = ..., metadata: Optional[Mapping[Any, Any]] = ..., type: Optional[Type[_T]] = ..., converter: Optional[_ConverterType[_T]] = ..., factory: Optional[Callable[[], _T]] = ..., kw_only: bool = ..., eq: Optional[bool] = ..., order: Optional[bool] = ..., ) -> _T: ... # This form catches an explicit default argument. @overload def attrib( default: _T, validator: Optional[_ValidatorArgType[_T]] = ..., repr: _ReprArgType = ..., cmp: Optional[bool] = ..., hash: Optional[bool] = ..., init: bool = ..., metadata: Optional[Mapping[Any, Any]] = ..., type: Optional[Type[_T]] = ..., converter: Optional[_ConverterType[_T]] = ..., factory: Optional[Callable[[], _T]] = ..., kw_only: bool = ..., eq: Optional[bool] = ..., order: Optional[bool] = ..., ) -> _T: ... # This form covers type=non-Type: e.g. forward references (str), Any @overload def attrib( default: Optional[_T] = ..., validator: Optional[_ValidatorArgType[_T]] = ..., repr: _ReprArgType = ..., cmp: Optional[bool] = ..., hash: Optional[bool] = ..., init: bool = ..., metadata: Optional[Mapping[Any, Any]] = ..., type: object = ..., converter: Optional[_ConverterType[_T]] = ..., factory: Optional[Callable[[], _T]] = ..., kw_only: bool = ..., eq: Optional[bool] = ..., order: Optional[bool] = ..., ) -> Any: ... @overload def attrs( maybe_cls: _C, these: Optional[Dict[str, Any]] = ..., repr_ns: Optional[str] = ..., repr: bool = ..., cmp: Optional[bool] = ..., hash: Optional[bool] = ..., init: bool = ..., slots: bool = ..., frozen: bool = ..., weakref_slot: bool = ..., str: bool = ..., auto_attribs: bool = ..., kw_only: bool = ..., cache_hash: bool = ..., auto_exc: bool = ..., eq: Optional[bool] = ..., order: Optional[bool] = ..., ) -> _C: ... @overload def attrs( maybe_cls: None = ..., these: Optional[Dict[str, Any]] = ..., repr_ns: Optional[str] = ..., repr: bool = ..., cmp: Optional[bool] = ..., hash: Optional[bool] = ..., init: bool = ..., slots: bool = ..., frozen: bool = ..., weakref_slot: bool = ..., str: bool = ..., auto_attribs: bool = ..., kw_only: bool = ..., cache_hash: bool = ..., auto_exc: bool = ..., eq: Optional[bool] = ..., order: Optional[bool] = ..., ) -> Callable[[_C], _C]: ... # TODO: add support for returning NamedTuple from the mypy plugin class _Fields(Tuple[Attribute[Any], ...]): def __getattr__(self, name: str) -> Attribute[Any]: ... def fields(cls: type) -> _Fields: ... def fields_dict(cls: type) -> Dict[str, Attribute[Any]]: ... def validate(inst: Any) -> None: ... # TODO: add support for returning a proper attrs class from the mypy plugin # we use Any instead of _CountingAttr so that e.g. `make_class('Foo', [attr.ib()])` is valid def make_class( name: str, attrs: Union[List[str], Tuple[str, ...], Dict[str, Any]], bases: Tuple[type, ...] = ..., repr_ns: Optional[str] = ..., repr: bool = ..., cmp: Optional[bool] = ..., hash: Optional[bool] = ..., init: bool = ..., slots: bool = ..., frozen: bool = ..., weakref_slot: bool = ..., str: bool = ..., auto_attribs: bool = ..., kw_only: bool = ..., cache_hash: bool = ..., auto_exc: bool = ..., eq: Optional[bool] = ..., order: Optional[bool] = ..., ) -> type: ... # _funcs -- # TODO: add support for returning TypedDict from the mypy plugin # FIXME: asdict/astuple do not honor their factory args. waiting on one of these: # https://github.com/python/mypy/issues/4236 # https://github.com/python/typing/issues/253 def asdict( inst: Any, recurse: bool = ..., filter: Optional[_FilterType[Any]] = ..., dict_factory: Type[Mapping[Any, Any]] = ..., retain_collection_types: bool = ..., ) -> Dict[str, Any]: ... # TODO: add support for returning NamedTuple from the mypy plugin def astuple( inst: Any, recurse: bool = ..., filter: Optional[_FilterType[Any]] = ..., tuple_factory: Type[Sequence[Any]] = ..., retain_collection_types: bool = ..., ) -> Tuple[Any, ...]: ... def has(cls: type) -> bool: ... def assoc(inst: _T, **changes: Any) -> _T: ... def evolve(inst: _T, **changes: Any) -> _T: ... # _config -- def set_run_validators(run: bool) -> None: ... def get_run_validators() -> bool: ... # aliases -- s = attributes = attrs ib = attr = attrib dataclass = attrs # Technically, partial(attrs, auto_attribs=True) ;) ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/attr/_compat.py ================================================ from __future__ import absolute_import, division, print_function import platform import sys import types import warnings PY2 = sys.version_info[0] == 2 PYPY = platform.python_implementation() == "PyPy" if PYPY or sys.version_info[:2] >= (3, 6): ordered_dict = dict else: from collections import OrderedDict ordered_dict = OrderedDict if PY2: from UserDict import IterableUserDict from collections import Mapping, Sequence # We 'bundle' isclass instead of using inspect as importing inspect is # fairly expensive (order of 10-15 ms for a modern machine in 2016) def isclass(klass): return isinstance(klass, (type, types.ClassType)) # TYPE is used in exceptions, repr(int) is different on Python 2 and 3. TYPE = "type" def iteritems(d): return d.iteritems() # Python 2 is bereft of a read-only dict proxy, so we make one! class ReadOnlyDict(IterableUserDict): """ Best-effort read-only dict wrapper. """ def __setitem__(self, key, val): # We gently pretend we're a Python 3 mappingproxy. raise TypeError( "'mappingproxy' object does not support item assignment" ) def update(self, _): # We gently pretend we're a Python 3 mappingproxy. raise AttributeError( "'mappingproxy' object has no attribute 'update'" ) def __delitem__(self, _): # We gently pretend we're a Python 3 mappingproxy. raise TypeError( "'mappingproxy' object does not support item deletion" ) def clear(self): # We gently pretend we're a Python 3 mappingproxy. raise AttributeError( "'mappingproxy' object has no attribute 'clear'" ) def pop(self, key, default=None): # We gently pretend we're a Python 3 mappingproxy. raise AttributeError( "'mappingproxy' object has no attribute 'pop'" ) def popitem(self): # We gently pretend we're a Python 3 mappingproxy. raise AttributeError( "'mappingproxy' object has no attribute 'popitem'" ) def setdefault(self, key, default=None): # We gently pretend we're a Python 3 mappingproxy. raise AttributeError( "'mappingproxy' object has no attribute 'setdefault'" ) def __repr__(self): # Override to be identical to the Python 3 version. return "mappingproxy(" + repr(self.data) + ")" def metadata_proxy(d): res = ReadOnlyDict() res.data.update(d) # We blocked update, so we have to do it like this. return res def just_warn(*args, **kw): # pragma: nocover """ We only warn on Python 3 because we are not aware of any concrete consequences of not setting the cell on Python 2. """ else: # Python 3 and later. from collections.abc import Mapping, Sequence # noqa def just_warn(*args, **kw): """ We only warn on Python 3 because we are not aware of any concrete consequences of not setting the cell on Python 2. """ warnings.warn( "Running interpreter doesn't sufficiently support code object " "introspection. Some features like bare super() or accessing " "__class__ will not work with slotted classes.", RuntimeWarning, stacklevel=2, ) def isclass(klass): return isinstance(klass, type) TYPE = "class" def iteritems(d): return d.items() def metadata_proxy(d): return types.MappingProxyType(dict(d)) def make_set_closure_cell(): """Return a function of two arguments (cell, value) which sets the value stored in the closure cell `cell` to `value`. """ # pypy makes this easy. (It also supports the logic below, but # why not do the easy/fast thing?) if PYPY: # pragma: no cover def set_closure_cell(cell, value): cell.__setstate__((value,)) return set_closure_cell # Otherwise gotta do it the hard way. # Create a function that will set its first cellvar to `value`. def set_first_cellvar_to(value): x = value return # This function will be eliminated as dead code, but # not before its reference to `x` forces `x` to be # represented as a closure cell rather than a local. def force_x_to_be_a_cell(): # pragma: no cover return x try: # Extract the code object and make sure our assumptions about # the closure behavior are correct. if PY2: co = set_first_cellvar_to.func_code else: co = set_first_cellvar_to.__code__ if co.co_cellvars != ("x",) or co.co_freevars != (): raise AssertionError # pragma: no cover # Convert this code object to a code object that sets the # function's first _freevar_ (not cellvar) to the argument. if sys.version_info >= (3, 8): # CPython 3.8+ has an incompatible CodeType signature # (added a posonlyargcount argument) but also added # CodeType.replace() to do this without counting parameters. set_first_freevar_code = co.replace( co_cellvars=co.co_freevars, co_freevars=co.co_cellvars ) else: args = [co.co_argcount] if not PY2: args.append(co.co_kwonlyargcount) args.extend( [ co.co_nlocals, co.co_stacksize, co.co_flags, co.co_code, co.co_consts, co.co_names, co.co_varnames, co.co_filename, co.co_name, co.co_firstlineno, co.co_lnotab, # These two arguments are reversed: co.co_cellvars, co.co_freevars, ] ) set_first_freevar_code = types.CodeType(*args) def set_closure_cell(cell, value): # Create a function using the set_first_freevar_code, # whose first closure cell is `cell`. Calling it will # change the value of that cell. setter = types.FunctionType( set_first_freevar_code, {}, "setter", (), (cell,) ) # And call it to set the cell. setter(value) # Make sure it works on this interpreter: def make_func_with_cell(): x = None def func(): return x # pragma: no cover return func if PY2: cell = make_func_with_cell().func_closure[0] else: cell = make_func_with_cell().__closure__[0] set_closure_cell(cell, 100) if cell.cell_contents != 100: raise AssertionError # pragma: no cover except Exception: return just_warn else: return set_closure_cell set_closure_cell = make_set_closure_cell() ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/attr/_config.py ================================================ from __future__ import absolute_import, division, print_function __all__ = ["set_run_validators", "get_run_validators"] _run_validators = True def set_run_validators(run): """ Set whether or not validators are run. By default, they are run. """ if not isinstance(run, bool): raise TypeError("'run' must be bool.") global _run_validators _run_validators = run def get_run_validators(): """ Return whether or not validators are run. """ return _run_validators ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/attr/_funcs.py ================================================ from __future__ import absolute_import, division, print_function import copy from ._compat import iteritems from ._make import NOTHING, _obj_setattr, fields from .exceptions import AttrsAttributeNotFoundError def asdict( inst, recurse=True, filter=None, dict_factory=dict, retain_collection_types=False, ): """ Return the ``attrs`` attribute values of *inst* as a dict. Optionally recurse into other ``attrs``-decorated classes. :param inst: Instance of an ``attrs``-decorated class. :param bool recurse: Recurse into classes that are also ``attrs``-decorated. :param callable filter: A callable whose return code determines whether an attribute or element is included (``True``) or dropped (``False``). Is called with the `attr.Attribute` as the first argument and the value as the second argument. :param callable dict_factory: A callable to produce dictionaries from. For example, to produce ordered dictionaries instead of normal Python dictionaries, pass in ``collections.OrderedDict``. :param bool retain_collection_types: Do not convert to ``list`` when encountering an attribute whose type is ``tuple`` or ``set``. Only meaningful if ``recurse`` is ``True``. :rtype: return type of *dict_factory* :raise attr.exceptions.NotAnAttrsClassError: If *cls* is not an ``attrs`` class. .. versionadded:: 16.0.0 *dict_factory* .. versionadded:: 16.1.0 *retain_collection_types* """ attrs = fields(inst.__class__) rv = dict_factory() for a in attrs: v = getattr(inst, a.name) if filter is not None and not filter(a, v): continue if recurse is True: if has(v.__class__): rv[a.name] = asdict( v, True, filter, dict_factory, retain_collection_types ) elif isinstance(v, (tuple, list, set)): cf = v.__class__ if retain_collection_types is True else list rv[a.name] = cf( [ _asdict_anything( i, filter, dict_factory, retain_collection_types ) for i in v ] ) elif isinstance(v, dict): df = dict_factory rv[a.name] = df( ( _asdict_anything( kk, filter, df, retain_collection_types ), _asdict_anything( vv, filter, df, retain_collection_types ), ) for kk, vv in iteritems(v) ) else: rv[a.name] = v else: rv[a.name] = v return rv def _asdict_anything(val, filter, dict_factory, retain_collection_types): """ ``asdict`` only works on attrs instances, this works on anything. """ if getattr(val.__class__, "__attrs_attrs__", None) is not None: # Attrs class. rv = asdict(val, True, filter, dict_factory, retain_collection_types) elif isinstance(val, (tuple, list, set)): cf = val.__class__ if retain_collection_types is True else list rv = cf( [ _asdict_anything( i, filter, dict_factory, retain_collection_types ) for i in val ] ) elif isinstance(val, dict): df = dict_factory rv = df( ( _asdict_anything(kk, filter, df, retain_collection_types), _asdict_anything(vv, filter, df, retain_collection_types), ) for kk, vv in iteritems(val) ) else: rv = val return rv def astuple( inst, recurse=True, filter=None, tuple_factory=tuple, retain_collection_types=False, ): """ Return the ``attrs`` attribute values of *inst* as a tuple. Optionally recurse into other ``attrs``-decorated classes. :param inst: Instance of an ``attrs``-decorated class. :param bool recurse: Recurse into classes that are also ``attrs``-decorated. :param callable filter: A callable whose return code determines whether an attribute or element is included (``True``) or dropped (``False``). Is called with the `attr.Attribute` as the first argument and the value as the second argument. :param callable tuple_factory: A callable to produce tuples from. For example, to produce lists instead of tuples. :param bool retain_collection_types: Do not convert to ``list`` or ``dict`` when encountering an attribute which type is ``tuple``, ``dict`` or ``set``. Only meaningful if ``recurse`` is ``True``. :rtype: return type of *tuple_factory* :raise attr.exceptions.NotAnAttrsClassError: If *cls* is not an ``attrs`` class. .. versionadded:: 16.2.0 """ attrs = fields(inst.__class__) rv = [] retain = retain_collection_types # Very long. :/ for a in attrs: v = getattr(inst, a.name) if filter is not None and not filter(a, v): continue if recurse is True: if has(v.__class__): rv.append( astuple( v, recurse=True, filter=filter, tuple_factory=tuple_factory, retain_collection_types=retain, ) ) elif isinstance(v, (tuple, list, set)): cf = v.__class__ if retain is True else list rv.append( cf( [ astuple( j, recurse=True, filter=filter, tuple_factory=tuple_factory, retain_collection_types=retain, ) if has(j.__class__) else j for j in v ] ) ) elif isinstance(v, dict): df = v.__class__ if retain is True else dict rv.append( df( ( astuple( kk, tuple_factory=tuple_factory, retain_collection_types=retain, ) if has(kk.__class__) else kk, astuple( vv, tuple_factory=tuple_factory, retain_collection_types=retain, ) if has(vv.__class__) else vv, ) for kk, vv in iteritems(v) ) ) else: rv.append(v) else: rv.append(v) return rv if tuple_factory is list else tuple_factory(rv) def has(cls): """ Check whether *cls* is a class with ``attrs`` attributes. :param type cls: Class to introspect. :raise TypeError: If *cls* is not a class. :rtype: bool """ return getattr(cls, "__attrs_attrs__", None) is not None def assoc(inst, **changes): """ Copy *inst* and apply *changes*. :param inst: Instance of a class with ``attrs`` attributes. :param changes: Keyword changes in the new copy. :return: A copy of inst with *changes* incorporated. :raise attr.exceptions.AttrsAttributeNotFoundError: If *attr_name* couldn't be found on *cls*. :raise attr.exceptions.NotAnAttrsClassError: If *cls* is not an ``attrs`` class. .. deprecated:: 17.1.0 Use `evolve` instead. """ import warnings warnings.warn( "assoc is deprecated and will be removed after 2018/01.", DeprecationWarning, stacklevel=2, ) new = copy.copy(inst) attrs = fields(inst.__class__) for k, v in iteritems(changes): a = getattr(attrs, k, NOTHING) if a is NOTHING: raise AttrsAttributeNotFoundError( "{k} is not an attrs attribute on {cl}.".format( k=k, cl=new.__class__ ) ) _obj_setattr(new, k, v) return new def evolve(inst, **changes): """ Create a new instance, based on *inst* with *changes* applied. :param inst: Instance of a class with ``attrs`` attributes. :param changes: Keyword changes in the new copy. :return: A copy of inst with *changes* incorporated. :raise TypeError: If *attr_name* couldn't be found in the class ``__init__``. :raise attr.exceptions.NotAnAttrsClassError: If *cls* is not an ``attrs`` class. .. versionadded:: 17.1.0 """ cls = inst.__class__ attrs = fields(cls) for a in attrs: if not a.init: continue attr_name = a.name # To deal with private attributes. init_name = attr_name if attr_name[0] != "_" else attr_name[1:] if init_name not in changes: changes[init_name] = getattr(inst, attr_name) return cls(**changes) ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/attr/_make.py ================================================ from __future__ import absolute_import, division, print_function import copy import linecache import sys import threading import uuid import warnings from operator import itemgetter from . import _config from ._compat import ( PY2, isclass, iteritems, metadata_proxy, ordered_dict, set_closure_cell, ) from .exceptions import ( DefaultAlreadySetError, FrozenInstanceError, NotAnAttrsClassError, PythonTooOldError, UnannotatedAttributeError, ) # This is used at least twice, so cache it here. _obj_setattr = object.__setattr__ _init_converter_pat = "__attr_converter_{}" _init_factory_pat = "__attr_factory_{}" _tuple_property_pat = ( " {attr_name} = _attrs_property(_attrs_itemgetter({index}))" ) _classvar_prefixes = ("typing.ClassVar", "t.ClassVar", "ClassVar") # we don't use a double-underscore prefix because that triggers # name mangling when trying to create a slot for the field # (when slots=True) _hash_cache_field = "_attrs_cached_hash" _empty_metadata_singleton = metadata_proxy({}) # Unique object for unequivocal getattr() defaults. _sentinel = object() class _Nothing(object): """ Sentinel class to indicate the lack of a value when ``None`` is ambiguous. ``_Nothing`` is a singleton. There is only ever one of it. """ _singleton = None def __new__(cls): if _Nothing._singleton is None: _Nothing._singleton = super(_Nothing, cls).__new__(cls) return _Nothing._singleton def __repr__(self): return "NOTHING" NOTHING = _Nothing() """ Sentinel to indicate the lack of a value when ``None`` is ambiguous. """ def attrib( default=NOTHING, validator=None, repr=True, cmp=None, hash=None, init=True, metadata=None, type=None, converter=None, factory=None, kw_only=False, eq=None, order=None, ): """ Create a new attribute on a class. .. warning:: Does *not* do anything unless the class is also decorated with `attr.s`! :param default: A value that is used if an ``attrs``-generated ``__init__`` is used and no value is passed while instantiating or the attribute is excluded using ``init=False``. If the value is an instance of `Factory`, its callable will be used to construct a new value (useful for mutable data types like lists or dicts). If a default is not set (or set manually to ``attr.NOTHING``), a value *must* be supplied when instantiating; otherwise a `TypeError` will be raised. The default can also be set using decorator notation as shown below. :type default: Any value :param callable factory: Syntactic sugar for ``default=attr.Factory(callable)``. :param validator: `callable` that is called by ``attrs``-generated ``__init__`` methods after the instance has been initialized. They receive the initialized instance, the `Attribute`, and the passed value. The return value is *not* inspected so the validator has to throw an exception itself. If a ``list`` is passed, its items are treated as validators and must all pass. Validators can be globally disabled and re-enabled using `get_run_validators`. The validator can also be set using decorator notation as shown below. :type validator: ``callable`` or a ``list`` of ``callable``\\ s. :param repr: Include this attribute in the generated ``__repr__`` method. If ``True``, include the attribute; if ``False``, omit it. By default, the built-in ``repr()`` function is used. To override how the attribute value is formatted, pass a ``callable`` that takes a single value and returns a string. Note that the resulting string is used as-is, i.e. it will be used directly *instead* of calling ``repr()`` (the default). :type repr: a ``bool`` or a ``callable`` to use a custom function. :param bool eq: If ``True`` (default), include this attribute in the generated ``__eq__`` and ``__ne__`` methods that check two instances for equality. :param bool order: If ``True`` (default), include this attributes in the generated ``__lt__``, ``__le__``, ``__gt__`` and ``__ge__`` methods. :param bool cmp: Setting to ``True`` is equivalent to setting ``eq=True, order=True``. Deprecated in favor of *eq* and *order*. :param hash: Include this attribute in the generated ``__hash__`` method. If ``None`` (default), mirror *eq*'s value. This is the correct behavior according the Python spec. Setting this value to anything else than ``None`` is *discouraged*. :type hash: ``bool`` or ``None`` :param bool init: Include this attribute in the generated ``__init__`` method. It is possible to set this to ``False`` and set a default value. In that case this attributed is unconditionally initialized with the specified default value or factory. :param callable converter: `callable` that is called by ``attrs``-generated ``__init__`` methods to converter attribute's value to the desired format. It is given the passed-in value, and the returned value will be used as the new value of the attribute. The value is converted before being passed to the validator, if any. :param metadata: An arbitrary mapping, to be used by third-party components. See `extending_metadata`. :param type: The type of the attribute. In Python 3.6 or greater, the preferred method to specify the type is using a variable annotation (see `PEP 526 `_). This argument is provided for backward compatibility. Regardless of the approach used, the type will be stored on ``Attribute.type``. Please note that ``attrs`` doesn't do anything with this metadata by itself. You can use it as part of your own code or for `static type checking `. :param kw_only: Make this attribute keyword-only (Python 3+) in the generated ``__init__`` (if ``init`` is ``False``, this parameter is ignored). .. versionadded:: 15.2.0 *convert* .. versionadded:: 16.3.0 *metadata* .. versionchanged:: 17.1.0 *validator* can be a ``list`` now. .. versionchanged:: 17.1.0 *hash* is ``None`` and therefore mirrors *eq* by default. .. versionadded:: 17.3.0 *type* .. deprecated:: 17.4.0 *convert* .. versionadded:: 17.4.0 *converter* as a replacement for the deprecated *convert* to achieve consistency with other noun-based arguments. .. versionadded:: 18.1.0 ``factory=f`` is syntactic sugar for ``default=attr.Factory(f)``. .. versionadded:: 18.2.0 *kw_only* .. versionchanged:: 19.2.0 *convert* keyword argument removed .. versionchanged:: 19.2.0 *repr* also accepts a custom callable. .. deprecated:: 19.2.0 *cmp* Removal on or after 2021-06-01. .. versionadded:: 19.2.0 *eq* and *order* """ eq, order = _determine_eq_order(cmp, eq, order) if hash is not None and hash is not True and hash is not False: raise TypeError( "Invalid value for hash. Must be True, False, or None." ) if factory is not None: if default is not NOTHING: raise ValueError( "The `default` and `factory` arguments are mutually " "exclusive." ) if not callable(factory): raise ValueError("The `factory` argument must be a callable.") default = Factory(factory) if metadata is None: metadata = {} return _CountingAttr( default=default, validator=validator, repr=repr, cmp=None, hash=hash, init=init, converter=converter, metadata=metadata, type=type, kw_only=kw_only, eq=eq, order=order, ) def _make_attr_tuple_class(cls_name, attr_names): """ Create a tuple subclass to hold `Attribute`s for an `attrs` class. The subclass is a bare tuple with properties for names. class MyClassAttributes(tuple): __slots__ = () x = property(itemgetter(0)) """ attr_class_name = "{}Attributes".format(cls_name) attr_class_template = [ "class {}(tuple):".format(attr_class_name), " __slots__ = ()", ] if attr_names: for i, attr_name in enumerate(attr_names): attr_class_template.append( _tuple_property_pat.format(index=i, attr_name=attr_name) ) else: attr_class_template.append(" pass") globs = {"_attrs_itemgetter": itemgetter, "_attrs_property": property} eval(compile("\n".join(attr_class_template), "", "exec"), globs) return globs[attr_class_name] # Tuple class for extracted attributes from a class definition. # `base_attrs` is a subset of `attrs`. _Attributes = _make_attr_tuple_class( "_Attributes", [ # all attributes to build dunder methods for "attrs", # attributes that have been inherited "base_attrs", # map inherited attributes to their originating classes "base_attrs_map", ], ) def _is_class_var(annot): """ Check whether *annot* is a typing.ClassVar. The string comparison hack is used to avoid evaluating all string annotations which would put attrs-based classes at a performance disadvantage compared to plain old classes. """ return str(annot).startswith(_classvar_prefixes) def _get_annotations(cls): """ Get annotations for *cls*. """ anns = getattr(cls, "__annotations__", None) if anns is None: return {} # Verify that the annotations aren't merely inherited. for base_cls in cls.__mro__[1:]: if anns is getattr(base_cls, "__annotations__", None): return {} return anns def _counter_getter(e): """ Key function for sorting to avoid re-creating a lambda for every class. """ return e[1].counter def _transform_attrs(cls, these, auto_attribs, kw_only): """ Transform all `_CountingAttr`s on a class into `Attribute`s. If *these* is passed, use that and don't look for them on the class. Return an `_Attributes`. """ cd = cls.__dict__ anns = _get_annotations(cls) if these is not None: ca_list = [(name, ca) for name, ca in iteritems(these)] if not isinstance(these, ordered_dict): ca_list.sort(key=_counter_getter) elif auto_attribs is True: ca_names = { name for name, attr in cd.items() if isinstance(attr, _CountingAttr) } ca_list = [] annot_names = set() for attr_name, type in anns.items(): if _is_class_var(type): continue annot_names.add(attr_name) a = cd.get(attr_name, NOTHING) if not isinstance(a, _CountingAttr): if a is NOTHING: a = attrib() else: a = attrib(default=a) ca_list.append((attr_name, a)) unannotated = ca_names - annot_names if len(unannotated) > 0: raise UnannotatedAttributeError( "The following `attr.ib`s lack a type annotation: " + ", ".join( sorted(unannotated, key=lambda n: cd.get(n).counter) ) + "." ) else: ca_list = sorted( ( (name, attr) for name, attr in cd.items() if isinstance(attr, _CountingAttr) ), key=lambda e: e[1].counter, ) own_attrs = [ Attribute.from_counting_attr( name=attr_name, ca=ca, type=anns.get(attr_name) ) for attr_name, ca in ca_list ] base_attrs = [] base_attr_map = {} # A dictionary of base attrs to their classes. taken_attr_names = {a.name: a for a in own_attrs} # Traverse the MRO and collect attributes. for base_cls in cls.__mro__[1:-1]: sub_attrs = getattr(base_cls, "__attrs_attrs__", None) if sub_attrs is not None: for a in sub_attrs: prev_a = taken_attr_names.get(a.name) # Only add an attribute if it hasn't been defined before. This # allows for overwriting attribute definitions by subclassing. if prev_a is None: base_attrs.append(a) taken_attr_names[a.name] = a base_attr_map[a.name] = base_cls attr_names = [a.name for a in base_attrs + own_attrs] AttrsClass = _make_attr_tuple_class(cls.__name__, attr_names) if kw_only: own_attrs = [a._assoc(kw_only=True) for a in own_attrs] base_attrs = [a._assoc(kw_only=True) for a in base_attrs] attrs = AttrsClass(base_attrs + own_attrs) # Mandatory vs non-mandatory attr order only matters when they are part of # the __init__ signature and when they aren't kw_only (which are moved to # the end and can be mandatory or non-mandatory in any order, as they will # be specified as keyword args anyway). Check the order of those attrs: had_default = False for a in (a for a in attrs if a.init is not False and a.kw_only is False): if had_default is True and a.default is NOTHING: raise ValueError( "No mandatory attributes allowed after an attribute with a " "default value or factory. Attribute in question: %r" % (a,) ) if had_default is False and a.default is not NOTHING: had_default = True return _Attributes((attrs, base_attrs, base_attr_map)) def _frozen_setattrs(self, name, value): """ Attached to frozen classes as __setattr__. """ raise FrozenInstanceError() def _frozen_delattrs(self, name): """ Attached to frozen classes as __delattr__. """ raise FrozenInstanceError() class _ClassBuilder(object): """ Iteratively build *one* class. """ __slots__ = ( "_cls", "_cls_dict", "_attrs", "_base_names", "_attr_names", "_slots", "_frozen", "_weakref_slot", "_cache_hash", "_has_post_init", "_delete_attribs", "_base_attr_map", "_is_exc", ) def __init__( self, cls, these, slots, frozen, weakref_slot, auto_attribs, kw_only, cache_hash, is_exc, ): attrs, base_attrs, base_map = _transform_attrs( cls, these, auto_attribs, kw_only ) self._cls = cls self._cls_dict = dict(cls.__dict__) if slots else {} self._attrs = attrs self._base_names = set(a.name for a in base_attrs) self._base_attr_map = base_map self._attr_names = tuple(a.name for a in attrs) self._slots = slots self._frozen = frozen or _has_frozen_base_class(cls) self._weakref_slot = weakref_slot self._cache_hash = cache_hash self._has_post_init = bool(getattr(cls, "__attrs_post_init__", False)) self._delete_attribs = not bool(these) self._is_exc = is_exc self._cls_dict["__attrs_attrs__"] = self._attrs if frozen: self._cls_dict["__setattr__"] = _frozen_setattrs self._cls_dict["__delattr__"] = _frozen_delattrs def __repr__(self): return "<_ClassBuilder(cls={cls})>".format(cls=self._cls.__name__) def build_class(self): """ Finalize class based on the accumulated configuration. Builder cannot be used after calling this method. """ if self._slots is True: return self._create_slots_class() else: return self._patch_original_class() def _patch_original_class(self): """ Apply accumulated methods and return the class. """ cls = self._cls base_names = self._base_names # Clean class of attribute definitions (`attr.ib()`s). if self._delete_attribs: for name in self._attr_names: if ( name not in base_names and getattr(cls, name, _sentinel) is not _sentinel ): try: delattr(cls, name) except AttributeError: # This can happen if a base class defines a class # variable and we want to set an attribute with the # same name by using only a type annotation. pass # Attach our dunder methods. for name, value in self._cls_dict.items(): setattr(cls, name, value) # Attach __setstate__. This is necessary to clear the hash code # cache on deserialization. See issue # https://github.com/python-attrs/attrs/issues/482 . # Note that this code only handles setstate for dict classes. # For slotted classes, see similar code in _create_slots_class . if self._cache_hash: existing_set_state_method = getattr(cls, "__setstate__", None) if existing_set_state_method: raise NotImplementedError( "Currently you cannot use hash caching if " "you specify your own __setstate__ method." "See https://github.com/python-attrs/attrs/issues/494 ." ) def cache_hash_set_state(chss_self, _): # clear hash code cache setattr(chss_self, _hash_cache_field, None) setattr(cls, "__setstate__", cache_hash_set_state) return cls def _create_slots_class(self): """ Build and return a new class with a `__slots__` attribute. """ base_names = self._base_names cd = { k: v for k, v in iteritems(self._cls_dict) if k not in tuple(self._attr_names) + ("__dict__", "__weakref__") } weakref_inherited = False # Traverse the MRO to check for an existing __weakref__. for base_cls in self._cls.__mro__[1:-1]: if "__weakref__" in getattr(base_cls, "__dict__", ()): weakref_inherited = True break names = self._attr_names if ( self._weakref_slot and "__weakref__" not in getattr(self._cls, "__slots__", ()) and "__weakref__" not in names and not weakref_inherited ): names += ("__weakref__",) # We only add the names of attributes that aren't inherited. # Settings __slots__ to inherited attributes wastes memory. slot_names = [name for name in names if name not in base_names] if self._cache_hash: slot_names.append(_hash_cache_field) cd["__slots__"] = tuple(slot_names) qualname = getattr(self._cls, "__qualname__", None) if qualname is not None: cd["__qualname__"] = qualname # __weakref__ is not writable. state_attr_names = tuple( an for an in self._attr_names if an != "__weakref__" ) def slots_getstate(self): """ Automatically created by attrs. """ return tuple(getattr(self, name) for name in state_attr_names) hash_caching_enabled = self._cache_hash def slots_setstate(self, state): """ Automatically created by attrs. """ __bound_setattr = _obj_setattr.__get__(self, Attribute) for name, value in zip(state_attr_names, state): __bound_setattr(name, value) # Clearing the hash code cache on deserialization is needed # because hash codes can change from run to run. See issue # https://github.com/python-attrs/attrs/issues/482 . # Note that this code only handles setstate for slotted classes. # For dict classes, see similar code in _patch_original_class . if hash_caching_enabled: __bound_setattr(_hash_cache_field, None) # slots and frozen require __getstate__/__setstate__ to work cd["__getstate__"] = slots_getstate cd["__setstate__"] = slots_setstate # Create new class based on old class and our methods. cls = type(self._cls)(self._cls.__name__, self._cls.__bases__, cd) # The following is a fix for # https://github.com/python-attrs/attrs/issues/102. On Python 3, # if a method mentions `__class__` or uses the no-arg super(), the # compiler will bake a reference to the class in the method itself # as `method.__closure__`. Since we replace the class with a # clone, we rewrite these references so it keeps working. for item in cls.__dict__.values(): if isinstance(item, (classmethod, staticmethod)): # Class- and staticmethods hide their functions inside. # These might need to be rewritten as well. closure_cells = getattr(item.__func__, "__closure__", None) else: closure_cells = getattr(item, "__closure__", None) if not closure_cells: # Catch None or the empty list. continue for cell in closure_cells: if cell.cell_contents is self._cls: set_closure_cell(cell, cls) return cls def add_repr(self, ns): self._cls_dict["__repr__"] = self._add_method_dunders( _make_repr(self._attrs, ns=ns) ) return self def add_str(self): repr = self._cls_dict.get("__repr__") if repr is None: raise ValueError( "__str__ can only be generated if a __repr__ exists." ) def __str__(self): return self.__repr__() self._cls_dict["__str__"] = self._add_method_dunders(__str__) return self def make_unhashable(self): self._cls_dict["__hash__"] = None return self def add_hash(self): self._cls_dict["__hash__"] = self._add_method_dunders( _make_hash( self._cls, self._attrs, frozen=self._frozen, cache_hash=self._cache_hash, ) ) return self def add_init(self): self._cls_dict["__init__"] = self._add_method_dunders( _make_init( self._cls, self._attrs, self._has_post_init, self._frozen, self._slots, self._cache_hash, self._base_attr_map, self._is_exc, ) ) return self def add_eq(self): cd = self._cls_dict cd["__eq__"], cd["__ne__"] = ( self._add_method_dunders(meth) for meth in _make_eq(self._cls, self._attrs) ) return self def add_order(self): cd = self._cls_dict cd["__lt__"], cd["__le__"], cd["__gt__"], cd["__ge__"] = ( self._add_method_dunders(meth) for meth in _make_order(self._cls, self._attrs) ) return self def _add_method_dunders(self, method): """ Add __module__ and __qualname__ to a *method* if possible. """ try: method.__module__ = self._cls.__module__ except AttributeError: pass try: method.__qualname__ = ".".join( (self._cls.__qualname__, method.__name__) ) except AttributeError: pass return method _CMP_DEPRECATION = ( "The usage of `cmp` is deprecated and will be removed on or after " "2021-06-01. Please use `eq` and `order` instead." ) def _determine_eq_order(cmp, eq, order): """ Validate the combination of *cmp*, *eq*, and *order*. Derive the effective values of eq and order. """ if cmp is not None and any((eq is not None, order is not None)): raise ValueError("Don't mix `cmp` with `eq' and `order`.") # cmp takes precedence due to bw-compatibility. if cmp is not None: warnings.warn(_CMP_DEPRECATION, DeprecationWarning, stacklevel=3) return cmp, cmp # If left None, equality is on and ordering mirrors equality. if eq is None: eq = True if order is None: order = eq if eq is False and order is True: raise ValueError("`order` can only be True if `eq` is True too.") return eq, order def attrs( maybe_cls=None, these=None, repr_ns=None, repr=True, cmp=None, hash=None, init=True, slots=False, frozen=False, weakref_slot=True, str=False, auto_attribs=False, kw_only=False, cache_hash=False, auto_exc=False, eq=None, order=None, ): r""" A class decorator that adds `dunder `_\ -methods according to the specified attributes using `attr.ib` or the *these* argument. :param these: A dictionary of name to `attr.ib` mappings. This is useful to avoid the definition of your attributes within the class body because you can't (e.g. if you want to add ``__repr__`` methods to Django models) or don't want to. If *these* is not ``None``, ``attrs`` will *not* search the class body for attributes and will *not* remove any attributes from it. If *these* is an ordered dict (`dict` on Python 3.6+, `collections.OrderedDict` otherwise), the order is deduced from the order of the attributes inside *these*. Otherwise the order of the definition of the attributes is used. :type these: `dict` of `str` to `attr.ib` :param str repr_ns: When using nested classes, there's no way in Python 2 to automatically detect that. Therefore it's possible to set the namespace explicitly for a more meaningful ``repr`` output. :param bool repr: Create a ``__repr__`` method with a human readable representation of ``attrs`` attributes.. :param bool str: Create a ``__str__`` method that is identical to ``__repr__``. This is usually not necessary except for `Exception`\ s. :param bool eq: If ``True`` or ``None`` (default), add ``__eq__`` and ``__ne__`` methods that check two instances for equality. They compare the instances as if they were tuples of their ``attrs`` attributes, but only iff the types of both classes are *identical*! :type eq: `bool` or `None` :param bool order: If ``True``, add ``__lt__``, ``__le__``, ``__gt__``, and ``__ge__`` methods that behave like *eq* above and allow instances to be ordered. If ``None`` (default) mirror value of *eq*. :type order: `bool` or `None` :param cmp: Setting to ``True`` is equivalent to setting ``eq=True, order=True``. Deprecated in favor of *eq* and *order*, has precedence over them for backward-compatibility though. Must not be mixed with *eq* or *order*. :type cmp: `bool` or `None` :param hash: If ``None`` (default), the ``__hash__`` method is generated according how *eq* and *frozen* are set. 1. If *both* are True, ``attrs`` will generate a ``__hash__`` for you. 2. If *eq* is True and *frozen* is False, ``__hash__`` will be set to None, marking it unhashable (which it is). 3. If *eq* is False, ``__hash__`` will be left untouched meaning the ``__hash__`` method of the base class will be used (if base class is ``object``, this means it will fall back to id-based hashing.). Although not recommended, you can decide for yourself and force ``attrs`` to create one (e.g. if the class is immutable even though you didn't freeze it programmatically) by passing ``True`` or not. Both of these cases are rather special and should be used carefully. See our documentation on `hashing`, Python's documentation on `object.__hash__`, and the `GitHub issue that led to the default \ behavior `_ for more details. :type hash: ``bool`` or ``None`` :param bool init: Create a ``__init__`` method that initializes the ``attrs`` attributes. Leading underscores are stripped for the argument name. If a ``__attrs_post_init__`` method exists on the class, it will be called after the class is fully initialized. :param bool slots: Create a `slotted class ` that's more memory-efficient. :param bool frozen: Make instances immutable after initialization. If someone attempts to modify a frozen instance, `attr.exceptions.FrozenInstanceError` is raised. Please note: 1. This is achieved by installing a custom ``__setattr__`` method on your class, so you can't implement your own. 2. True immutability is impossible in Python. 3. This *does* have a minor a runtime performance `impact ` when initializing new instances. In other words: ``__init__`` is slightly slower with ``frozen=True``. 4. If a class is frozen, you cannot modify ``self`` in ``__attrs_post_init__`` or a self-written ``__init__``. You can circumvent that limitation by using ``object.__setattr__(self, "attribute_name", value)``. :param bool weakref_slot: Make instances weak-referenceable. This has no effect unless ``slots`` is also enabled. :param bool auto_attribs: If True, collect `PEP 526`_-annotated attributes (Python 3.6 and later only) from the class body. In this case, you **must** annotate every field. If ``attrs`` encounters a field that is set to an `attr.ib` but lacks a type annotation, an `attr.exceptions.UnannotatedAttributeError` is raised. Use ``field_name: typing.Any = attr.ib(...)`` if you don't want to set a type. If you assign a value to those attributes (e.g. ``x: int = 42``), that value becomes the default value like if it were passed using ``attr.ib(default=42)``. Passing an instance of `Factory` also works as expected. Attributes annotated as `typing.ClassVar`, and attributes that are neither annotated nor set to an `attr.ib` are **ignored**. .. _`PEP 526`: https://www.python.org/dev/peps/pep-0526/ :param bool kw_only: Make all attributes keyword-only (Python 3+) in the generated ``__init__`` (if ``init`` is ``False``, this parameter is ignored). :param bool cache_hash: Ensure that the object's hash code is computed only once and stored on the object. If this is set to ``True``, hashing must be either explicitly or implicitly enabled for this class. If the hash code is cached, avoid any reassignments of fields involved in hash code computation or mutations of the objects those fields point to after object creation. If such changes occur, the behavior of the object's hash code is undefined. :param bool auto_exc: If the class subclasses `BaseException` (which implicitly includes any subclass of any exception), the following happens to behave like a well-behaved Python exceptions class: - the values for *eq*, *order*, and *hash* are ignored and the instances compare and hash by the instance's ids (N.B. ``attrs`` will *not* remove existing implementations of ``__hash__`` or the equality methods. It just won't add own ones.), - all attributes that are either passed into ``__init__`` or have a default value are additionally available as a tuple in the ``args`` attribute, - the value of *str* is ignored leaving ``__str__`` to base classes. .. versionadded:: 16.0.0 *slots* .. versionadded:: 16.1.0 *frozen* .. versionadded:: 16.3.0 *str* .. versionadded:: 16.3.0 Support for ``__attrs_post_init__``. .. versionchanged:: 17.1.0 *hash* supports ``None`` as value which is also the default now. .. versionadded:: 17.3.0 *auto_attribs* .. versionchanged:: 18.1.0 If *these* is passed, no attributes are deleted from the class body. .. versionchanged:: 18.1.0 If *these* is ordered, the order is retained. .. versionadded:: 18.2.0 *weakref_slot* .. deprecated:: 18.2.0 ``__lt__``, ``__le__``, ``__gt__``, and ``__ge__`` now raise a `DeprecationWarning` if the classes compared are subclasses of each other. ``__eq`` and ``__ne__`` never tried to compared subclasses to each other. .. versionchanged:: 19.2.0 ``__lt__``, ``__le__``, ``__gt__``, and ``__ge__`` now do not consider subclasses comparable anymore. .. versionadded:: 18.2.0 *kw_only* .. versionadded:: 18.2.0 *cache_hash* .. versionadded:: 19.1.0 *auto_exc* .. deprecated:: 19.2.0 *cmp* Removal on or after 2021-06-01. .. versionadded:: 19.2.0 *eq* and *order* """ eq, order = _determine_eq_order(cmp, eq, order) def wrap(cls): if getattr(cls, "__class__", None) is None: raise TypeError("attrs only works with new-style classes.") is_exc = auto_exc is True and issubclass(cls, BaseException) builder = _ClassBuilder( cls, these, slots, frozen, weakref_slot, auto_attribs, kw_only, cache_hash, is_exc, ) if repr is True: builder.add_repr(repr_ns) if str is True: builder.add_str() if eq is True and not is_exc: builder.add_eq() if order is True and not is_exc: builder.add_order() if hash is not True and hash is not False and hash is not None: # Can't use `hash in` because 1 == True for example. raise TypeError( "Invalid value for hash. Must be True, False, or None." ) elif hash is False or (hash is None and eq is False) or is_exc: # Don't do anything. Should fall back to __object__'s __hash__ # which is by id. if cache_hash: raise TypeError( "Invalid value for cache_hash. To use hash caching," " hashing must be either explicitly or implicitly " "enabled." ) elif hash is True or (hash is None and eq is True and frozen is True): # Build a __hash__ if told so, or if it's safe. builder.add_hash() else: # Raise TypeError on attempts to hash. if cache_hash: raise TypeError( "Invalid value for cache_hash. To use hash caching," " hashing must be either explicitly or implicitly " "enabled." ) builder.make_unhashable() if init is True: builder.add_init() else: if cache_hash: raise TypeError( "Invalid value for cache_hash. To use hash caching," " init must be True." ) return builder.build_class() # maybe_cls's type depends on the usage of the decorator. It's a class # if it's used as `@attrs` but ``None`` if used as `@attrs()`. if maybe_cls is None: return wrap else: return wrap(maybe_cls) _attrs = attrs """ Internal alias so we can use it in functions that take an argument called *attrs*. """ if PY2: def _has_frozen_base_class(cls): """ Check whether *cls* has a frozen ancestor by looking at its __setattr__. """ return ( getattr(cls.__setattr__, "__module__", None) == _frozen_setattrs.__module__ and cls.__setattr__.__name__ == _frozen_setattrs.__name__ ) else: def _has_frozen_base_class(cls): """ Check whether *cls* has a frozen ancestor by looking at its __setattr__. """ return cls.__setattr__ == _frozen_setattrs def _attrs_to_tuple(obj, attrs): """ Create a tuple of all values of *obj*'s *attrs*. """ return tuple(getattr(obj, a.name) for a in attrs) def _generate_unique_filename(cls, func_name): """ Create a "filename" suitable for a function being generated. """ unique_id = uuid.uuid4() extra = "" count = 1 while True: unique_filename = "".format( func_name, cls.__module__, getattr(cls, "__qualname__", cls.__name__), extra, ) # To handle concurrency we essentially "reserve" our spot in # the linecache with a dummy line. The caller can then # set this value correctly. cache_line = (1, None, (str(unique_id),), unique_filename) if ( linecache.cache.setdefault(unique_filename, cache_line) == cache_line ): return unique_filename # Looks like this spot is taken. Try again. count += 1 extra = "-{0}".format(count) def _make_hash(cls, attrs, frozen, cache_hash): attrs = tuple( a for a in attrs if a.hash is True or (a.hash is None and a.eq is True) ) tab = " " unique_filename = _generate_unique_filename(cls, "hash") type_hash = hash(unique_filename) method_lines = ["def __hash__(self):"] def append_hash_computation_lines(prefix, indent): """ Generate the code for actually computing the hash code. Below this will either be returned directly or used to compute a value which is then cached, depending on the value of cache_hash """ method_lines.extend( [indent + prefix + "hash((", indent + " %d," % (type_hash,)] ) for a in attrs: method_lines.append(indent + " self.%s," % a.name) method_lines.append(indent + " ))") if cache_hash: method_lines.append(tab + "if self.%s is None:" % _hash_cache_field) if frozen: append_hash_computation_lines( "object.__setattr__(self, '%s', " % _hash_cache_field, tab * 2 ) method_lines.append(tab * 2 + ")") # close __setattr__ else: append_hash_computation_lines( "self.%s = " % _hash_cache_field, tab * 2 ) method_lines.append(tab + "return self.%s" % _hash_cache_field) else: append_hash_computation_lines("return ", tab) script = "\n".join(method_lines) globs = {} locs = {} bytecode = compile(script, unique_filename, "exec") eval(bytecode, globs, locs) # In order of debuggers like PDB being able to step through the code, # we add a fake linecache entry. linecache.cache[unique_filename] = ( len(script), None, script.splitlines(True), unique_filename, ) return locs["__hash__"] def _add_hash(cls, attrs): """ Add a hash method to *cls*. """ cls.__hash__ = _make_hash(cls, attrs, frozen=False, cache_hash=False) return cls def __ne__(self, other): """ Check equality and either forward a NotImplemented or return the result negated. """ result = self.__eq__(other) if result is NotImplemented: return NotImplemented return not result def _make_eq(cls, attrs): attrs = [a for a in attrs if a.eq] unique_filename = _generate_unique_filename(cls, "eq") lines = [ "def __eq__(self, other):", " if other.__class__ is not self.__class__:", " return NotImplemented", ] # We can't just do a big self.x = other.x and... clause due to # irregularities like nan == nan is false but (nan,) == (nan,) is true. if attrs: lines.append(" return (") others = [" ) == ("] for a in attrs: lines.append(" self.%s," % (a.name,)) others.append(" other.%s," % (a.name,)) lines += others + [" )"] else: lines.append(" return True") script = "\n".join(lines) globs = {} locs = {} bytecode = compile(script, unique_filename, "exec") eval(bytecode, globs, locs) # In order of debuggers like PDB being able to step through the code, # we add a fake linecache entry. linecache.cache[unique_filename] = ( len(script), None, script.splitlines(True), unique_filename, ) return locs["__eq__"], __ne__ def _make_order(cls, attrs): attrs = [a for a in attrs if a.order] def attrs_to_tuple(obj): """ Save us some typing. """ return _attrs_to_tuple(obj, attrs) def __lt__(self, other): """ Automatically created by attrs. """ if other.__class__ is self.__class__: return attrs_to_tuple(self) < attrs_to_tuple(other) return NotImplemented def __le__(self, other): """ Automatically created by attrs. """ if other.__class__ is self.__class__: return attrs_to_tuple(self) <= attrs_to_tuple(other) return NotImplemented def __gt__(self, other): """ Automatically created by attrs. """ if other.__class__ is self.__class__: return attrs_to_tuple(self) > attrs_to_tuple(other) return NotImplemented def __ge__(self, other): """ Automatically created by attrs. """ if other.__class__ is self.__class__: return attrs_to_tuple(self) >= attrs_to_tuple(other) return NotImplemented return __lt__, __le__, __gt__, __ge__ def _add_eq(cls, attrs=None): """ Add equality methods to *cls* with *attrs*. """ if attrs is None: attrs = cls.__attrs_attrs__ cls.__eq__, cls.__ne__ = _make_eq(cls, attrs) return cls _already_repring = threading.local() def _make_repr(attrs, ns): """ Make a repr method that includes relevant *attrs*, adding *ns* to the full name. """ # Figure out which attributes to include, and which function to use to # format them. The a.repr value can be either bool or a custom callable. attr_names_with_reprs = tuple( (a.name, repr if a.repr is True else a.repr) for a in attrs if a.repr is not False ) def __repr__(self): """ Automatically created by attrs. """ try: working_set = _already_repring.working_set except AttributeError: working_set = set() _already_repring.working_set = working_set if id(self) in working_set: return "..." real_cls = self.__class__ if ns is None: qualname = getattr(real_cls, "__qualname__", None) if qualname is not None: class_name = qualname.rsplit(">.", 1)[-1] else: class_name = real_cls.__name__ else: class_name = ns + "." + real_cls.__name__ # Since 'self' remains on the stack (i.e.: strongly referenced) for the # duration of this call, it's safe to depend on id(...) stability, and # not need to track the instance and therefore worry about properties # like weakref- or hash-ability. working_set.add(id(self)) try: result = [class_name, "("] first = True for name, attr_repr in attr_names_with_reprs: if first: first = False else: result.append(", ") result.extend( (name, "=", attr_repr(getattr(self, name, NOTHING))) ) return "".join(result) + ")" finally: working_set.remove(id(self)) return __repr__ def _add_repr(cls, ns=None, attrs=None): """ Add a repr method to *cls*. """ if attrs is None: attrs = cls.__attrs_attrs__ cls.__repr__ = _make_repr(attrs, ns) return cls def _make_init( cls, attrs, post_init, frozen, slots, cache_hash, base_attr_map, is_exc ): attrs = [a for a in attrs if a.init or a.default is not NOTHING] unique_filename = _generate_unique_filename(cls, "init") script, globs, annotations = _attrs_to_init_script( attrs, frozen, slots, post_init, cache_hash, base_attr_map, is_exc ) locs = {} bytecode = compile(script, unique_filename, "exec") attr_dict = dict((a.name, a) for a in attrs) globs.update({"NOTHING": NOTHING, "attr_dict": attr_dict}) if frozen is True: # Save the lookup overhead in __init__ if we need to circumvent # immutability. globs["_cached_setattr"] = _obj_setattr eval(bytecode, globs, locs) # In order of debuggers like PDB being able to step through the code, # we add a fake linecache entry. linecache.cache[unique_filename] = ( len(script), None, script.splitlines(True), unique_filename, ) __init__ = locs["__init__"] __init__.__annotations__ = annotations return __init__ def fields(cls): """ Return the tuple of ``attrs`` attributes for a class. The tuple also allows accessing the fields by their names (see below for examples). :param type cls: Class to introspect. :raise TypeError: If *cls* is not a class. :raise attr.exceptions.NotAnAttrsClassError: If *cls* is not an ``attrs`` class. :rtype: tuple (with name accessors) of `attr.Attribute` .. versionchanged:: 16.2.0 Returned tuple allows accessing the fields by name. """ if not isclass(cls): raise TypeError("Passed object must be a class.") attrs = getattr(cls, "__attrs_attrs__", None) if attrs is None: raise NotAnAttrsClassError( "{cls!r} is not an attrs-decorated class.".format(cls=cls) ) return attrs def fields_dict(cls): """ Return an ordered dictionary of ``attrs`` attributes for a class, whose keys are the attribute names. :param type cls: Class to introspect. :raise TypeError: If *cls* is not a class. :raise attr.exceptions.NotAnAttrsClassError: If *cls* is not an ``attrs`` class. :rtype: an ordered dict where keys are attribute names and values are `attr.Attribute`\\ s. This will be a `dict` if it's naturally ordered like on Python 3.6+ or an :class:`~collections.OrderedDict` otherwise. .. versionadded:: 18.1.0 """ if not isclass(cls): raise TypeError("Passed object must be a class.") attrs = getattr(cls, "__attrs_attrs__", None) if attrs is None: raise NotAnAttrsClassError( "{cls!r} is not an attrs-decorated class.".format(cls=cls) ) return ordered_dict(((a.name, a) for a in attrs)) def validate(inst): """ Validate all attributes on *inst* that have a validator. Leaves all exceptions through. :param inst: Instance of a class with ``attrs`` attributes. """ if _config._run_validators is False: return for a in fields(inst.__class__): v = a.validator if v is not None: v(inst, a, getattr(inst, a.name)) def _is_slot_cls(cls): return "__slots__" in cls.__dict__ def _is_slot_attr(a_name, base_attr_map): """ Check if the attribute name comes from a slot class. """ return a_name in base_attr_map and _is_slot_cls(base_attr_map[a_name]) def _attrs_to_init_script( attrs, frozen, slots, post_init, cache_hash, base_attr_map, is_exc ): """ Return a script of an initializer for *attrs* and a dict of globals. The globals are expected by the generated script. If *frozen* is True, we cannot set the attributes directly so we use a cached ``object.__setattr__``. """ lines = [] any_slot_ancestors = any( _is_slot_attr(a.name, base_attr_map) for a in attrs ) if frozen is True: if slots is True: lines.append( # Circumvent the __setattr__ descriptor to save one lookup per # assignment. # Note _setattr will be used again below if cache_hash is True "_setattr = _cached_setattr.__get__(self, self.__class__)" ) def fmt_setter(attr_name, value_var): return "_setattr('%(attr_name)s', %(value_var)s)" % { "attr_name": attr_name, "value_var": value_var, } def fmt_setter_with_converter(attr_name, value_var): conv_name = _init_converter_pat.format(attr_name) return "_setattr('%(attr_name)s', %(conv)s(%(value_var)s))" % { "attr_name": attr_name, "value_var": value_var, "conv": conv_name, } else: # Dict frozen classes assign directly to __dict__. # But only if the attribute doesn't come from an ancestor slot # class. # Note _inst_dict will be used again below if cache_hash is True lines.append("_inst_dict = self.__dict__") if any_slot_ancestors: lines.append( # Circumvent the __setattr__ descriptor to save one lookup # per assignment. "_setattr = _cached_setattr.__get__(self, self.__class__)" ) def fmt_setter(attr_name, value_var): if _is_slot_attr(attr_name, base_attr_map): res = "_setattr('%(attr_name)s', %(value_var)s)" % { "attr_name": attr_name, "value_var": value_var, } else: res = "_inst_dict['%(attr_name)s'] = %(value_var)s" % { "attr_name": attr_name, "value_var": value_var, } return res def fmt_setter_with_converter(attr_name, value_var): conv_name = _init_converter_pat.format(attr_name) if _is_slot_attr(attr_name, base_attr_map): tmpl = "_setattr('%(attr_name)s', %(c)s(%(value_var)s))" else: tmpl = "_inst_dict['%(attr_name)s'] = %(c)s(%(value_var)s)" return tmpl % { "attr_name": attr_name, "value_var": value_var, "c": conv_name, } else: # Not frozen. def fmt_setter(attr_name, value): return "self.%(attr_name)s = %(value)s" % { "attr_name": attr_name, "value": value, } def fmt_setter_with_converter(attr_name, value_var): conv_name = _init_converter_pat.format(attr_name) return "self.%(attr_name)s = %(conv)s(%(value_var)s)" % { "attr_name": attr_name, "value_var": value_var, "conv": conv_name, } args = [] kw_only_args = [] attrs_to_validate = [] # This is a dictionary of names to validator and converter callables. # Injecting this into __init__ globals lets us avoid lookups. names_for_globals = {} annotations = {"return": None} for a in attrs: if a.validator: attrs_to_validate.append(a) attr_name = a.name arg_name = a.name.lstrip("_") has_factory = isinstance(a.default, Factory) if has_factory and a.default.takes_self: maybe_self = "self" else: maybe_self = "" if a.init is False: if has_factory: init_factory_name = _init_factory_pat.format(a.name) if a.converter is not None: lines.append( fmt_setter_with_converter( attr_name, init_factory_name + "({0})".format(maybe_self), ) ) conv_name = _init_converter_pat.format(a.name) names_for_globals[conv_name] = a.converter else: lines.append( fmt_setter( attr_name, init_factory_name + "({0})".format(maybe_self), ) ) names_for_globals[init_factory_name] = a.default.factory else: if a.converter is not None: lines.append( fmt_setter_with_converter( attr_name, "attr_dict['{attr_name}'].default".format( attr_name=attr_name ), ) ) conv_name = _init_converter_pat.format(a.name) names_for_globals[conv_name] = a.converter else: lines.append( fmt_setter( attr_name, "attr_dict['{attr_name}'].default".format( attr_name=attr_name ), ) ) elif a.default is not NOTHING and not has_factory: arg = "{arg_name}=attr_dict['{attr_name}'].default".format( arg_name=arg_name, attr_name=attr_name ) if a.kw_only: kw_only_args.append(arg) else: args.append(arg) if a.converter is not None: lines.append(fmt_setter_with_converter(attr_name, arg_name)) names_for_globals[ _init_converter_pat.format(a.name) ] = a.converter else: lines.append(fmt_setter(attr_name, arg_name)) elif has_factory: arg = "{arg_name}=NOTHING".format(arg_name=arg_name) if a.kw_only: kw_only_args.append(arg) else: args.append(arg) lines.append( "if {arg_name} is not NOTHING:".format(arg_name=arg_name) ) init_factory_name = _init_factory_pat.format(a.name) if a.converter is not None: lines.append( " " + fmt_setter_with_converter(attr_name, arg_name) ) lines.append("else:") lines.append( " " + fmt_setter_with_converter( attr_name, init_factory_name + "({0})".format(maybe_self), ) ) names_for_globals[ _init_converter_pat.format(a.name) ] = a.converter else: lines.append(" " + fmt_setter(attr_name, arg_name)) lines.append("else:") lines.append( " " + fmt_setter( attr_name, init_factory_name + "({0})".format(maybe_self), ) ) names_for_globals[init_factory_name] = a.default.factory else: if a.kw_only: kw_only_args.append(arg_name) else: args.append(arg_name) if a.converter is not None: lines.append(fmt_setter_with_converter(attr_name, arg_name)) names_for_globals[ _init_converter_pat.format(a.name) ] = a.converter else: lines.append(fmt_setter(attr_name, arg_name)) if a.init is True and a.converter is None and a.type is not None: annotations[arg_name] = a.type if attrs_to_validate: # we can skip this if there are no validators. names_for_globals["_config"] = _config lines.append("if _config._run_validators is True:") for a in attrs_to_validate: val_name = "__attr_validator_{}".format(a.name) attr_name = "__attr_{}".format(a.name) lines.append( " {}(self, {}, self.{})".format(val_name, attr_name, a.name) ) names_for_globals[val_name] = a.validator names_for_globals[attr_name] = a if post_init: lines.append("self.__attrs_post_init__()") # because this is set only after __attrs_post_init is called, a crash # will result if post-init tries to access the hash code. This seemed # preferable to setting this beforehand, in which case alteration to # field values during post-init combined with post-init accessing the # hash code would result in silent bugs. if cache_hash: if frozen: if slots: # if frozen and slots, then _setattr defined above init_hash_cache = "_setattr('%s', %s)" else: # if frozen and not slots, then _inst_dict defined above init_hash_cache = "_inst_dict['%s'] = %s" else: init_hash_cache = "self.%s = %s" lines.append(init_hash_cache % (_hash_cache_field, "None")) # For exceptions we rely on BaseException.__init__ for proper # initialization. if is_exc: vals = ",".join("self." + a.name for a in attrs if a.init) lines.append("BaseException.__init__(self, %s)" % (vals,)) args = ", ".join(args) if kw_only_args: if PY2: raise PythonTooOldError( "Keyword-only arguments only work on Python 3 and later." ) args += "{leading_comma}*, {kw_only_args}".format( leading_comma=", " if args else "", kw_only_args=", ".join(kw_only_args), ) return ( """\ def __init__(self, {args}): {lines} """.format( args=args, lines="\n ".join(lines) if lines else "pass" ), names_for_globals, annotations, ) class Attribute(object): """ *Read-only* representation of an attribute. :attribute name: The name of the attribute. Plus *all* arguments of `attr.ib` (except for ``factory`` which is only syntactic sugar for ``default=Factory(...)``. For the version history of the fields, see `attr.ib`. """ __slots__ = ( "name", "default", "validator", "repr", "eq", "order", "hash", "init", "metadata", "type", "converter", "kw_only", ) def __init__( self, name, default, validator, repr, cmp, # XXX: unused, remove along with other cmp code. hash, init, metadata=None, type=None, converter=None, kw_only=False, eq=None, order=None, ): eq, order = _determine_eq_order(cmp, eq, order) # Cache this descriptor here to speed things up later. bound_setattr = _obj_setattr.__get__(self, Attribute) # Despite the big red warning, people *do* instantiate `Attribute` # themselves. bound_setattr("name", name) bound_setattr("default", default) bound_setattr("validator", validator) bound_setattr("repr", repr) bound_setattr("eq", eq) bound_setattr("order", order) bound_setattr("hash", hash) bound_setattr("init", init) bound_setattr("converter", converter) bound_setattr( "metadata", ( metadata_proxy(metadata) if metadata else _empty_metadata_singleton ), ) bound_setattr("type", type) bound_setattr("kw_only", kw_only) def __setattr__(self, name, value): raise FrozenInstanceError() @classmethod def from_counting_attr(cls, name, ca, type=None): # type holds the annotated value. deal with conflicts: if type is None: type = ca.type elif ca.type is not None: raise ValueError( "Type annotation and type argument cannot both be present" ) inst_dict = { k: getattr(ca, k) for k in Attribute.__slots__ if k not in ( "name", "validator", "default", "type", ) # exclude methods and deprecated alias } return cls( name=name, validator=ca._validator, default=ca._default, type=type, cmp=None, **inst_dict ) @property def cmp(self): """ Simulate the presence of a cmp attribute and warn. """ warnings.warn(_CMP_DEPRECATION, DeprecationWarning, stacklevel=2) return self.eq and self.order # Don't use attr.assoc since fields(Attribute) doesn't work def _assoc(self, **changes): """ Copy *self* and apply *changes*. """ new = copy.copy(self) new._setattrs(changes.items()) return new # Don't use _add_pickle since fields(Attribute) doesn't work def __getstate__(self): """ Play nice with pickle. """ return tuple( getattr(self, name) if name != "metadata" else dict(self.metadata) for name in self.__slots__ ) def __setstate__(self, state): """ Play nice with pickle. """ self._setattrs(zip(self.__slots__, state)) def _setattrs(self, name_values_pairs): bound_setattr = _obj_setattr.__get__(self, Attribute) for name, value in name_values_pairs: if name != "metadata": bound_setattr(name, value) else: bound_setattr( name, metadata_proxy(value) if value else _empty_metadata_singleton, ) _a = [ Attribute( name=name, default=NOTHING, validator=None, repr=True, cmp=None, eq=True, order=False, hash=(name != "metadata"), init=True, ) for name in Attribute.__slots__ ] Attribute = _add_hash( _add_eq(_add_repr(Attribute, attrs=_a), attrs=_a), attrs=[a for a in _a if a.hash], ) class _CountingAttr(object): """ Intermediate representation of attributes that uses a counter to preserve the order in which the attributes have been defined. *Internal* data structure of the attrs library. Running into is most likely the result of a bug like a forgotten `@attr.s` decorator. """ __slots__ = ( "counter", "_default", "repr", "eq", "order", "hash", "init", "metadata", "_validator", "converter", "type", "kw_only", ) __attrs_attrs__ = tuple( Attribute( name=name, default=NOTHING, validator=None, repr=True, cmp=None, hash=True, init=True, kw_only=False, eq=True, order=False, ) for name in ( "counter", "_default", "repr", "eq", "order", "hash", "init", ) ) + ( Attribute( name="metadata", default=None, validator=None, repr=True, cmp=None, hash=False, init=True, kw_only=False, eq=True, order=False, ), ) cls_counter = 0 def __init__( self, default, validator, repr, cmp, # XXX: unused, remove along with cmp hash, init, converter, metadata, type, kw_only, eq, order, ): _CountingAttr.cls_counter += 1 self.counter = _CountingAttr.cls_counter self._default = default # If validator is a list/tuple, wrap it using helper validator. if validator and isinstance(validator, (list, tuple)): self._validator = and_(*validator) else: self._validator = validator self.repr = repr self.eq = eq self.order = order self.hash = hash self.init = init self.converter = converter self.metadata = metadata self.type = type self.kw_only = kw_only def validator(self, meth): """ Decorator that adds *meth* to the list of validators. Returns *meth* unchanged. .. versionadded:: 17.1.0 """ if self._validator is None: self._validator = meth else: self._validator = and_(self._validator, meth) return meth def default(self, meth): """ Decorator that allows to set the default for an attribute. Returns *meth* unchanged. :raises DefaultAlreadySetError: If default has been set before. .. versionadded:: 17.1.0 """ if self._default is not NOTHING: raise DefaultAlreadySetError() self._default = Factory(meth, takes_self=True) return meth _CountingAttr = _add_eq(_add_repr(_CountingAttr)) @attrs(slots=True, init=False, hash=True) class Factory(object): """ Stores a factory callable. If passed as the default value to `attr.ib`, the factory is used to generate a new value. :param callable factory: A callable that takes either none or exactly one mandatory positional argument depending on *takes_self*. :param bool takes_self: Pass the partially initialized instance that is being initialized as a positional argument. .. versionadded:: 17.1.0 *takes_self* """ factory = attrib() takes_self = attrib() def __init__(self, factory, takes_self=False): """ `Factory` is part of the default machinery so if we want a default value here, we have to implement it ourselves. """ self.factory = factory self.takes_self = takes_self def make_class(name, attrs, bases=(object,), **attributes_arguments): """ A quick way to create a new class called *name* with *attrs*. :param name: The name for the new class. :type name: str :param attrs: A list of names or a dictionary of mappings of names to attributes. If *attrs* is a list or an ordered dict (`dict` on Python 3.6+, `collections.OrderedDict` otherwise), the order is deduced from the order of the names or attributes inside *attrs*. Otherwise the order of the definition of the attributes is used. :type attrs: `list` or `dict` :param tuple bases: Classes that the new class will subclass. :param attributes_arguments: Passed unmodified to `attr.s`. :return: A new class with *attrs*. :rtype: type .. versionadded:: 17.1.0 *bases* .. versionchanged:: 18.1.0 If *attrs* is ordered, the order is retained. """ if isinstance(attrs, dict): cls_dict = attrs elif isinstance(attrs, (list, tuple)): cls_dict = dict((a, attrib()) for a in attrs) else: raise TypeError("attrs argument must be a dict or a list.") post_init = cls_dict.pop("__attrs_post_init__", None) type_ = type( name, bases, {} if post_init is None else {"__attrs_post_init__": post_init}, ) # For pickling to work, the __module__ variable needs to be set to the # frame where the class is created. Bypass this step in environments where # sys._getframe is not defined (Jython for example) or sys._getframe is not # defined for arguments greater than 0 (IronPython). try: type_.__module__ = sys._getframe(1).f_globals.get( "__name__", "__main__" ) except (AttributeError, ValueError): pass # We do it here for proper warnings with meaningful stacklevel. cmp = attributes_arguments.pop("cmp", None) attributes_arguments["eq"], attributes_arguments[ "order" ] = _determine_eq_order( cmp, attributes_arguments.get("eq"), attributes_arguments.get("order") ) return _attrs(these=cls_dict, **attributes_arguments)(type_) # These are required by within this module so we define them here and merely # import into .validators. @attrs(slots=True, hash=True) class _AndValidator(object): """ Compose many validators to a single one. """ _validators = attrib() def __call__(self, inst, attr, value): for v in self._validators: v(inst, attr, value) def and_(*validators): """ A validator that composes multiple validators into one. When called on a value, it runs all wrapped validators. :param validators: Arbitrary number of validators. :type validators: callables .. versionadded:: 17.1.0 """ vals = [] for validator in validators: vals.extend( validator._validators if isinstance(validator, _AndValidator) else [validator] ) return _AndValidator(tuple(vals)) ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/attr/_version_info.py ================================================ from __future__ import absolute_import, division, print_function from functools import total_ordering from ._funcs import astuple from ._make import attrib, attrs @total_ordering @attrs(eq=False, order=False, slots=True, frozen=True) class VersionInfo(object): """ A version object that can be compared to tuple of length 1--4: >>> attr.VersionInfo(19, 1, 0, "final") <= (19, 2) True >>> attr.VersionInfo(19, 1, 0, "final") < (19, 1, 1) True >>> vi = attr.VersionInfo(19, 2, 0, "final") >>> vi < (19, 1, 1) False >>> vi < (19,) False >>> vi == (19, 2,) True >>> vi == (19, 2, 1) False .. versionadded:: 19.2 """ year = attrib(type=int) minor = attrib(type=int) micro = attrib(type=int) releaselevel = attrib(type=str) @classmethod def _from_version_string(cls, s): """ Parse *s* and return a _VersionInfo. """ v = s.split(".") if len(v) == 3: v.append("final") return cls( year=int(v[0]), minor=int(v[1]), micro=int(v[2]), releaselevel=v[3] ) def _ensure_tuple(self, other): """ Ensure *other* is a tuple of a valid length. Returns a possibly transformed *other* and ourselves as a tuple of the same length as *other*. """ if self.__class__ is other.__class__: other = astuple(other) if not isinstance(other, tuple): raise NotImplementedError if not (1 <= len(other) <= 4): raise NotImplementedError return astuple(self)[: len(other)], other def __eq__(self, other): try: us, them = self._ensure_tuple(other) except NotImplementedError: return NotImplemented return us == them def __lt__(self, other): try: us, them = self._ensure_tuple(other) except NotImplementedError: return NotImplemented # Since alphabetically "dev0" < "final" < "post1" < "post2", we don't # have to do anything special with releaselevel for now. return us < them ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/attr/_version_info.pyi ================================================ class VersionInfo: @property def year(self) -> int: ... @property def minor(self) -> int: ... @property def micro(self) -> int: ... @property def releaselevel(self) -> str: ... ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/attr/converters.py ================================================ """ Commonly useful converters. """ from __future__ import absolute_import, division, print_function from ._make import NOTHING, Factory def optional(converter): """ A converter that allows an attribute to be optional. An optional attribute is one which can be set to ``None``. :param callable converter: the converter that is used for non-``None`` values. .. versionadded:: 17.1.0 """ def optional_converter(val): if val is None: return None return converter(val) return optional_converter def default_if_none(default=NOTHING, factory=None): """ A converter that allows to replace ``None`` values by *default* or the result of *factory*. :param default: Value to be used if ``None`` is passed. Passing an instance of `attr.Factory` is supported, however the ``takes_self`` option is *not*. :param callable factory: A callable that takes not parameters whose result is used if ``None`` is passed. :raises TypeError: If **neither** *default* or *factory* is passed. :raises TypeError: If **both** *default* and *factory* are passed. :raises ValueError: If an instance of `attr.Factory` is passed with ``takes_self=True``. .. versionadded:: 18.2.0 """ if default is NOTHING and factory is None: raise TypeError("Must pass either `default` or `factory`.") if default is not NOTHING and factory is not None: raise TypeError( "Must pass either `default` or `factory` but not both." ) if factory is not None: default = Factory(factory) if isinstance(default, Factory): if default.takes_self: raise ValueError( "`takes_self` is not supported by default_if_none." ) def default_if_none_converter(val): if val is not None: return val return default.factory() else: def default_if_none_converter(val): if val is not None: return val return default return default_if_none_converter ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/attr/converters.pyi ================================================ from typing import TypeVar, Optional, Callable, overload from . import _ConverterType _T = TypeVar("_T") def optional( converter: _ConverterType[_T] ) -> _ConverterType[Optional[_T]]: ... @overload def default_if_none(default: _T) -> _ConverterType[_T]: ... @overload def default_if_none(*, factory: Callable[[], _T]) -> _ConverterType[_T]: ... ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/attr/exceptions.py ================================================ from __future__ import absolute_import, division, print_function class FrozenInstanceError(AttributeError): """ A frozen/immutable instance has been attempted to be modified. It mirrors the behavior of ``namedtuples`` by using the same error message and subclassing `AttributeError`. .. versionadded:: 16.1.0 """ msg = "can't set attribute" args = [msg] class AttrsAttributeNotFoundError(ValueError): """ An ``attrs`` function couldn't find an attribute that the user asked for. .. versionadded:: 16.2.0 """ class NotAnAttrsClassError(ValueError): """ A non-``attrs`` class has been passed into an ``attrs`` function. .. versionadded:: 16.2.0 """ class DefaultAlreadySetError(RuntimeError): """ A default has been set using ``attr.ib()`` and is attempted to be reset using the decorator. .. versionadded:: 17.1.0 """ class UnannotatedAttributeError(RuntimeError): """ A class with ``auto_attribs=True`` has an ``attr.ib()`` without a type annotation. .. versionadded:: 17.3.0 """ class PythonTooOldError(RuntimeError): """ An ``attrs`` feature requiring a more recent python version has been used. .. versionadded:: 18.2.0 """ class NotCallableError(TypeError): """ A ``attr.ib()`` requiring a callable has been set with a value that is not callable. .. versionadded:: 19.2.0 """ def __init__(self, msg, value): super(TypeError, self).__init__(msg, value) self.msg = msg self.value = value def __str__(self): return str(self.msg) ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/attr/exceptions.pyi ================================================ from typing import Any class FrozenInstanceError(AttributeError): msg: str = ... class AttrsAttributeNotFoundError(ValueError): ... class NotAnAttrsClassError(ValueError): ... class DefaultAlreadySetError(RuntimeError): ... class UnannotatedAttributeError(RuntimeError): ... class PythonTooOldError(RuntimeError): ... class NotCallableError(TypeError): msg: str = ... value: Any = ... def __init__(self, msg: str, value: Any) -> None: ... ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/attr/filters.py ================================================ """ Commonly useful filters for `attr.asdict`. """ from __future__ import absolute_import, division, print_function from ._compat import isclass from ._make import Attribute def _split_what(what): """ Returns a tuple of `frozenset`s of classes and attributes. """ return ( frozenset(cls for cls in what if isclass(cls)), frozenset(cls for cls in what if isinstance(cls, Attribute)), ) def include(*what): """ Whitelist *what*. :param what: What to whitelist. :type what: `list` of `type` or `attr.Attribute`\\ s :rtype: `callable` """ cls, attrs = _split_what(what) def include_(attribute, value): return value.__class__ in cls or attribute in attrs return include_ def exclude(*what): """ Blacklist *what*. :param what: What to blacklist. :type what: `list` of classes or `attr.Attribute`\\ s. :rtype: `callable` """ cls, attrs = _split_what(what) def exclude_(attribute, value): return value.__class__ not in cls and attribute not in attrs return exclude_ ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/attr/filters.pyi ================================================ from typing import Union, Any from . import Attribute, _FilterType def include(*what: Union[type, Attribute[Any]]) -> _FilterType[Any]: ... def exclude(*what: Union[type, Attribute[Any]]) -> _FilterType[Any]: ... ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/attr/py.typed ================================================ ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/attr/validators.py ================================================ """ Commonly useful validators. """ from __future__ import absolute_import, division, print_function import re from ._make import _AndValidator, and_, attrib, attrs from .exceptions import NotCallableError __all__ = [ "and_", "deep_iterable", "deep_mapping", "in_", "instance_of", "is_callable", "matches_re", "optional", "provides", ] @attrs(repr=False, slots=True, hash=True) class _InstanceOfValidator(object): type = attrib() def __call__(self, inst, attr, value): """ We use a callable class to be able to change the ``__repr__``. """ if not isinstance(value, self.type): raise TypeError( "'{name}' must be {type!r} (got {value!r} that is a " "{actual!r}).".format( name=attr.name, type=self.type, actual=value.__class__, value=value, ), attr, self.type, value, ) def __repr__(self): return "".format( type=self.type ) def instance_of(type): """ A validator that raises a `TypeError` if the initializer is called with a wrong type for this particular attribute (checks are performed using `isinstance` therefore it's also valid to pass a tuple of types). :param type: The type to check for. :type type: type or tuple of types :raises TypeError: With a human readable error message, the attribute (of type `attr.Attribute`), the expected type, and the value it got. """ return _InstanceOfValidator(type) @attrs(repr=False, frozen=True) class _MatchesReValidator(object): regex = attrib() flags = attrib() match_func = attrib() def __call__(self, inst, attr, value): """ We use a callable class to be able to change the ``__repr__``. """ if not self.match_func(value): raise ValueError( "'{name}' must match regex {regex!r}" " ({value!r} doesn't)".format( name=attr.name, regex=self.regex.pattern, value=value ), attr, self.regex, value, ) def __repr__(self): return "".format( regex=self.regex ) def matches_re(regex, flags=0, func=None): r""" A validator that raises `ValueError` if the initializer is called with a string that doesn't match *regex*. :param str regex: a regex string to match against :param int flags: flags that will be passed to the underlying re function (default 0) :param callable func: which underlying `re` function to call (options are `re.fullmatch`, `re.search`, `re.match`, default is ``None`` which means either `re.fullmatch` or an emulation of it on Python 2). For performance reasons, they won't be used directly but on a pre-`re.compile`\ ed pattern. .. versionadded:: 19.2.0 """ fullmatch = getattr(re, "fullmatch", None) valid_funcs = (fullmatch, None, re.search, re.match) if func not in valid_funcs: raise ValueError( "'func' must be one of %s." % ( ", ".join( sorted( e and e.__name__ or "None" for e in set(valid_funcs) ) ), ) ) pattern = re.compile(regex, flags) if func is re.match: match_func = pattern.match elif func is re.search: match_func = pattern.search else: if fullmatch: match_func = pattern.fullmatch else: pattern = re.compile(r"(?:{})\Z".format(regex), flags) match_func = pattern.match return _MatchesReValidator(pattern, flags, match_func) @attrs(repr=False, slots=True, hash=True) class _ProvidesValidator(object): interface = attrib() def __call__(self, inst, attr, value): """ We use a callable class to be able to change the ``__repr__``. """ if not self.interface.providedBy(value): raise TypeError( "'{name}' must provide {interface!r} which {value!r} " "doesn't.".format( name=attr.name, interface=self.interface, value=value ), attr, self.interface, value, ) def __repr__(self): return "".format( interface=self.interface ) def provides(interface): """ A validator that raises a `TypeError` if the initializer is called with an object that does not provide the requested *interface* (checks are performed using ``interface.providedBy(value)`` (see `zope.interface `_). :param zope.interface.Interface interface: The interface to check for. :raises TypeError: With a human readable error message, the attribute (of type `attr.Attribute`), the expected interface, and the value it got. """ return _ProvidesValidator(interface) @attrs(repr=False, slots=True, hash=True) class _OptionalValidator(object): validator = attrib() def __call__(self, inst, attr, value): if value is None: return self.validator(inst, attr, value) def __repr__(self): return "".format( what=repr(self.validator) ) def optional(validator): """ A validator that makes an attribute optional. An optional attribute is one which can be set to ``None`` in addition to satisfying the requirements of the sub-validator. :param validator: A validator (or a list of validators) that is used for non-``None`` values. :type validator: callable or `list` of callables. .. versionadded:: 15.1.0 .. versionchanged:: 17.1.0 *validator* can be a list of validators. """ if isinstance(validator, list): return _OptionalValidator(_AndValidator(validator)) return _OptionalValidator(validator) @attrs(repr=False, slots=True, hash=True) class _InValidator(object): options = attrib() def __call__(self, inst, attr, value): try: in_options = value in self.options except TypeError: # e.g. `1 in "abc"` in_options = False if not in_options: raise ValueError( "'{name}' must be in {options!r} (got {value!r})".format( name=attr.name, options=self.options, value=value ) ) def __repr__(self): return "".format( options=self.options ) def in_(options): """ A validator that raises a `ValueError` if the initializer is called with a value that does not belong in the options provided. The check is performed using ``value in options``. :param options: Allowed options. :type options: list, tuple, `enum.Enum`, ... :raises ValueError: With a human readable error message, the attribute (of type `attr.Attribute`), the expected options, and the value it got. .. versionadded:: 17.1.0 """ return _InValidator(options) @attrs(repr=False, slots=False, hash=True) class _IsCallableValidator(object): def __call__(self, inst, attr, value): """ We use a callable class to be able to change the ``__repr__``. """ if not callable(value): message = ( "'{name}' must be callable " "(got {value!r} that is a {actual!r})." ) raise NotCallableError( msg=message.format( name=attr.name, value=value, actual=value.__class__ ), value=value, ) def __repr__(self): return "" def is_callable(): """ A validator that raises a `attr.exceptions.NotCallableError` if the initializer is called with a value for this particular attribute that is not callable. .. versionadded:: 19.1.0 :raises `attr.exceptions.NotCallableError`: With a human readable error message containing the attribute (`attr.Attribute`) name, and the value it got. """ return _IsCallableValidator() @attrs(repr=False, slots=True, hash=True) class _DeepIterable(object): member_validator = attrib(validator=is_callable()) iterable_validator = attrib( default=None, validator=optional(is_callable()) ) def __call__(self, inst, attr, value): """ We use a callable class to be able to change the ``__repr__``. """ if self.iterable_validator is not None: self.iterable_validator(inst, attr, value) for member in value: self.member_validator(inst, attr, member) def __repr__(self): iterable_identifier = ( "" if self.iterable_validator is None else " {iterable!r}".format(iterable=self.iterable_validator) ) return ( "" ).format( iterable_identifier=iterable_identifier, member=self.member_validator, ) def deep_iterable(member_validator, iterable_validator=None): """ A validator that performs deep validation of an iterable. :param member_validator: Validator to apply to iterable members :param iterable_validator: Validator to apply to iterable itself (optional) .. versionadded:: 19.1.0 :raises TypeError: if any sub-validators fail """ return _DeepIterable(member_validator, iterable_validator) @attrs(repr=False, slots=True, hash=True) class _DeepMapping(object): key_validator = attrib(validator=is_callable()) value_validator = attrib(validator=is_callable()) mapping_validator = attrib(default=None, validator=optional(is_callable())) def __call__(self, inst, attr, value): """ We use a callable class to be able to change the ``__repr__``. """ if self.mapping_validator is not None: self.mapping_validator(inst, attr, value) for key in value: self.key_validator(inst, attr, key) self.value_validator(inst, attr, value[key]) def __repr__(self): return ( "" ).format(key=self.key_validator, value=self.value_validator) def deep_mapping(key_validator, value_validator, mapping_validator=None): """ A validator that performs deep validation of a dictionary. :param key_validator: Validator to apply to dictionary keys :param value_validator: Validator to apply to dictionary values :param mapping_validator: Validator to apply to top-level mapping attribute (optional) .. versionadded:: 19.1.0 :raises TypeError: if any sub-validators fail """ return _DeepMapping(key_validator, value_validator, mapping_validator) ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/attr/validators.pyi ================================================ from typing import ( Container, List, Union, TypeVar, Type, Any, Optional, Tuple, Iterable, Mapping, Callable, Match, AnyStr, overload, ) from . import _ValidatorType _T = TypeVar("_T") _T1 = TypeVar("_T1") _T2 = TypeVar("_T2") _T3 = TypeVar("_T3") _I = TypeVar("_I", bound=Iterable) _K = TypeVar("_K") _V = TypeVar("_V") _M = TypeVar("_M", bound=Mapping) # To be more precise on instance_of use some overloads. # If there are more than 3 items in the tuple then we fall back to Any @overload def instance_of(type: Type[_T]) -> _ValidatorType[_T]: ... @overload def instance_of(type: Tuple[Type[_T]]) -> _ValidatorType[_T]: ... @overload def instance_of( type: Tuple[Type[_T1], Type[_T2]] ) -> _ValidatorType[Union[_T1, _T2]]: ... @overload def instance_of( type: Tuple[Type[_T1], Type[_T2], Type[_T3]] ) -> _ValidatorType[Union[_T1, _T2, _T3]]: ... @overload def instance_of(type: Tuple[type, ...]) -> _ValidatorType[Any]: ... def provides(interface: Any) -> _ValidatorType[Any]: ... def optional( validator: Union[_ValidatorType[_T], List[_ValidatorType[_T]]] ) -> _ValidatorType[Optional[_T]]: ... def in_(options: Container[_T]) -> _ValidatorType[_T]: ... def and_(*validators: _ValidatorType[_T]) -> _ValidatorType[_T]: ... def matches_re( regex: AnyStr, flags: int = ..., func: Optional[ Callable[[AnyStr, AnyStr, int], Optional[Match[AnyStr]]] ] = ..., ) -> _ValidatorType[AnyStr]: ... def deep_iterable( member_validator: _ValidatorType[_T], iterable_validator: Optional[_ValidatorType[_I]] = ..., ) -> _ValidatorType[_I]: ... def deep_mapping( key_validator: _ValidatorType[_K], value_validator: _ValidatorType[_V], mapping_validator: Optional[_ValidatorType[_M]] = ..., ) -> _ValidatorType[_M]: ... def is_callable() -> _ValidatorType[_T]: ... ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/attrs-19.3.0.dist-info/INSTALLER ================================================ pip ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/attrs-19.3.0.dist-info/LICENSE ================================================ The MIT License (MIT) Copyright (c) 2015 Hynek Schlawack Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/attrs-19.3.0.dist-info/METADATA ================================================ Metadata-Version: 2.1 Name: attrs Version: 19.3.0 Summary: Classes Without Boilerplate Home-page: https://www.attrs.org/ Author: Hynek Schlawack Author-email: hs@ox.cx Maintainer: Hynek Schlawack Maintainer-email: hs@ox.cx License: MIT Project-URL: Documentation, https://www.attrs.org/ Project-URL: Bug Tracker, https://github.com/python-attrs/attrs/issues Project-URL: Source Code, https://github.com/python-attrs/attrs Keywords: class,attribute,boilerplate Platform: UNKNOWN Classifier: Development Status :: 5 - Production/Stable Classifier: Intended Audience :: Developers Classifier: Natural Language :: English Classifier: License :: OSI Approved :: MIT License Classifier: Operating System :: OS Independent Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 2 Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: 3.4 Classifier: Programming Language :: Python :: 3.5 Classifier: Programming Language :: Python :: 3.6 Classifier: Programming Language :: Python :: 3.7 Classifier: Programming Language :: Python :: 3.8 Classifier: Programming Language :: Python :: Implementation :: CPython Classifier: Programming Language :: Python :: Implementation :: PyPy Classifier: Topic :: Software Development :: Libraries :: Python Modules Requires-Python: >=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.* Description-Content-Type: text/x-rst Provides-Extra: azure-pipelines Requires-Dist: coverage ; extra == 'azure-pipelines' Requires-Dist: hypothesis ; extra == 'azure-pipelines' Requires-Dist: pympler ; extra == 'azure-pipelines' Requires-Dist: pytest (>=4.3.0) ; extra == 'azure-pipelines' Requires-Dist: six ; extra == 'azure-pipelines' Requires-Dist: zope.interface ; extra == 'azure-pipelines' Requires-Dist: pytest-azurepipelines ; extra == 'azure-pipelines' Provides-Extra: dev Requires-Dist: coverage ; extra == 'dev' Requires-Dist: hypothesis ; extra == 'dev' Requires-Dist: pympler ; extra == 'dev' Requires-Dist: pytest (>=4.3.0) ; extra == 'dev' Requires-Dist: six ; extra == 'dev' Requires-Dist: zope.interface ; extra == 'dev' Requires-Dist: sphinx ; extra == 'dev' Requires-Dist: pre-commit ; extra == 'dev' Provides-Extra: docs Requires-Dist: sphinx ; extra == 'docs' Requires-Dist: zope.interface ; extra == 'docs' Provides-Extra: tests Requires-Dist: coverage ; extra == 'tests' Requires-Dist: hypothesis ; extra == 'tests' Requires-Dist: pympler ; extra == 'tests' Requires-Dist: pytest (>=4.3.0) ; extra == 'tests' Requires-Dist: six ; extra == 'tests' Requires-Dist: zope.interface ; extra == 'tests' .. image:: https://www.attrs.org/en/latest/_static/attrs_logo.png :alt: attrs Logo ====================================== ``attrs``: Classes Without Boilerplate ====================================== .. image:: https://readthedocs.org/projects/attrs/badge/?version=stable :target: https://www.attrs.org/en/stable/?badge=stable :alt: Documentation Status .. image:: https://attrs.visualstudio.com/attrs/_apis/build/status/python-attrs.attrs?branchName=master :target: https://attrs.visualstudio.com/attrs/_build/latest?definitionId=1&branchName=master :alt: CI Status .. image:: https://codecov.io/github/python-attrs/attrs/branch/master/graph/badge.svg :target: https://codecov.io/github/python-attrs/attrs :alt: Test Coverage .. image:: https://img.shields.io/badge/code%20style-black-000000.svg :target: https://github.com/psf/black :alt: Code style: black .. teaser-begin ``attrs`` is the Python package that will bring back the **joy** of **writing classes** by relieving you from the drudgery of implementing object protocols (aka `dunder `_ methods). Its main goal is to help you to write **concise** and **correct** software without slowing down your code. .. -spiel-end- For that, it gives you a class decorator and a way to declaratively define the attributes on that class: .. -code-begin- .. code-block:: pycon >>> import attr >>> @attr.s ... class SomeClass(object): ... a_number = attr.ib(default=42) ... list_of_numbers = attr.ib(factory=list) ... ... def hard_math(self, another_number): ... return self.a_number + sum(self.list_of_numbers) * another_number >>> sc = SomeClass(1, [1, 2, 3]) >>> sc SomeClass(a_number=1, list_of_numbers=[1, 2, 3]) >>> sc.hard_math(3) 19 >>> sc == SomeClass(1, [1, 2, 3]) True >>> sc != SomeClass(2, [3, 2, 1]) True >>> attr.asdict(sc) {'a_number': 1, 'list_of_numbers': [1, 2, 3]} >>> SomeClass() SomeClass(a_number=42, list_of_numbers=[]) >>> C = attr.make_class("C", ["a", "b"]) >>> C("foo", "bar") C(a='foo', b='bar') After *declaring* your attributes ``attrs`` gives you: - a concise and explicit overview of the class's attributes, - a nice human-readable ``__repr__``, - a complete set of comparison methods (equality and ordering), - an initializer, - and much more, *without* writing dull boilerplate code again and again and *without* runtime performance penalties. On Python 3.6 and later, you can often even drop the calls to ``attr.ib()`` by using `type annotations `_. This gives you the power to use actual classes with actual types in your code instead of confusing ``tuple``\ s or `confusingly behaving `_ ``namedtuple``\ s. Which in turn encourages you to write *small classes* that do `one thing well `_. Never again violate the `single responsibility principle `_ just because implementing ``__init__`` et al is a painful drag. .. -testimonials- Testimonials ============ **Amber Hawkie Brown**, Twisted Release Manager and Computer Owl: Writing a fully-functional class using attrs takes me less time than writing this testimonial. **Glyph Lefkowitz**, creator of `Twisted `_, `Automat `_, and other open source software, in `The One Python Library Everyone Needs `_: I’m looking forward to is being able to program in Python-with-attrs everywhere. It exerts a subtle, but positive, design influence in all the codebases I’ve see it used in. **Kenneth Reitz**, creator of `Requests `_ (`on paper no less `_!): attrs—classes for humans. I like it. **Łukasz Langa**, creator of `Black `_, prolific Python core developer, and release manager for Python 3.8 and 3.9: I'm increasingly digging your attr.ocity. Good job! .. -end- .. -project-information- Getting Help ============ Please use the ``python-attrs`` tag on `StackOverflow `_ to get help. Answering questions of your fellow developers is also great way to help the project! Project Information =================== ``attrs`` is released under the `MIT `_ license, its documentation lives at `Read the Docs `_, the code on `GitHub `_, and the latest release on `PyPI `_. It’s rigorously tested on Python 2.7, 3.4+, and PyPy. We collect information on **third-party extensions** in our `wiki `_. Feel free to browse and add your own! If you'd like to contribute to ``attrs`` you're most welcome and we've written `a little guide `_ to get you started! Release Information =================== 19.3.0 (2019-10-15) ------------------- Changes ^^^^^^^ - Fixed ``auto_attribs`` usage when default values cannot be compared directly with ``==``, such as ``numpy`` arrays. `#585 `_ `Full changelog `_. Credits ======= ``attrs`` is written and maintained by `Hynek Schlawack `_. The development is kindly supported by `Variomedia AG `_. A full list of contributors can be found in `GitHub's overview `_. It’s the spiritual successor of `characteristic `_ and aspires to fix some of it clunkiness and unfortunate decisions. Both were inspired by Twisted’s `FancyEqMixin `_ but both are implemented using class decorators because `subclassing is bad for you `_, m’kay? ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/attrs-19.3.0.dist-info/RECORD ================================================ attr/__init__.py,sha256=ONaI-ZEGOIC7IDqH2HANgesnOxPE1m0GIRRYPPsXEHk,1349 attr/__init__.pyi,sha256=fOnMRTF00b5J23PYPF74u66UVhVzzm0KYVxzmVXHPw0,8257 attr/__pycache__/__init__.cpython-36.pyc,, attr/__pycache__/_compat.cpython-36.pyc,, attr/__pycache__/_config.cpython-36.pyc,, attr/__pycache__/_funcs.cpython-36.pyc,, attr/__pycache__/_make.cpython-36.pyc,, attr/__pycache__/_version_info.cpython-36.pyc,, attr/__pycache__/converters.cpython-36.pyc,, attr/__pycache__/exceptions.cpython-36.pyc,, attr/__pycache__/filters.cpython-36.pyc,, attr/__pycache__/validators.cpython-36.pyc,, attr/_compat.py,sha256=-pJtdtqgCg0K6rH_BWf3wKuTum58GD-WWPclQQ2SUaU,7326 attr/_config.py,sha256=_KvW0mQdH2PYjHc0YfIUaV_o2pVfM7ziMEYTxwmEhOA,514 attr/_funcs.py,sha256=unAJfNGSTOzxyFzkj7Rs3O1bfsQodmXyir9uZKen-vY,9696 attr/_make.py,sha256=HhjGhFEbnxPKuUb9hFmAjXoQGpekniw1IEF3_Z-vwCc,70807 attr/_version_info.py,sha256=azMi1lNelb3cJvvYUMXsXVbUANkRzbD5IEiaXVpeVr4,2162 attr/_version_info.pyi,sha256=x_M3L3WuB7r_ULXAWjx959udKQ4HLB8l-hsc1FDGNvk,209 attr/converters.py,sha256=5QJRYSXE8G7PW0289y_SPwvvZIcw-nJIuBlfYVdB4BQ,2141 attr/converters.pyi,sha256=wAhCoOT1MFV8t323rpD87O7bxQ8CYLTPiBQd-29BieI,351 attr/exceptions.py,sha256=hbhOa3b4W8_mRrbj3FsMTR4Bt5xzbJs5xaFTWn8s6h4,1635 attr/exceptions.pyi,sha256=4zuaJyl2axxWbqnZgxo_2oTpPNbyowEw3A4hqV5PmAc,458 attr/filters.py,sha256=weDxwATsa69T_0bPVjiM1fGsciAMQmwhY5G8Jm5BxuI,1098 attr/filters.pyi,sha256=xDpmKQlFdssgxGa5tsl1ADh_3zwAwAT4vUhd8h-8-Tk,214 attr/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 attr/validators.py,sha256=8AsxgdDgh3sGPseiUIMPGcTr6PvaDYfH3AK46tsvs8U,11460 attr/validators.pyi,sha256=vZgsJqUwrJevh4v_Hd7_RSXqDrBctE6-3AEZ7uYKodo,1868 attrs-19.3.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 attrs-19.3.0.dist-info/LICENSE,sha256=v2WaKLSSQGAvVrvfSQy-LsUJsVuY-Z17GaUsdA4yeGM,1082 attrs-19.3.0.dist-info/METADATA,sha256=WmnjYy_TftebL3pewXyGEaD4TZRrLUEHk3frEkAtqL0,9022 attrs-19.3.0.dist-info/RECORD,, attrs-19.3.0.dist-info/WHEEL,sha256=8zNYZbwQSXoB9IfXOjPfeNwvAsALAjffgk27FqvCWbo,110 attrs-19.3.0.dist-info/top_level.txt,sha256=tlRYMddkRlKPqJ96wP2_j9uEsmcNHgD2SbuWd4CzGVU,5 ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/attrs-19.3.0.dist-info/WHEEL ================================================ Wheel-Version: 1.0 Generator: bdist_wheel (0.33.6) Root-Is-Purelib: true Tag: py2-none-any Tag: py3-none-any ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/attrs-19.3.0.dist-info/top_level.txt ================================================ attr ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/automat/__init__.py ================================================ # -*- test-case-name: automat -*- from ._methodical import MethodicalMachine from ._core import NoTransition __all__ = [ 'MethodicalMachine', 'NoTransition', ] ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/automat/_core.py ================================================ # -*- test-case-name: automat._test.test_core -*- """ A core state-machine abstraction. Perhaps something that could be replaced with or integrated into machinist. """ from itertools import chain _NO_STATE = "" class NoTransition(Exception): """ A finite state machine in C{state} has no transition for C{symbol}. @param state: the finite state machine's state at the time of the illegal transition. @param symbol: the input symbol for which no transition exists. """ def __init__(self, state, symbol): self.state = state self.symbol = symbol super(Exception, self).__init__( "no transition for {} in {}".format(symbol, state) ) class Automaton(object): """ A declaration of a finite state machine. Note that this is not the machine itself; it is immutable. """ def __init__(self): """ Initialize the set of transitions and the initial state. """ self._initialState = _NO_STATE self._transitions = set() @property def initialState(self): """ Return this automaton's initial state. """ return self._initialState @initialState.setter def initialState(self, state): """ Set this automaton's initial state. Raises a ValueError if this automaton already has an initial state. """ if self._initialState is not _NO_STATE: raise ValueError( "initial state already set to {}".format(self._initialState)) self._initialState = state def addTransition(self, inState, inputSymbol, outState, outputSymbols): """ Add the given transition to the outputSymbol. Raise ValueError if there is already a transition with the same inState and inputSymbol. """ # keeping self._transitions in a flat list makes addTransition # O(n^2), but state machines don't tend to have hundreds of # transitions. for (anInState, anInputSymbol, anOutState, _) in self._transitions: if (anInState == inState and anInputSymbol == inputSymbol): raise ValueError( "already have transition from {} via {}".format(inState, inputSymbol)) self._transitions.add( (inState, inputSymbol, outState, tuple(outputSymbols)) ) def allTransitions(self): """ All transitions. """ return frozenset(self._transitions) def inputAlphabet(self): """ The full set of symbols acceptable to this automaton. """ return {inputSymbol for (inState, inputSymbol, outState, outputSymbol) in self._transitions} def outputAlphabet(self): """ The full set of symbols which can be produced by this automaton. """ return set( chain.from_iterable( outputSymbols for (inState, inputSymbol, outState, outputSymbols) in self._transitions ) ) def states(self): """ All valid states; "Q" in the mathematical description of a state machine. """ return frozenset( chain.from_iterable( (inState, outState) for (inState, inputSymbol, outState, outputSymbol) in self._transitions ) ) def outputForInput(self, inState, inputSymbol): """ A 2-tuple of (outState, outputSymbols) for inputSymbol. """ for (anInState, anInputSymbol, outState, outputSymbols) in self._transitions: if (inState, inputSymbol) == (anInState, anInputSymbol): return (outState, list(outputSymbols)) raise NoTransition(state=inState, symbol=inputSymbol) class Transitioner(object): """ The combination of a current state and an L{Automaton}. """ def __init__(self, automaton, initialState): self._automaton = automaton self._state = initialState self._tracer = None def setTrace(self, tracer): self._tracer = tracer def transition(self, inputSymbol): """ Transition between states, returning any outputs. """ outState, outputSymbols = self._automaton.outputForInput(self._state, inputSymbol) outTracer = None if self._tracer: outTracer = self._tracer(self._state._name(), inputSymbol._name(), outState._name()) self._state = outState return (outputSymbols, outTracer) ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/automat/_discover.py ================================================ import collections import inspect from automat import MethodicalMachine from twisted.python.modules import PythonModule, getModule def isOriginalLocation(attr): """ Attempt to discover if this appearance of a PythonAttribute representing a class refers to the module where that class was defined. """ sourceModule = inspect.getmodule(attr.load()) if sourceModule is None: return False currentModule = attr while not isinstance(currentModule, PythonModule): currentModule = currentModule.onObject return currentModule.name == sourceModule.__name__ def findMachinesViaWrapper(within): """ Recursively yield L{MethodicalMachine}s and their FQPNs within a L{PythonModule} or a L{twisted.python.modules.PythonAttribute} wrapper object. Note that L{PythonModule}s may refer to packages, as well. The discovery heuristic considers L{MethodicalMachine} instances that are module-level attributes or class-level attributes accessible from module scope. Machines inside nested classes will be discovered, but those returned from functions or methods will not be. @type within: L{PythonModule} or L{twisted.python.modules.PythonAttribute} @param within: Where to start the search. @return: a generator which yields FQPN, L{MethodicalMachine} pairs. """ queue = collections.deque([within]) visited = set() while queue: attr = queue.pop() value = attr.load() if isinstance(value, MethodicalMachine) and value not in visited: visited.add(value) yield attr.name, value elif (inspect.isclass(value) and isOriginalLocation(attr) and value not in visited): visited.add(value) queue.extendleft(attr.iterAttributes()) elif isinstance(attr, PythonModule) and value not in visited: visited.add(value) queue.extendleft(attr.iterAttributes()) queue.extendleft(attr.iterModules()) class InvalidFQPN(Exception): """ The given FQPN was not a dot-separated list of Python objects. """ class NoModule(InvalidFQPN): """ A prefix of the FQPN was not an importable module or package. """ class NoObject(InvalidFQPN): """ A suffix of the FQPN was not an accessible object """ def wrapFQPN(fqpn): """ Given an FQPN, retrieve the object via the global Python module namespace and wrap it with a L{PythonModule} or a L{twisted.python.modules.PythonAttribute}. """ # largely cribbed from t.p.reflect.namedAny if not fqpn: raise InvalidFQPN("FQPN was empty") components = collections.deque(fqpn.split('.')) if '' in components: raise InvalidFQPN( "name must be a string giving a '.'-separated list of Python " "identifiers, not %r" % (fqpn,)) component = components.popleft() try: module = getModule(component) except KeyError: raise NoModule(component) # find the bottom-most module while components: component = components.popleft() try: module = module[component] except KeyError: components.appendleft(component) break else: module.load() else: return module # find the bottom-most attribute attribute = module for component in components: try: attribute = next(child for child in attribute.iterAttributes() if child.name.rsplit('.', 1)[-1] == component) except StopIteration: raise NoObject('{}.{}'.format(attribute.name, component)) return attribute def findMachines(fqpn): """ Recursively yield L{MethodicalMachine}s and their FQPNs in and under the a Python object specified by an FQPN. The discovery heuristic considers L{MethodicalMachine} instances that are module-level attributes or class-level attributes accessible from module scope. Machines inside nested classes will be discovered, but those returned from functions or methods will not be. @type within: an FQPN @param within: Where to start the search. @return: a generator which yields FQPN, L{MethodicalMachine} pairs. """ return findMachinesViaWrapper(wrapFQPN(fqpn)) ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/automat/_introspection.py ================================================ """ Python introspection helpers. """ from types import CodeType as code, FunctionType as function def copycode(template, changes): names = [ "argcount", "nlocals", "stacksize", "flags", "code", "consts", "names", "varnames", "filename", "name", "firstlineno", "lnotab", "freevars", "cellvars" ] if hasattr(code, "co_kwonlyargcount"): names.insert(1, "kwonlyargcount") if hasattr(code, "co_posonlyargcount"): # PEP 570 added "positional only arguments" names.insert(1, "posonlyargcount") values = [ changes.get(name, getattr(template, "co_" + name)) for name in names ] return code(*values) def copyfunction(template, funcchanges, codechanges): names = [ "globals", "name", "defaults", "closure", ] values = [ funcchanges.get(name, getattr(template, "__" + name + "__")) for name in names ] return function(copycode(template.__code__, codechanges), *values) def preserveName(f): """ Preserve the name of the given function on the decorated function. """ def decorator(decorated): return copyfunction(decorated, dict(name=f.__name__), dict(name=f.__name__)) return decorator ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/automat/_methodical.py ================================================ # -*- test-case-name: automat._test.test_methodical -*- import collections from functools import wraps from itertools import count try: # Python 3 from inspect import getfullargspec as getArgsSpec except ImportError: # Python 2 from inspect import getargspec as getArgsSpec import attr import six from ._core import Transitioner, Automaton from ._introspection import preserveName ArgSpec = collections.namedtuple('ArgSpec', ['args', 'varargs', 'varkw', 'defaults', 'kwonlyargs', 'kwonlydefaults', 'annotations']) def _getArgSpec(func): """ Normalize inspect.ArgSpec across python versions and convert mutable attributes to immutable types. :param Callable func: A function. :return: The function's ArgSpec. :rtype: ArgSpec """ spec = getArgsSpec(func) return ArgSpec( args=tuple(spec.args), varargs=spec.varargs, varkw=spec.varkw if six.PY3 else spec.keywords, defaults=spec.defaults if spec.defaults else (), kwonlyargs=tuple(spec.kwonlyargs) if six.PY3 else (), kwonlydefaults=( tuple(spec.kwonlydefaults.items()) if spec.kwonlydefaults else () ) if six.PY3 else (), annotations=tuple(spec.annotations.items()) if six.PY3 else (), ) def _getArgNames(spec): """ Get the name of all arguments defined in a function signature. The name of * and ** arguments is normalized to "*args" and "**kwargs". :param ArgSpec spec: A function to interrogate for a signature. :return: The set of all argument names in `func`s signature. :rtype: Set[str] """ return set( spec.args + spec.kwonlyargs + (('*args',) if spec.varargs else ()) + (('**kwargs',) if spec.varkw else ()) + spec.annotations ) def _keywords_only(f): """ Decorate a function so all its arguments must be passed by keyword. A useful utility for decorators that take arguments so that they don't accidentally get passed the thing they're decorating as their first argument. Only works for methods right now. """ @wraps(f) def g(self, **kw): return f(self, **kw) return g @attr.s(frozen=True) class MethodicalState(object): """ A state for a L{MethodicalMachine}. """ machine = attr.ib(repr=False) method = attr.ib() serialized = attr.ib(repr=False) def upon(self, input, enter, outputs, collector=list): """ Declare a state transition within the :class:`automat.MethodicalMachine` associated with this :class:`automat.MethodicalState`: upon the receipt of the `input`, enter the `state`, emitting each output in `outputs`. :param MethodicalInput input: The input triggering a state transition. :param MethodicalState enter: The resulting state. :param Iterable[MethodicalOutput] outputs: The outputs to be triggered as a result of the declared state transition. :param Callable collector: The function to be used when collecting output return values. :raises TypeError: if any of the `outputs` signatures do not match the `inputs` signature. :raises ValueError: if the state transition from `self` via `input` has already been defined. """ inputArgs = _getArgNames(input.argSpec) for output in outputs: outputArgs = _getArgNames(output.argSpec) if not outputArgs.issubset(inputArgs): raise TypeError( "method {input} signature {inputSignature} " "does not match output {output} " "signature {outputSignature}".format( input=input.method.__name__, output=output.method.__name__, inputSignature=getArgsSpec(input.method), outputSignature=getArgsSpec(output.method), )) self.machine._oneTransition(self, input, enter, outputs, collector) def _name(self): return self.method.__name__ def _transitionerFromInstance(oself, symbol, automaton): """ Get a L{Transitioner} """ transitioner = getattr(oself, symbol, None) if transitioner is None: transitioner = Transitioner( automaton, automaton.initialState, ) setattr(oself, symbol, transitioner) return transitioner def _empty(): pass def _docstring(): """docstring""" def assertNoCode(inst, attribute, f): # The function body must be empty, i.e. "pass" or "return None", which # both yield the same bytecode: LOAD_CONST (None), RETURN_VALUE. We also # accept functions with only a docstring, which yields slightly different # bytecode, because the "None" is put in a different constant slot. # Unfortunately, this does not catch function bodies that return a # constant value, e.g. "return 1", because their code is identical to a # "return None". They differ in the contents of their constant table, but # checking that would require us to parse the bytecode, find the index # being returned, then making sure the table has a None at that index. if f.__code__.co_code not in (_empty.__code__.co_code, _docstring.__code__.co_code): raise ValueError("function body must be empty") def _filterArgs(args, kwargs, inputSpec, outputSpec): """ Filter out arguments that were passed to input that output won't accept. :param tuple args: The *args that input received. :param dict kwargs: The **kwargs that input received. :param ArgSpec inputSpec: The input's arg spec. :param ArgSpec outputSpec: The output's arg spec. :return: The args and kwargs that output will accept. :rtype: Tuple[tuple, dict] """ named_args = tuple(zip(inputSpec.args[1:], args)) if outputSpec.varargs: # Only return all args if the output accepts *args. return_args = args else: # Filter out arguments that don't appear # in the output's method signature. return_args = [v for n, v in named_args if n in outputSpec.args] # Get any of input's default arguments that were not passed. passed_arg_names = tuple(kwargs) for name, value in named_args: passed_arg_names += (name, value) defaults = zip(inputSpec.args[::-1], inputSpec.defaults[::-1]) full_kwargs = {n: v for n, v in defaults if n not in passed_arg_names} full_kwargs.update(kwargs) if outputSpec.varkw: # Only pass all kwargs if the output method accepts **kwargs. return_kwargs = full_kwargs else: # Filter out names that the output method does not accept. all_accepted_names = outputSpec.args[1:] + outputSpec.kwonlyargs return_kwargs = {n: v for n, v in full_kwargs.items() if n in all_accepted_names} return return_args, return_kwargs @attr.s(cmp=False, hash=False) class MethodicalInput(object): """ An input for a L{MethodicalMachine}. """ automaton = attr.ib(repr=False) method = attr.ib(validator=assertNoCode) symbol = attr.ib(repr=False) collectors = attr.ib(default=attr.Factory(dict), repr=False) argSpec = attr.ib(init=False, repr=False) @argSpec.default def _buildArgSpec(self): return _getArgSpec(self.method) def __get__(self, oself, type=None): """ Return a function that takes no arguments and returns values returned by output functions produced by the given L{MethodicalInput} in C{oself}'s current state. """ transitioner = _transitionerFromInstance(oself, self.symbol, self.automaton) @preserveName(self.method) @wraps(self.method) def doInput(*args, **kwargs): self.method(oself, *args, **kwargs) previousState = transitioner._state (outputs, outTracer) = transitioner.transition(self) collector = self.collectors[previousState] values = [] for output in outputs: if outTracer: outTracer(output._name()) a, k = _filterArgs(args, kwargs, self.argSpec, output.argSpec) value = output(oself, *a, **k) values.append(value) return collector(values) return doInput def _name(self): return self.method.__name__ @attr.s(frozen=True) class MethodicalOutput(object): """ An output for a L{MethodicalMachine}. """ machine = attr.ib(repr=False) method = attr.ib() argSpec = attr.ib(init=False, repr=False) @argSpec.default def _buildArgSpec(self): return _getArgSpec(self.method) def __get__(self, oself, type=None): """ Outputs are private, so raise an exception when we attempt to get one. """ raise AttributeError( "{cls}.{method} is a state-machine output method; " "to produce this output, call an input method instead.".format( cls=type.__name__, method=self.method.__name__ ) ) def __call__(self, oself, *args, **kwargs): """ Call the underlying method. """ return self.method(oself, *args, **kwargs) def _name(self): return self.method.__name__ @attr.s(cmp=False, hash=False) class MethodicalTracer(object): automaton = attr.ib(repr=False) symbol = attr.ib(repr=False) def __get__(self, oself, type=None): transitioner = _transitionerFromInstance(oself, self.symbol, self.automaton) def setTrace(tracer): transitioner.setTrace(tracer) return setTrace counter = count() def gensym(): """ Create a unique Python identifier. """ return "_symbol_" + str(next(counter)) class MethodicalMachine(object): """ A :class:`MethodicalMachine` is an interface to an `Automaton` that uses methods on a class. """ def __init__(self): self._automaton = Automaton() self._reducers = {} self._symbol = gensym() def __get__(self, oself, type=None): """ L{MethodicalMachine} is an implementation detail for setting up class-level state; applications should never need to access it on an instance. """ if oself is not None: raise AttributeError( "MethodicalMachine is an implementation detail.") return self @_keywords_only def state(self, initial=False, terminal=False, serialized=None): """ Declare a state, possibly an initial state or a terminal state. This is a decorator for methods, but it will modify the method so as not to be callable any more. :param bool initial: is this state the initial state? Only one state on this :class:`automat.MethodicalMachine` may be an initial state; more than one is an error. :param bool terminal: Is this state a terminal state? i.e. a state that the machine can end up in? (This is purely informational at this point.) :param Hashable serialized: a serializable value to be used to represent this state to external systems. This value should be hashable; :py:func:`unicode` is a good type to use. """ def decorator(stateMethod): state = MethodicalState(machine=self, method=stateMethod, serialized=serialized) if initial: self._automaton.initialState = state return state return decorator @_keywords_only def input(self): """ Declare an input. This is a decorator for methods. """ def decorator(inputMethod): return MethodicalInput(automaton=self._automaton, method=inputMethod, symbol=self._symbol) return decorator @_keywords_only def output(self): """ Declare an output. This is a decorator for methods. This method will be called when the state machine transitions to this state as specified in the decorated `output` method. """ def decorator(outputMethod): return MethodicalOutput(machine=self, method=outputMethod) return decorator def _oneTransition(self, startState, inputToken, endState, outputTokens, collector): """ See L{MethodicalState.upon}. """ # FIXME: tests for all of this (some of it is wrong) # if not isinstance(startState, MethodicalState): # raise NotImplementedError("start state {} isn't a state" # .format(startState)) # if not isinstance(inputToken, MethodicalInput): # raise NotImplementedError("start state {} isn't an input" # .format(inputToken)) # if not isinstance(endState, MethodicalState): # raise NotImplementedError("end state {} isn't a state" # .format(startState)) # for output in outputTokens: # if not isinstance(endState, MethodicalState): # raise NotImplementedError("output state {} isn't a state" # .format(endState)) self._automaton.addTransition(startState, inputToken, endState, tuple(outputTokens)) inputToken.collectors[startState] = collector @_keywords_only def serializer(self): """ """ def decorator(decoratee): @wraps(decoratee) def serialize(oself): transitioner = _transitionerFromInstance(oself, self._symbol, self._automaton) return decoratee(oself, transitioner._state.serialized) return serialize return decorator @_keywords_only def unserializer(self): """ """ def decorator(decoratee): @wraps(decoratee) def unserialize(oself, *args, **kwargs): state = decoratee(oself, *args, **kwargs) mapping = {} for eachState in self._automaton.states(): mapping[eachState.serialized] = eachState transitioner = _transitionerFromInstance( oself, self._symbol, self._automaton) transitioner._state = mapping[state] return None # it's on purpose return unserialize return decorator @property def _setTrace(self): return MethodicalTracer(self._automaton, self._symbol) def asDigraph(self): """ Generate a L{graphviz.Digraph} that represents this machine's states and transitions. @return: L{graphviz.Digraph} object; for more information, please see the documentation for U{graphviz} """ from ._visualize import makeDigraph return makeDigraph( self._automaton, stateAsString=lambda state: state.method.__name__, inputAsString=lambda input: input.method.__name__, outputAsString=lambda output: output.method.__name__, ) ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/automat/_test/__init__.py ================================================ ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/automat/_test/test_core.py ================================================ from .._core import Automaton, NoTransition from unittest import TestCase class CoreTests(TestCase): """ Tests for Automat's (currently private, implementation detail) core. """ def test_NoTransition(self): """ A L{NoTransition} exception describes the state and input symbol that caused it. """ # NoTransition requires two arguments with self.assertRaises(TypeError): NoTransition() state = "current-state" symbol = "transitionless-symbol" noTransitionException = NoTransition(state=state, symbol=symbol) self.assertIs(noTransitionException.symbol, symbol) self.assertIn(state, str(noTransitionException)) self.assertIn(symbol, str(noTransitionException)) def test_noOutputForInput(self): """ L{Automaton.outputForInput} raises L{NoTransition} if no transition for that input is defined. """ a = Automaton() self.assertRaises(NoTransition, a.outputForInput, "no-state", "no-symbol") def test_oneTransition(self): """ L{Automaton.addTransition} adds its input symbol to L{Automaton.inputAlphabet}, all its outputs to L{Automaton.outputAlphabet}, and causes L{Automaton.outputForInput} to start returning the new state and output symbols. """ a = Automaton() a.addTransition("beginning", "begin", "ending", ["end"]) self.assertEqual(a.inputAlphabet(), {"begin"}) self.assertEqual(a.outputAlphabet(), {"end"}) self.assertEqual(a.outputForInput("beginning", "begin"), ("ending", ["end"])) self.assertEqual(a.states(), {"beginning", "ending"}) def test_oneTransition_nonIterableOutputs(self): """ L{Automaton.addTransition} raises a TypeError when given outputs that aren't iterable and doesn't add any transitions. """ a = Automaton() nonIterableOutputs = 1 self.assertRaises( TypeError, a.addTransition, "fromState", "viaSymbol", "toState", nonIterableOutputs) self.assertFalse(a.inputAlphabet()) self.assertFalse(a.outputAlphabet()) self.assertFalse(a.states()) self.assertFalse(a.allTransitions()) def test_initialState(self): """ L{Automaton.initialState} is a descriptor that sets the initial state if it's not yet set, and raises L{ValueError} if it is. """ a = Automaton() a.initialState = "a state" self.assertEqual(a.initialState, "a state") with self.assertRaises(ValueError): a.initialState = "another state" # FIXME: addTransition for transition that's been added before ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/automat/_test/test_discover.py ================================================ import operator import os import shutil import sys import textwrap import tempfile from unittest import skipIf, TestCase import six def isTwistedInstalled(): try: __import__('twisted') except ImportError: return False else: return True class _WritesPythonModules(TestCase): """ A helper that enables generating Python module test fixtures. """ def setUp(self): super(_WritesPythonModules, self).setUp() from twisted.python.modules import getModule, PythonPath from twisted.python.filepath import FilePath self.getModule = getModule self.PythonPath = PythonPath self.FilePath = FilePath self.originalSysModules = set(sys.modules.keys()) self.savedSysPath = sys.path[:] self.pathDir = tempfile.mkdtemp() self.makeImportable(self.pathDir) def tearDown(self): super(_WritesPythonModules, self).tearDown() sys.path[:] = self.savedSysPath modulesToDelete = six.viewkeys(sys.modules) - self.originalSysModules for module in modulesToDelete: del sys.modules[module] shutil.rmtree(self.pathDir) def makeImportable(self, path): sys.path.append(path) def writeSourceInto(self, source, path, moduleName): directory = self.FilePath(path) module = directory.child(moduleName) # FilePath always opens a file in binary mode - but that will # break on Python 3 with open(module.path, 'w') as f: f.write(textwrap.dedent(source)) return self.PythonPath([directory.path]) def makeModule(self, source, path, moduleName): pythonModuleName, _ = os.path.splitext(moduleName) return self.writeSourceInto(source, path, moduleName)[pythonModuleName] def attributesAsDict(self, hasIterAttributes): return {attr.name: attr for attr in hasIterAttributes.iterAttributes()} def loadModuleAsDict(self, module): module.load() return self.attributesAsDict(module) def makeModuleAsDict(self, source, path, name): return self.loadModuleAsDict(self.makeModule(source, path, name)) @skipIf(not isTwistedInstalled(), "Twisted is not installed.") class OriginalLocationTests(_WritesPythonModules): """ Tests that L{isOriginalLocation} detects when a L{PythonAttribute}'s FQPN refers to an object inside the module where it was defined. For example: A L{twisted.python.modules.PythonAttribute} with a name of 'foo.bar' that refers to a 'bar' object defined in module 'baz' does *not* refer to bar's original location, while a L{PythonAttribute} with a name of 'baz.bar' does. """ def setUp(self): super(OriginalLocationTests, self).setUp() from .._discover import isOriginalLocation self.isOriginalLocation = isOriginalLocation def test_failsWithNoModule(self): """ L{isOriginalLocation} returns False when the attribute refers to an object whose source module cannot be determined. """ source = """\ class Fake(object): pass hasEmptyModule = Fake() hasEmptyModule.__module__ = None """ moduleDict = self.makeModuleAsDict(source, self.pathDir, 'empty_module_attr.py') self.assertFalse(self.isOriginalLocation( moduleDict['empty_module_attr.hasEmptyModule'])) def test_failsWithDifferentModule(self): """ L{isOriginalLocation} returns False when the attribute refers to an object outside of the module where that object was defined. """ originalSource = """\ class ImportThisClass(object): pass importThisObject = ImportThisClass() importThisNestingObject = ImportThisClass() importThisNestingObject.nestedObject = ImportThisClass() """ importingSource = """\ from original import (ImportThisClass, importThisObject, importThisNestingObject) """ self.makeModule(originalSource, self.pathDir, 'original.py') importingDict = self.makeModuleAsDict(importingSource, self.pathDir, 'importing.py') self.assertFalse( self.isOriginalLocation( importingDict['importing.ImportThisClass'])) self.assertFalse( self.isOriginalLocation( importingDict['importing.importThisObject'])) nestingObject = importingDict['importing.importThisNestingObject'] nestingObjectDict = self.attributesAsDict(nestingObject) nestedObject = nestingObjectDict[ 'importing.importThisNestingObject.nestedObject'] self.assertFalse(self.isOriginalLocation(nestedObject)) def test_succeedsWithSameModule(self): """ L{isOriginalLocation} returns True when the attribute refers to an object inside the module where that object was defined. """ mSource = textwrap.dedent(""" class ThisClassWasDefinedHere(object): pass anObject = ThisClassWasDefinedHere() aNestingObject = ThisClassWasDefinedHere() aNestingObject.nestedObject = ThisClassWasDefinedHere() """) mDict = self.makeModuleAsDict(mSource, self.pathDir, 'm.py') self.assertTrue(self.isOriginalLocation( mDict['m.ThisClassWasDefinedHere'])) self.assertTrue(self.isOriginalLocation(mDict['m.aNestingObject'])) nestingObject = mDict['m.aNestingObject'] nestingObjectDict = self.attributesAsDict(nestingObject) nestedObject = nestingObjectDict['m.aNestingObject.nestedObject'] self.assertTrue(self.isOriginalLocation(nestedObject)) @skipIf(not isTwistedInstalled(), "Twisted is not installed.") class FindMachinesViaWrapperTests(_WritesPythonModules): """ L{findMachinesViaWrapper} recursively yields FQPN, L{MethodicalMachine} pairs in and under a given L{twisted.python.modules.PythonModule} or L{twisted.python.modules.PythonAttribute}. """ TEST_MODULE_SOURCE = """ from automat import MethodicalMachine class PythonClass(object): _classMachine = MethodicalMachine() class NestedClass(object): _nestedClassMachine = MethodicalMachine() ignoredAttribute = "I am ignored." def ignoredMethod(self): "I am also ignored." rootLevelMachine = MethodicalMachine() ignoredPythonObject = PythonClass() anotherIgnoredPythonObject = "I am ignored." """ def setUp(self): super(FindMachinesViaWrapperTests, self).setUp() from .._discover import findMachinesViaWrapper self.findMachinesViaWrapper = findMachinesViaWrapper def test_yieldsMachine(self): """ When given a L{twisted.python.modules.PythonAttribute} that refers directly to a L{MethodicalMachine}, L{findMachinesViaWrapper} yields that machine and its FQPN. """ source = """\ from automat import MethodicalMachine rootMachine = MethodicalMachine() """ moduleDict = self.makeModuleAsDict(source, self.pathDir, 'root.py') rootMachine = moduleDict['root.rootMachine'] self.assertIn(('root.rootMachine', rootMachine.load()), list(self.findMachinesViaWrapper(rootMachine))) def test_yieldsMachineInClass(self): """ When given a L{twisted.python.modules.PythonAttribute} that refers to a class that contains a L{MethodicalMachine} as a class variable, L{findMachinesViaWrapper} yields that machine and its FQPN. """ source = """\ from automat import MethodicalMachine class PythonClass(object): _classMachine = MethodicalMachine() """ moduleDict = self.makeModuleAsDict(source, self.pathDir, 'clsmod.py') PythonClass = moduleDict['clsmod.PythonClass'] self.assertIn(('clsmod.PythonClass._classMachine', PythonClass.load()._classMachine), list(self.findMachinesViaWrapper(PythonClass))) def test_yieldsMachineInNestedClass(self): """ When given a L{twisted.python.modules.PythonAttribute} that refers to a nested class that contains a L{MethodicalMachine} as a class variable, L{findMachinesViaWrapper} yields that machine and its FQPN. """ source = """\ from automat import MethodicalMachine class PythonClass(object): class NestedClass(object): _classMachine = MethodicalMachine() """ moduleDict = self.makeModuleAsDict(source, self.pathDir, 'nestedcls.py') PythonClass = moduleDict['nestedcls.PythonClass'] self.assertIn(('nestedcls.PythonClass.NestedClass._classMachine', PythonClass.load().NestedClass._classMachine), list(self.findMachinesViaWrapper(PythonClass))) def test_yieldsMachineInModule(self): """ When given a L{twisted.python.modules.PythonModule} that refers to a module that contains a L{MethodicalMachine}, L{findMachinesViaWrapper} yields that machine and its FQPN. """ source = """\ from automat import MethodicalMachine rootMachine = MethodicalMachine() """ module = self.makeModule(source, self.pathDir, 'root.py') rootMachine = self.loadModuleAsDict(module)['root.rootMachine'].load() self.assertIn(('root.rootMachine', rootMachine), list(self.findMachinesViaWrapper(module))) def test_yieldsMachineInClassInModule(self): """ When given a L{twisted.python.modules.PythonModule} that refers to the original module of a class containing a L{MethodicalMachine}, L{findMachinesViaWrapper} yields that machine and its FQPN. """ source = """\ from automat import MethodicalMachine class PythonClass(object): _classMachine = MethodicalMachine() """ module = self.makeModule(source, self.pathDir, 'clsmod.py') PythonClass = self.loadModuleAsDict( module)['clsmod.PythonClass'].load() self.assertIn(('clsmod.PythonClass._classMachine', PythonClass._classMachine), list(self.findMachinesViaWrapper(module))) def test_yieldsMachineInNestedClassInModule(self): """ When given a L{twisted.python.modules.PythonModule} that refers to the original module of a nested class containing a L{MethodicalMachine}, L{findMachinesViaWrapper} yields that machine and its FQPN. """ source = """\ from automat import MethodicalMachine class PythonClass(object): class NestedClass(object): _classMachine = MethodicalMachine() """ module = self.makeModule(source, self.pathDir, 'nestedcls.py') PythonClass = self.loadModuleAsDict( module)['nestedcls.PythonClass'].load() self.assertIn(('nestedcls.PythonClass.NestedClass._classMachine', PythonClass.NestedClass._classMachine), list(self.findMachinesViaWrapper(module))) def test_ignoresImportedClass(self): """ When given a L{twisted.python.modules.PythonAttribute} that refers to a class imported from another module, any L{MethodicalMachine}s on that class are ignored. This behavior ensures that a machine is only discovered on a class when visiting the module where that class was defined. """ originalSource = """ from automat import MethodicalMachine class PythonClass(object): _classMachine = MethodicalMachine() """ importingSource = """ from original import PythonClass """ self.makeModule(originalSource, self.pathDir, 'original.py') importingModule = self.makeModule(importingSource, self.pathDir, 'importing.py') self.assertFalse(list(self.findMachinesViaWrapper(importingModule))) def test_descendsIntoPackages(self): """ L{findMachinesViaWrapper} descends into packages to discover machines. """ pythonPath = self.PythonPath([self.pathDir]) package = self.FilePath(self.pathDir).child("test_package") package.makedirs() package.child('__init__.py').touch() source = """ from automat import MethodicalMachine class PythonClass(object): _classMachine = MethodicalMachine() rootMachine = MethodicalMachine() """ self.makeModule(source, package.path, 'module.py') test_package = pythonPath['test_package'] machines = sorted(self.findMachinesViaWrapper(test_package), key=operator.itemgetter(0)) moduleDict = self.loadModuleAsDict(test_package['module']) rootMachine = moduleDict['test_package.module.rootMachine'].load() PythonClass = moduleDict['test_package.module.PythonClass'].load() expectedMachines = sorted( [('test_package.module.rootMachine', rootMachine), ('test_package.module.PythonClass._classMachine', PythonClass._classMachine)], key=operator.itemgetter(0)) self.assertEqual(expectedMachines, machines) def test_infiniteLoop(self): """ L{findMachinesViaWrapper} ignores infinite loops. Note this test can't fail - it can only run forever! """ source = """ class InfiniteLoop(object): pass InfiniteLoop.loop = InfiniteLoop """ module = self.makeModule(source, self.pathDir, 'loop.py') self.assertFalse(list(self.findMachinesViaWrapper(module))) @skipIf(not isTwistedInstalled(), "Twisted is not installed.") class WrapFQPNTests(TestCase): """ Tests that ensure L{wrapFQPN} loads the L{twisted.python.modules.PythonModule} or L{twisted.python.modules.PythonAttribute} for a given FQPN. """ def setUp(self): from twisted.python.modules import PythonModule, PythonAttribute from .._discover import wrapFQPN, InvalidFQPN, NoModule, NoObject self.PythonModule = PythonModule self.PythonAttribute = PythonAttribute self.wrapFQPN = wrapFQPN self.InvalidFQPN = InvalidFQPN self.NoModule = NoModule self.NoObject = NoObject def assertModuleWrapperRefersTo(self, moduleWrapper, module): """ Assert that a L{twisted.python.modules.PythonModule} refers to a particular Python module. """ self.assertIsInstance(moduleWrapper, self.PythonModule) self.assertEqual(moduleWrapper.name, module.__name__) self.assertIs(moduleWrapper.load(), module) def assertAttributeWrapperRefersTo(self, attributeWrapper, fqpn, obj): """ Assert that a L{twisted.python.modules.PythonAttribute} refers to a particular Python object. """ self.assertIsInstance(attributeWrapper, self.PythonAttribute) self.assertEqual(attributeWrapper.name, fqpn) self.assertIs(attributeWrapper.load(), obj) def test_failsWithEmptyFQPN(self): """ L{wrapFQPN} raises L{InvalidFQPN} when given an empty string. """ with self.assertRaises(self.InvalidFQPN): self.wrapFQPN('') def test_failsWithBadDotting(self): """" L{wrapFQPN} raises L{InvalidFQPN} when given a badly-dotted FQPN. (e.g., x..y). """ for bad in ('.fails', 'fails.', 'this..fails'): with self.assertRaises(self.InvalidFQPN): self.wrapFQPN(bad) def test_singleModule(self): """ L{wrapFQPN} returns a L{twisted.python.modules.PythonModule} referring to the single module a dotless FQPN describes. """ import os moduleWrapper = self.wrapFQPN('os') self.assertIsInstance(moduleWrapper, self.PythonModule) self.assertIs(moduleWrapper.load(), os) def test_failsWithMissingSingleModuleOrPackage(self): """ L{wrapFQPN} raises L{NoModule} when given a dotless FQPN that does not refer to a module or package. """ with self.assertRaises(self.NoModule): self.wrapFQPN("this is not an acceptable name!") def test_singlePackage(self): """ L{wrapFQPN} returns a L{twisted.python.modules.PythonModule} referring to the single package a dotless FQPN describes. """ import xml self.assertModuleWrapperRefersTo(self.wrapFQPN('xml'), xml) def test_multiplePackages(self): """ L{wrapFQPN} returns a L{twisted.python.modules.PythonModule} referring to the deepest package described by dotted FQPN. """ import xml.etree self.assertModuleWrapperRefersTo(self.wrapFQPN('xml.etree'), xml.etree) def test_multiplePackagesFinalModule(self): """ L{wrapFQPN} returns a L{twisted.python.modules.PythonModule} referring to the deepest module described by dotted FQPN. """ import xml.etree.ElementTree self.assertModuleWrapperRefersTo( self.wrapFQPN('xml.etree.ElementTree'), xml.etree.ElementTree) def test_singleModuleObject(self): """ L{wrapFQPN} returns a L{twisted.python.modules.PythonAttribute} referring to the deepest object an FQPN names, traversing one module. """ import os self.assertAttributeWrapperRefersTo( self.wrapFQPN('os.path'), 'os.path', os.path) def test_multiplePackagesObject(self): """ L{wrapFQPN} returns a L{twisted.python.modules.PythonAttribute} referring to the deepest object described by an FQPN, descending through several packages. """ import xml.etree.ElementTree import automat for fqpn, obj in [('xml.etree.ElementTree.fromstring', xml.etree.ElementTree.fromstring), ('automat.MethodicalMachine.__doc__', automat.MethodicalMachine.__doc__)]: self.assertAttributeWrapperRefersTo( self.wrapFQPN(fqpn), fqpn, obj) def test_failsWithMultiplePackagesMissingModuleOrPackage(self): """ L{wrapFQPN} raises L{NoObject} when given an FQPN that contains a missing attribute, module, or package. """ for bad in ('xml.etree.nope!', 'xml.etree.nope!.but.the.rest.is.believable'): with self.assertRaises(self.NoObject): self.wrapFQPN(bad) @skipIf(not isTwistedInstalled(), "Twisted is not installed.") class FindMachinesIntegrationTests(_WritesPythonModules): """ Integration tests to check that L{findMachines} yields all machines discoverable at or below an FQPN. """ SOURCE = """ from automat import MethodicalMachine class PythonClass(object): _machine = MethodicalMachine() ignored = "i am ignored" rootLevel = MethodicalMachine() ignored = "i am ignored" """ def setUp(self): super(FindMachinesIntegrationTests, self).setUp() from .._discover import findMachines self.findMachines = findMachines packageDir = self.FilePath(self.pathDir).child("test_package") packageDir.makedirs() self.pythonPath = self.PythonPath([self.pathDir]) self.writeSourceInto(self.SOURCE, packageDir.path, '__init__.py') subPackageDir = packageDir.child('subpackage') subPackageDir.makedirs() subPackageDir.child('__init__.py').touch() self.makeModule(self.SOURCE, subPackageDir.path, 'module.py') self.packageDict = self.loadModuleAsDict( self.pythonPath['test_package']) self.moduleDict = self.loadModuleAsDict( self.pythonPath['test_package']['subpackage']['module']) def test_discoverAll(self): """ Given a top-level package FQPN, L{findMachines} discovers all L{MethodicalMachine} instances in and below it. """ machines = sorted(self.findMachines('test_package'), key=operator.itemgetter(0)) tpRootLevel = self.packageDict['test_package.rootLevel'].load() tpPythonClass = self.packageDict['test_package.PythonClass'].load() mRLAttr = self.moduleDict['test_package.subpackage.module.rootLevel'] mRootLevel = mRLAttr.load() mPCAttr = self.moduleDict['test_package.subpackage.module.PythonClass'] mPythonClass = mPCAttr.load() expectedMachines = sorted( [('test_package.rootLevel', tpRootLevel), ('test_package.PythonClass._machine', tpPythonClass._machine), ('test_package.subpackage.module.rootLevel', mRootLevel), ('test_package.subpackage.module.PythonClass._machine', mPythonClass._machine)], key=operator.itemgetter(0)) self.assertEqual(expectedMachines, machines) ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/automat/_test/test_methodical.py ================================================ """ Tests for the public interface of Automat. """ from functools import reduce from unittest import TestCase from automat._methodical import ArgSpec, _getArgNames, _getArgSpec, _filterArgs from .. import MethodicalMachine, NoTransition from .. import _methodical class MethodicalTests(TestCase): """ Tests for L{MethodicalMachine}. """ def test_oneTransition(self): """ L{MethodicalMachine} provides a way for you to declare a state machine with inputs, outputs, and states as methods. When you have declared an input, an output, and a state, calling the input method in that state will produce the specified output. """ class Machination(object): machine = MethodicalMachine() @machine.input() def anInput(self): "an input" @machine.output() def anOutput(self): "an output" return "an-output-value" @machine.output() def anotherOutput(self): "another output" return "another-output-value" @machine.state(initial=True) def anState(self): "a state" @machine.state() def anotherState(self): "another state" anState.upon(anInput, enter=anotherState, outputs=[anOutput]) anotherState.upon(anInput, enter=anotherState, outputs=[anotherOutput]) m = Machination() self.assertEqual(m.anInput(), ["an-output-value"]) self.assertEqual(m.anInput(), ["another-output-value"]) def test_machineItselfIsPrivate(self): """ L{MethodicalMachine} is an implementation detail. If you attempt to access it on an instance of your class, you will get an exception. However, since tools may need to access it for the purposes of, for example, visualization, you may access it on the class itself. """ expectedMachine = MethodicalMachine() class Machination(object): machine = expectedMachine machination = Machination() with self.assertRaises(AttributeError) as cm: machination.machine self.assertIn("MethodicalMachine is an implementation detail", str(cm.exception)) self.assertIs(Machination.machine, expectedMachine) def test_outputsArePrivate(self): """ One of the benefits of using a state machine is that your output method implementations don't need to take invalid state transitions into account - the methods simply won't be called. This property would be broken if client code called output methods directly, so output methods are not directly visible under their names. """ class Machination(object): machine = MethodicalMachine() counter = 0 @machine.input() def anInput(self): "an input" @machine.output() def anOutput(self): self.counter += 1 @machine.state(initial=True) def state(self): "a machine state" state.upon(anInput, enter=state, outputs=[anOutput]) mach1 = Machination() mach1.anInput() self.assertEqual(mach1.counter, 1) mach2 = Machination() with self.assertRaises(AttributeError) as cm: mach2.anOutput self.assertEqual(mach2.counter, 0) self.assertIn( "Machination.anOutput is a state-machine output method; to " "produce this output, call an input method instead.", str(cm.exception) ) def test_multipleMachines(self): """ Two machines may co-exist happily on the same instance; they don't interfere with each other. """ class MultiMach(object): a = MethodicalMachine() b = MethodicalMachine() @a.input() def inputA(self): "input A" @b.input() def inputB(self): "input B" @a.state(initial=True) def initialA(self): "initial A" @b.state(initial=True) def initialB(self): "initial B" @a.output() def outputA(self): return "A" @b.output() def outputB(self): return "B" initialA.upon(inputA, initialA, [outputA]) initialB.upon(inputB, initialB, [outputB]) mm = MultiMach() self.assertEqual(mm.inputA(), ["A"]) self.assertEqual(mm.inputB(), ["B"]) def test_collectOutputs(self): """ Outputs can be combined with the "collector" argument to "upon". """ import operator class Machine(object): m = MethodicalMachine() @m.input() def input(self): "an input" @m.output() def outputA(self): return "A" @m.output() def outputB(self): return "B" @m.state(initial=True) def state(self): "a state" state.upon(input, state, [outputA, outputB], collector=lambda x: reduce(operator.add, x)) m = Machine() self.assertEqual(m.input(), "AB") def test_methodName(self): """ Input methods preserve their declared names. """ class Mech(object): m = MethodicalMachine() @m.input() def declaredInputName(self): "an input" @m.state(initial=True) def aState(self): "state" m = Mech() with self.assertRaises(TypeError) as cm: m.declaredInputName("too", "many", "arguments") self.assertIn("declaredInputName", str(cm.exception)) def test_inputWithArguments(self): """ If an input takes an argument, it will pass that along to its output. """ class Mechanism(object): m = MethodicalMachine() @m.input() def input(self, x, y=1): "an input" @m.state(initial=True) def state(self): "a state" @m.output() def output(self, x, y=1): self._x = x return x + y state.upon(input, state, [output]) m = Mechanism() self.assertEqual(m.input(3), [4]) self.assertEqual(m._x, 3) def test_outputWithSubsetOfArguments(self): """ Inputs pass arguments that output will accept. """ class Mechanism(object): m = MethodicalMachine() @m.input() def input(self, x, y=1): "an input" @m.state(initial=True) def state(self): "a state" @m.output() def outputX(self, x): self._x = x return x @m.output() def outputY(self, y): self._y = y return y @m.output() def outputNoArgs(self): return None state.upon(input, state, [outputX, outputY, outputNoArgs]) m = Mechanism() # Pass x as positional argument. self.assertEqual(m.input(3), [3, 1, None]) self.assertEqual(m._x, 3) self.assertEqual(m._y, 1) # Pass x as key word argument. self.assertEqual(m.input(x=4), [4, 1, None]) self.assertEqual(m._x, 4) self.assertEqual(m._y, 1) # Pass y as positional argument. self.assertEqual(m.input(6, 3), [6, 3, None]) self.assertEqual(m._x, 6) self.assertEqual(m._y, 3) # Pass y as key word argument. self.assertEqual(m.input(5, y=2), [5, 2, None]) self.assertEqual(m._x, 5) self.assertEqual(m._y, 2) def test_inputFunctionsMustBeEmpty(self): """ The wrapped input function must have an empty body. """ # input functions are executed to assert that the signature matches, # but their body must be empty _methodical._empty() # chase coverage _methodical._docstring() class Mechanism(object): m = MethodicalMachine() with self.assertRaises(ValueError) as cm: @m.input() def input(self): "an input" list() # pragma: no cover self.assertEqual(str(cm.exception), "function body must be empty") # all three of these cases should be valid. Functions/methods with # docstrings produce slightly different bytecode than ones without. class MechanismWithDocstring(object): m = MethodicalMachine() @m.input() def input(self): "an input" @m.state(initial=True) def start(self): "starting state" start.upon(input, enter=start, outputs=[]) MechanismWithDocstring().input() class MechanismWithPass(object): m = MethodicalMachine() @m.input() def input(self): pass @m.state(initial=True) def start(self): "starting state" start.upon(input, enter=start, outputs=[]) MechanismWithPass().input() class MechanismWithDocstringAndPass(object): m = MethodicalMachine() @m.input() def input(self): "an input" pass @m.state(initial=True) def start(self): "starting state" start.upon(input, enter=start, outputs=[]) MechanismWithDocstringAndPass().input() class MechanismReturnsNone(object): m = MethodicalMachine() @m.input() def input(self): return None @m.state(initial=True) def start(self): "starting state" start.upon(input, enter=start, outputs=[]) MechanismReturnsNone().input() class MechanismWithDocstringAndReturnsNone(object): m = MethodicalMachine() @m.input() def input(self): "an input" return None @m.state(initial=True) def start(self): "starting state" start.upon(input, enter=start, outputs=[]) MechanismWithDocstringAndReturnsNone().input() def test_inputOutputMismatch(self): """ All the argument lists of the outputs for a given input must match; if one does not the call to C{upon} will raise a C{TypeError}. """ class Mechanism(object): m = MethodicalMachine() @m.input() def nameOfInput(self, a): "an input" @m.output() def outputThatMatches(self, a): "an output that matches" @m.output() def outputThatDoesntMatch(self, b): "an output that doesn't match" @m.state() def state(self): "a state" with self.assertRaises(TypeError) as cm: state.upon(nameOfInput, state, [outputThatMatches, outputThatDoesntMatch]) self.assertIn("nameOfInput", str(cm.exception)) self.assertIn("outputThatDoesntMatch", str(cm.exception)) def test_getArgNames(self): """ Type annotations should be included in the set of """ spec = ArgSpec( args=('a', 'b'), varargs=None, varkw=None, defaults=None, kwonlyargs=(), kwonlydefaults=None, annotations=(('a', int), ('b', str)), ) self.assertEqual( _getArgNames(spec), {'a', 'b', ('a', int), ('b', str)}, ) def test_filterArgs(self): """ filterArgs() should not filter the `args` parameter if outputSpec accepts `*args`. """ inputSpec = _getArgSpec(lambda *args, **kwargs: None) outputSpec = _getArgSpec(lambda *args, **kwargs: None) argsIn = () argsOut, _ = _filterArgs(argsIn, {}, inputSpec, outputSpec) self.assertIs(argsIn, argsOut) def test_multipleInitialStatesFailure(self): """ A L{MethodicalMachine} can only have one initial state. """ class WillFail(object): m = MethodicalMachine() @m.state(initial=True) def firstInitialState(self): "The first initial state -- this is OK." with self.assertRaises(ValueError): @m.state(initial=True) def secondInitialState(self): "The second initial state -- results in a ValueError." def test_multipleTransitionsFailure(self): """ A L{MethodicalMachine} can only have one transition per start/event pair. """ class WillFail(object): m = MethodicalMachine() @m.state(initial=True) def start(self): "We start here." @m.state() def end(self): "Rainbows end." @m.input() def event(self): "An event." start.upon(event, enter=end, outputs=[]) with self.assertRaises(ValueError): start.upon(event, enter=end, outputs=[]) def test_badTransitionForCurrentState(self): """ Calling any input method that lacks a transition for the machine's current state raises an informative L{NoTransition}. """ class OnlyOnePath(object): m = MethodicalMachine() @m.state(initial=True) def start(self): "Start state." @m.state() def end(self): "End state." @m.input() def advance(self): "Move from start to end." @m.input() def deadEnd(self): "A transition from nowhere to nowhere." start.upon(advance, end, []) machine = OnlyOnePath() with self.assertRaises(NoTransition) as cm: machine.deadEnd() self.assertIn("deadEnd", str(cm.exception)) self.assertIn("start", str(cm.exception)) machine.advance() with self.assertRaises(NoTransition) as cm: machine.deadEnd() self.assertIn("deadEnd", str(cm.exception)) self.assertIn("end", str(cm.exception)) def test_saveState(self): """ L{MethodicalMachine.serializer} is a decorator that modifies its decoratee's signature to take a "state" object as its first argument, which is the "serialized" argument to the L{MethodicalMachine.state} decorator. """ class Mechanism(object): m = MethodicalMachine() def __init__(self): self.value = 1 @m.state(serialized="first-state", initial=True) def first(self): "First state." @m.state(serialized="second-state") def second(self): "Second state." @m.serializer() def save(self, state): return { 'machine-state': state, 'some-value': self.value, } self.assertEqual( Mechanism().save(), { "machine-state": "first-state", "some-value": 1, } ) def test_restoreState(self): """ L{MethodicalMachine.unserializer} decorates a function that becomes a machine-state unserializer; its return value is mapped to the C{serialized} parameter to C{state}, and the L{MethodicalMachine} associated with that instance's state is updated to that state. """ class Mechanism(object): m = MethodicalMachine() def __init__(self): self.value = 1 self.ranOutput = False @m.state(serialized="first-state", initial=True) def first(self): "First state." @m.state(serialized="second-state") def second(self): "Second state." @m.input() def input(self): "an input" @m.output() def output(self): self.value = 2 self.ranOutput = True return 1 @m.output() def output2(self): return 2 first.upon(input, second, [output], collector=lambda x: list(x)[0]) second.upon(input, second, [output2], collector=lambda x: list(x)[0]) @m.serializer() def save(self, state): return { 'machine-state': state, 'some-value': self.value, } @m.unserializer() def _restore(self, blob): self.value = blob['some-value'] return blob['machine-state'] @classmethod def fromBlob(cls, blob): self = cls() self._restore(blob) return self m1 = Mechanism() m1.input() blob = m1.save() m2 = Mechanism.fromBlob(blob) self.assertEqual(m2.ranOutput, False) self.assertEqual(m2.input(), 2) self.assertEqual( m2.save(), { 'machine-state': 'second-state', 'some-value': 2, } ) # FIXME: error for wrong types on any call to _oneTransition # FIXME: better public API for .upon; maybe a context manager? # FIXME: when transitions are defined, validate that we can always get to # terminal? do we care about this? # FIXME: implementation (and use-case/example) for passing args from in to out # FIXME: possibly these need some kind of support from core # FIXME: wildcard state (in all states, when input X, emit Y and go to Z) # FIXME: wildcard input (in state X, when any input, emit Y and go to Z) # FIXME: combined wildcards (in any state for any input, emit Y go to Z) ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/automat/_test/test_trace.py ================================================ from unittest import TestCase from .._methodical import MethodicalMachine class SampleObject(object): mm = MethodicalMachine() @mm.state(initial=True) def begin(self): "initial state" @mm.state() def middle(self): "middle state" @mm.state() def end(self): "end state" @mm.input() def go1(self): "sample input" @mm.input() def go2(self): "sample input" @mm.input() def back(self): "sample input" @mm.output() def out(self): "sample output" setTrace = mm._setTrace begin.upon(go1, middle, [out]) middle.upon(go2, end, [out]) end.upon(back, middle, []) middle.upon(back, begin, []) class TraceTests(TestCase): def test_only_inputs(self): traces = [] def tracer(old_state, input, new_state): traces.append((old_state, input, new_state)) return None # "I only care about inputs, not outputs" s = SampleObject() s.setTrace(tracer) s.go1() self.assertEqual(traces, [("begin", "go1", "middle"), ]) s.go2() self.assertEqual(traces, [("begin", "go1", "middle"), ("middle", "go2", "end"), ]) s.setTrace(None) s.back() self.assertEqual(traces, [("begin", "go1", "middle"), ("middle", "go2", "end"), ]) s.go2() self.assertEqual(traces, [("begin", "go1", "middle"), ("middle", "go2", "end"), ]) def test_inputs_and_outputs(self): traces = [] def tracer(old_state, input, new_state): traces.append((old_state, input, new_state, None)) def trace_outputs(output): traces.append((old_state, input, new_state, output)) return trace_outputs # "I care about outputs too" s = SampleObject() s.setTrace(tracer) s.go1() self.assertEqual(traces, [("begin", "go1", "middle", None), ("begin", "go1", "middle", "out"), ]) s.go2() self.assertEqual(traces, [("begin", "go1", "middle", None), ("begin", "go1", "middle", "out"), ("middle", "go2", "end", None), ("middle", "go2", "end", "out"), ]) s.setTrace(None) s.back() self.assertEqual(traces, [("begin", "go1", "middle", None), ("begin", "go1", "middle", "out"), ("middle", "go2", "end", None), ("middle", "go2", "end", "out"), ]) s.go2() self.assertEqual(traces, [("begin", "go1", "middle", None), ("begin", "go1", "middle", "out"), ("middle", "go2", "end", None), ("middle", "go2", "end", "out"), ]) ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/automat/_test/test_visualize.py ================================================ from __future__ import print_function import functools import os import subprocess from unittest import TestCase, skipIf import attr from .._methodical import MethodicalMachine from .test_discover import isTwistedInstalled def isGraphvizModuleInstalled(): """ Is the graphviz Python module installed? """ try: __import__("graphviz") except ImportError: return False else: return True def isGraphvizInstalled(): """ Are the graphviz tools installed? """ r, w = os.pipe() os.close(w) try: return not subprocess.call("dot", stdin=r, shell=True) finally: os.close(r) def sampleMachine(): """ Create a sample L{MethodicalMachine} with some sample states. """ mm = MethodicalMachine() class SampleObject(object): @mm.state(initial=True) def begin(self): "initial state" @mm.state() def end(self): "end state" @mm.input() def go(self): "sample input" @mm.output() def out(self): "sample output" begin.upon(go, end, [out]) so = SampleObject() so.go() return mm @skipIf(not isGraphvizModuleInstalled(), "Graphviz module is not installed.") class ElementMakerTests(TestCase): """ L{elementMaker} generates HTML representing the specified element. """ def setUp(self): from .._visualize import elementMaker self.elementMaker = elementMaker def test_sortsAttrs(self): """ L{elementMaker} orders HTML attributes lexicographically. """ expected = r'

' self.assertEqual(expected, self.elementMaker("div", b='2', a='1', c='3')) def test_quotesAttrs(self): """ L{elementMaker} quotes HTML attributes according to DOT's quoting rule. See U{http://www.graphviz.org/doc/info/lang.html}, footnote 1. """ expected = r'
' self.assertEqual(expected, self.elementMaker("div", b='a " quote', a=1, c="a string")) def test_noAttrs(self): """ L{elementMaker} should render an element with no attributes. """ expected = r'
' self.assertEqual(expected, self.elementMaker("div")) @attr.s class HTMLElement(object): """Holds an HTML element, as created by elementMaker.""" name = attr.ib() children = attr.ib() attributes = attr.ib() def findElements(element, predicate): """ Recursively collect all elements in an L{HTMLElement} tree that match the optional predicate. """ if predicate(element): return [element] elif isLeaf(element): return [] return [result for child in element.children for result in findElements(child, predicate)] def isLeaf(element): """ This HTML element is actually leaf node. """ return not isinstance(element, HTMLElement) @skipIf(not isGraphvizModuleInstalled(), "Graphviz module is not installed.") class TableMakerTests(TestCase): """ Tests that ensure L{tableMaker} generates HTML tables usable as labels in DOT graphs. For more information, read the "HTML-Like Labels" section of U{http://www.graphviz.org/doc/info/shapes.html}. """ def fakeElementMaker(self, name, *children, **attributes): return HTMLElement(name=name, children=children, attributes=attributes) def setUp(self): from .._visualize import tableMaker self.inputLabel = "input label" self.port = "the port" self.tableMaker = functools.partial(tableMaker, _E=self.fakeElementMaker) def test_inputLabelRow(self): """ The table returned by L{tableMaker} always contains the input symbol label in its first row, and that row contains one cell with a port attribute set to the provided port. """ def hasPort(element): return (not isLeaf(element) and element.attributes.get("port") == self.port) for outputLabels in ([], ["an output label"]): table = self.tableMaker(self.inputLabel, outputLabels, port=self.port) self.assertGreater(len(table.children), 0) inputLabelRow = table.children[0] portCandidates = findElements(table, hasPort) self.assertEqual(len(portCandidates), 1) self.assertEqual(portCandidates[0].name, "td") self.assertEqual(findElements(inputLabelRow, isLeaf), [self.inputLabel]) def test_noOutputLabels(self): """ L{tableMaker} does not add a colspan attribute to the input label's cell or a second row if there no output labels. """ table = self.tableMaker("input label", (), port=self.port) self.assertEqual(len(table.children), 1) (inputLabelRow,) = table.children self.assertNotIn("colspan", inputLabelRow.attributes) def test_withOutputLabels(self): """ L{tableMaker} adds a colspan attribute to the input label's cell equal to the number of output labels and a second row that contains the output labels. """ table = self.tableMaker(self.inputLabel, ("output label 1", "output label 2"), port=self.port) self.assertEqual(len(table.children), 2) inputRow, outputRow = table.children def hasCorrectColspan(element): return (not isLeaf(element) and element.name == "td" and element.attributes.get('colspan') == "2") self.assertEqual(len(findElements(inputRow, hasCorrectColspan)), 1) self.assertEqual(findElements(outputRow, isLeaf), ["output label 1", "output label 2"]) @skipIf(not isGraphvizModuleInstalled(), "Graphviz module is not installed.") @skipIf(not isGraphvizInstalled(), "Graphviz tools are not installed.") class IntegrationTests(TestCase): """ Tests which make sure Graphviz can understand the output produced by Automat. """ def test_validGraphviz(self): """ L{graphviz} emits valid graphviz data. """ p = subprocess.Popen("dot", stdin=subprocess.PIPE, stdout=subprocess.PIPE) out, err = p.communicate("".join(sampleMachine().asDigraph()) .encode("utf-8")) self.assertEqual(p.returncode, 0) @skipIf(not isGraphvizModuleInstalled(), "Graphviz module is not installed.") class SpotChecks(TestCase): """ Tests to make sure that the output contains salient features of the machine being generated. """ def test_containsMachineFeatures(self): """ The output of L{graphviz} should contain the names of the states, inputs, outputs in the state machine. """ gvout = "".join(sampleMachine().asDigraph()) self.assertIn("begin", gvout) self.assertIn("end", gvout) self.assertIn("go", gvout) self.assertIn("out", gvout) class RecordsDigraphActions(object): """ Records calls made to L{FakeDigraph}. """ def __init__(self): self.reset() def reset(self): self.renderCalls = [] self.saveCalls = [] class FakeDigraph(object): """ A fake L{graphviz.Digraph}. Instantiate it with a L{RecordsDigraphActions}. """ def __init__(self, recorder): self._recorder = recorder def render(self, **kwargs): self._recorder.renderCalls.append(kwargs) def save(self, **kwargs): self._recorder.saveCalls.append(kwargs) class FakeMethodicalMachine(object): """ A fake L{MethodicalMachine}. Instantiate it with a L{FakeDigraph} """ def __init__(self, digraph): self._digraph = digraph def asDigraph(self): return self._digraph @skipIf(not isGraphvizModuleInstalled(), "Graphviz module is not installed.") @skipIf(not isGraphvizInstalled(), "Graphviz tools are not installed.") @skipIf(not isTwistedInstalled(), "Twisted is not installed.") class VisualizeToolTests(TestCase): def setUp(self): self.digraphRecorder = RecordsDigraphActions() self.fakeDigraph = FakeDigraph(self.digraphRecorder) self.fakeProgname = 'tool-test' self.fakeSysPath = ['ignored'] self.collectedOutput = [] self.fakeFQPN = 'fake.fqpn' def collectPrints(self, *args): self.collectedOutput.append(' '.join(args)) def fakeFindMachines(self, fqpn): yield fqpn, FakeMethodicalMachine(self.fakeDigraph) def tool(self, progname=None, argv=None, syspath=None, findMachines=None, print=None): from .._visualize import tool return tool( _progname=progname or self.fakeProgname, _argv=argv or [self.fakeFQPN], _syspath=syspath or self.fakeSysPath, _findMachines=findMachines or self.fakeFindMachines, _print=print or self.collectPrints) def test_checksCurrentDirectory(self): """ L{tool} adds '' to sys.path to ensure L{automat._discover.findMachines} searches the current directory. """ self.tool(argv=[self.fakeFQPN]) self.assertEqual(self.fakeSysPath[0], '') def test_quietHidesOutput(self): """ Passing -q/--quiet hides all output. """ self.tool(argv=[self.fakeFQPN, '--quiet']) self.assertFalse(self.collectedOutput) self.tool(argv=[self.fakeFQPN, '-q']) self.assertFalse(self.collectedOutput) def test_onlySaveDot(self): """ Passing an empty string for --image-directory/-i disables rendering images. """ for arg in ('--image-directory', '-i'): self.digraphRecorder.reset() self.collectedOutput = [] self.tool(argv=[self.fakeFQPN, arg, '']) self.assertFalse(any("image" in line for line in self.collectedOutput)) self.assertEqual(len(self.digraphRecorder.saveCalls), 1) (call,) = self.digraphRecorder.saveCalls self.assertEqual("{}.dot".format(self.fakeFQPN), call['filename']) self.assertFalse(self.digraphRecorder.renderCalls) def test_saveOnlyImage(self): """ Passing an empty string for --dot-directory/-d disables saving dot files. """ for arg in ('--dot-directory', '-d'): self.digraphRecorder.reset() self.collectedOutput = [] self.tool(argv=[self.fakeFQPN, arg, '']) self.assertFalse(any("dot" in line for line in self.collectedOutput)) self.assertEqual(len(self.digraphRecorder.renderCalls), 1) (call,) = self.digraphRecorder.renderCalls self.assertEqual("{}.dot".format(self.fakeFQPN), call['filename']) self.assertTrue(call['cleanup']) self.assertFalse(self.digraphRecorder.saveCalls) def test_saveDotAndImagesInDifferentDirectories(self): """ Passing different directories to --image-directory and --dot-directory writes images and dot files to those directories. """ imageDirectory = 'image' dotDirectory = 'dot' self.tool(argv=[self.fakeFQPN, '--image-directory', imageDirectory, '--dot-directory', dotDirectory]) self.assertTrue(any("image" in line for line in self.collectedOutput)) self.assertTrue(any("dot" in line for line in self.collectedOutput)) self.assertEqual(len(self.digraphRecorder.renderCalls), 1) (renderCall,) = self.digraphRecorder.renderCalls self.assertEqual(renderCall["directory"], imageDirectory) self.assertTrue(renderCall['cleanup']) self.assertEqual(len(self.digraphRecorder.saveCalls), 1) (saveCall,) = self.digraphRecorder.saveCalls self.assertEqual(saveCall["directory"], dotDirectory) def test_saveDotAndImagesInSameDirectory(self): """ Passing the same directory to --image-directory and --dot-directory writes images and dot files to that one directory. """ directory = 'imagesAndDot' self.tool(argv=[self.fakeFQPN, '--image-directory', directory, '--dot-directory', directory]) self.assertTrue(any("image and dot" in line for line in self.collectedOutput)) self.assertEqual(len(self.digraphRecorder.renderCalls), 1) (renderCall,) = self.digraphRecorder.renderCalls self.assertEqual(renderCall["directory"], directory) self.assertFalse(renderCall['cleanup']) self.assertFalse(len(self.digraphRecorder.saveCalls)) ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/automat/_visualize.py ================================================ from __future__ import print_function import argparse import sys import graphviz from ._discover import findMachines def _gvquote(s): return '"{}"'.format(s.replace('"', r'\"')) def _gvhtml(s): return '<{}>'.format(s) def elementMaker(name, *children, **attrs): """ Construct a string from the HTML element description. """ formattedAttrs = ' '.join('{}={}'.format(key, _gvquote(str(value))) for key, value in sorted(attrs.items())) formattedChildren = ''.join(children) return u'<{name} {attrs}>{children}'.format( name=name, attrs=formattedAttrs, children=formattedChildren) def tableMaker(inputLabel, outputLabels, port, _E=elementMaker): """ Construct an HTML table to label a state transition. """ colspan = {} if outputLabels: colspan['colspan'] = str(len(outputLabels)) inputLabelCell = _E("td", _E("font", inputLabel, face="menlo-italic"), color="purple", port=port, **colspan) pointSize = {"point-size": "9"} outputLabelCells = [_E("td", _E("font", outputLabel, **pointSize), color="pink") for outputLabel in outputLabels] rows = [_E("tr", inputLabelCell)] if outputLabels: rows.append(_E("tr", *outputLabelCells)) return _E("table", *rows) def makeDigraph(automaton, inputAsString=repr, outputAsString=repr, stateAsString=repr): """ Produce a L{graphviz.Digraph} object from an automaton. """ digraph = graphviz.Digraph(graph_attr={'pack': 'true', 'dpi': '100'}, node_attr={'fontname': 'Menlo'}, edge_attr={'fontname': 'Menlo'}) for state in automaton.states(): if state is automaton.initialState: stateShape = "bold" fontName = "Menlo-Bold" else: stateShape = "" fontName = "Menlo" digraph.node(stateAsString(state), fontame=fontName, shape="ellipse", style=stateShape, color="blue") for n, eachTransition in enumerate(automaton.allTransitions()): inState, inputSymbol, outState, outputSymbols = eachTransition thisTransition = "t{}".format(n) inputLabel = inputAsString(inputSymbol) port = "tableport" table = tableMaker(inputLabel, [outputAsString(outputSymbol) for outputSymbol in outputSymbols], port=port) digraph.node(thisTransition, label=_gvhtml(table), margin="0.2", shape="none") digraph.edge(stateAsString(inState), '{}:{}:w'.format(thisTransition, port), arrowhead="none") digraph.edge('{}:{}:e'.format(thisTransition, port), stateAsString(outState)) return digraph def tool(_progname=sys.argv[0], _argv=sys.argv[1:], _syspath=sys.path, _findMachines=findMachines, _print=print): """ Entry point for command line utility. """ DESCRIPTION = """ Visualize automat.MethodicalMachines as graphviz graphs. """ EPILOG = """ You must have the graphviz tool suite installed. Please visit http://www.graphviz.org for more information. """ if _syspath[0]: _syspath.insert(0, '') argumentParser = argparse.ArgumentParser( prog=_progname, description=DESCRIPTION, epilog=EPILOG) argumentParser.add_argument('fqpn', help="A Fully Qualified Path name" " representing where to find machines.") argumentParser.add_argument('--quiet', '-q', help="suppress output", default=False, action="store_true") argumentParser.add_argument('--dot-directory', '-d', help="Where to write out .dot files.", default=".automat_visualize") argumentParser.add_argument('--image-directory', '-i', help="Where to write out image files.", default=".automat_visualize") argumentParser.add_argument('--image-type', '-t', help="The image format.", choices=graphviz.FORMATS, default='png') argumentParser.add_argument('--view', '-v', help="View rendered graphs with" " default image viewer", default=False, action="store_true") args = argumentParser.parse_args(_argv) explicitlySaveDot = (args.dot_directory and (not args.image_directory or args.image_directory != args.dot_directory)) if args.quiet: def _print(*args): pass for fqpn, machine in _findMachines(args.fqpn): _print(fqpn, '...discovered') digraph = machine.asDigraph() if explicitlySaveDot: digraph.save(filename="{}.dot".format(fqpn), directory=args.dot_directory) _print(fqpn, "...wrote dot into", args.dot_directory) if args.image_directory: deleteDot = not args.dot_directory or explicitlySaveDot digraph.format = args.image_type digraph.render(filename="{}.dot".format(fqpn), directory=args.image_directory, view=args.view, cleanup=deleteDot) if deleteDot: msg = "...wrote image into" else: msg = "...wrote image and dot into" _print(fqpn, msg, args.image_directory) ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/bson/__init__.py ================================================ # Copyright 2009-present MongoDB, Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """BSON (Binary JSON) encoding and decoding. The mapping from Python types to BSON types is as follows: ======================================= ============= =================== Python Type BSON Type Supported Direction ======================================= ============= =================== None null both bool boolean both int [#int]_ int32 / int64 py -> bson long int64 py -> bson `bson.int64.Int64` int64 both float number (real) both string string py -> bson unicode string both list array both dict / `SON` object both datetime.datetime [#dt]_ [#dt2]_ date both `bson.regex.Regex` regex both compiled re [#re]_ regex py -> bson `bson.binary.Binary` binary both `bson.objectid.ObjectId` oid both `bson.dbref.DBRef` dbref both None undefined bson -> py unicode code bson -> py `bson.code.Code` code py -> bson unicode symbol bson -> py bytes (Python 3) [#bytes]_ binary both ======================================= ============= =================== Note that, when using Python 2.x, to save binary data it must be wrapped as an instance of `bson.binary.Binary`. Otherwise it will be saved as a BSON string and retrieved as unicode. Users of Python 3.x can use the Python bytes type. .. [#int] A Python int will be saved as a BSON int32 or BSON int64 depending on its size. A BSON int32 will always decode to a Python int. A BSON int64 will always decode to a :class:`~bson.int64.Int64`. .. [#dt] datetime.datetime instances will be rounded to the nearest millisecond when saved .. [#dt2] all datetime.datetime instances are treated as *naive*. clients should always use UTC. .. [#re] :class:`~bson.regex.Regex` instances and regular expression objects from ``re.compile()`` are both saved as BSON regular expressions. BSON regular expressions are decoded as :class:`~bson.regex.Regex` instances. .. [#bytes] The bytes type from Python 3.x is encoded as BSON binary with subtype 0. In Python 3.x it will be decoded back to bytes. In Python 2.x it will be decoded to an instance of :class:`~bson.binary.Binary` with subtype 0. """ import calendar import datetime import itertools import platform import re import struct import sys import uuid from codecs import (utf_8_decode as _utf_8_decode, utf_8_encode as _utf_8_encode) from bson.binary import (Binary, OLD_UUID_SUBTYPE, JAVA_LEGACY, CSHARP_LEGACY, UUIDLegacy) from bson.code import Code from bson.codec_options import ( CodecOptions, DEFAULT_CODEC_OPTIONS, _raw_document_class) from bson.dbref import DBRef from bson.decimal128 import Decimal128 from bson.errors import (InvalidBSON, InvalidDocument, InvalidStringData) from bson.int64 import Int64 from bson.max_key import MaxKey from bson.min_key import MinKey from bson.objectid import ObjectId from bson.py3compat import (abc, b, PY3, iteritems, text_type, string_type, reraise) from bson.regex import Regex from bson.son import SON, RE_TYPE from bson.timestamp import Timestamp from bson.tz_util import utc try: from bson import _cbson _USE_C = True except ImportError: _USE_C = False EPOCH_AWARE = datetime.datetime.fromtimestamp(0, utc) EPOCH_NAIVE = datetime.datetime.utcfromtimestamp(0) BSONNUM = b"\x01" # Floating point BSONSTR = b"\x02" # UTF-8 string BSONOBJ = b"\x03" # Embedded document BSONARR = b"\x04" # Array BSONBIN = b"\x05" # Binary BSONUND = b"\x06" # Undefined BSONOID = b"\x07" # ObjectId BSONBOO = b"\x08" # Boolean BSONDAT = b"\x09" # UTC Datetime BSONNUL = b"\x0A" # Null BSONRGX = b"\x0B" # Regex BSONREF = b"\x0C" # DBRef BSONCOD = b"\x0D" # Javascript code BSONSYM = b"\x0E" # Symbol BSONCWS = b"\x0F" # Javascript code with scope BSONINT = b"\x10" # 32bit int BSONTIM = b"\x11" # Timestamp BSONLON = b"\x12" # 64bit int BSONDEC = b"\x13" # Decimal128 BSONMIN = b"\xFF" # Min key BSONMAX = b"\x7F" # Max key _UNPACK_FLOAT_FROM = struct.Struct("= obj_end: raise InvalidBSON("invalid object length") # If this is the top-level document, validate the total size too. if position == 0 and obj_size != obj_end: raise InvalidBSON("invalid object length") return obj_size, end def _get_object(data, view, position, obj_end, opts, dummy): """Decode a BSON subdocument to opts.document_class or bson.dbref.DBRef.""" obj_size, end = _get_object_size(data, position, obj_end) if _raw_document_class(opts.document_class): return (opts.document_class(data[position:end + 1], opts), position + obj_size) obj = _elements_to_dict(data, view, position + 4, end, opts) position += obj_size if "$ref" in obj: return (DBRef(obj.pop("$ref"), obj.pop("$id", None), obj.pop("$db", None), obj), position) return obj, position def _get_array(data, view, position, obj_end, opts, element_name): """Decode a BSON array to python list.""" size = _UNPACK_INT_FROM(data, position)[0] end = position + size - 1 if data[end] != _OBJEND: raise InvalidBSON("bad eoo") position += 4 end -= 1 result = [] # Avoid doing global and attribute lookups in the loop. append = result.append index = data.index getter = _ELEMENT_GETTER decoder_map = opts.type_registry._decoder_map while position < end: element_type = data[position] # Just skip the keys. position = index(b'\x00', position) + 1 try: value, position = getter[element_type]( data, view, position, obj_end, opts, element_name) except KeyError: _raise_unknown_type(element_type, element_name) if decoder_map: custom_decoder = decoder_map.get(type(value)) if custom_decoder is not None: value = custom_decoder(value) append(value) if position != end + 1: raise InvalidBSON('bad array length') return result, position + 1 def _get_binary(data, view, position, obj_end, opts, dummy1): """Decode a BSON binary to bson.binary.Binary or python UUID.""" length, subtype = _UNPACK_LENGTH_SUBTYPE_FROM(data, position) position += 5 if subtype == 2: length2 = _UNPACK_INT_FROM(data, position)[0] position += 4 if length2 != length - 4: raise InvalidBSON("invalid binary (st 2) - lengths don't match!") length = length2 end = position + length if length < 0 or end > obj_end: raise InvalidBSON('bad binary object length') if subtype == 3: # Java Legacy uuid_representation = opts.uuid_representation if uuid_representation == JAVA_LEGACY: java = data[position:end] value = uuid.UUID(bytes=java[0:8][::-1] + java[8:16][::-1]) # C# legacy elif uuid_representation == CSHARP_LEGACY: value = uuid.UUID(bytes_le=data[position:end]) # Python else: value = uuid.UUID(bytes=data[position:end]) return value, end if subtype == 4: return uuid.UUID(bytes=data[position:end]), end # Python3 special case. Decode subtype 0 to 'bytes'. if PY3 and subtype == 0: value = data[position:end] else: value = Binary(data[position:end], subtype) return value, end def _get_oid(data, view, position, dummy0, dummy1, dummy2): """Decode a BSON ObjectId to bson.objectid.ObjectId.""" end = position + 12 return ObjectId(data[position:end]), end def _get_boolean(data, view, position, dummy0, dummy1, dummy2): """Decode a BSON true/false to python True/False.""" end = position + 1 boolean_byte = data[position:end] if boolean_byte == b'\x00': return False, end elif boolean_byte == b'\x01': return True, end raise InvalidBSON('invalid boolean value: %r' % boolean_byte) def _get_date(data, view, position, dummy0, opts, dummy1): """Decode a BSON datetime to python datetime.datetime.""" return _millis_to_datetime( _UNPACK_LONG_FROM(data, position)[0], opts), position + 8 def _get_code(data, view, position, obj_end, opts, element_name): """Decode a BSON code to bson.code.Code.""" code, position = _get_string(data, view, position, obj_end, opts, element_name) return Code(code), position def _get_code_w_scope(data, view, position, obj_end, opts, element_name): """Decode a BSON code_w_scope to bson.code.Code.""" code_end = position + _UNPACK_INT_FROM(data, position)[0] code, position = _get_string( data, view, position + 4, code_end, opts, element_name) scope, position = _get_object(data, view, position, code_end, opts, element_name) if position != code_end: raise InvalidBSON('scope outside of javascript code boundaries') return Code(code, scope), position def _get_regex(data, view, position, dummy0, opts, dummy1): """Decode a BSON regex to bson.regex.Regex or a python pattern object.""" pattern, position = _get_c_string(data, view, position, opts) bson_flags, position = _get_c_string(data, view, position, opts) bson_re = Regex(pattern, bson_flags) return bson_re, position def _get_ref(data, view, position, obj_end, opts, element_name): """Decode (deprecated) BSON DBPointer to bson.dbref.DBRef.""" collection, position = _get_string( data, view, position, obj_end, opts, element_name) oid, position = _get_oid(data, view, position, obj_end, opts, element_name) return DBRef(collection, oid), position def _get_timestamp(data, view, position, dummy0, dummy1, dummy2): """Decode a BSON timestamp to bson.timestamp.Timestamp.""" inc, timestamp = _UNPACK_TIMESTAMP_FROM(data, position) return Timestamp(timestamp, inc), position + 8 def _get_int64(data, view, position, dummy0, dummy1, dummy2): """Decode a BSON int64 to bson.int64.Int64.""" return Int64(_UNPACK_LONG_FROM(data, position)[0]), position + 8 def _get_decimal128(data, view, position, dummy0, dummy1, dummy2): """Decode a BSON decimal128 to bson.decimal128.Decimal128.""" end = position + 16 return Decimal128.from_bid(data[position:end]), end # Each decoder function's signature is: # - data: bytes # - view: memoryview that references `data` # - position: int, beginning of object in 'data' to decode # - obj_end: int, end of object to decode in 'data' if variable-length type # - opts: a CodecOptions _ELEMENT_GETTER = { _maybe_ord(BSONNUM): _get_float, _maybe_ord(BSONSTR): _get_string, _maybe_ord(BSONOBJ): _get_object, _maybe_ord(BSONARR): _get_array, _maybe_ord(BSONBIN): _get_binary, _maybe_ord(BSONUND): lambda u, v, w, x, y, z: (None, w), # Deprecated undefined _maybe_ord(BSONOID): _get_oid, _maybe_ord(BSONBOO): _get_boolean, _maybe_ord(BSONDAT): _get_date, _maybe_ord(BSONNUL): lambda u, v, w, x, y, z: (None, w), _maybe_ord(BSONRGX): _get_regex, _maybe_ord(BSONREF): _get_ref, # Deprecated DBPointer _maybe_ord(BSONCOD): _get_code, _maybe_ord(BSONSYM): _get_string, # Deprecated symbol _maybe_ord(BSONCWS): _get_code_w_scope, _maybe_ord(BSONINT): _get_int, _maybe_ord(BSONTIM): _get_timestamp, _maybe_ord(BSONLON): _get_int64, _maybe_ord(BSONDEC): _get_decimal128, _maybe_ord(BSONMIN): lambda u, v, w, x, y, z: (MinKey(), w), _maybe_ord(BSONMAX): lambda u, v, w, x, y, z: (MaxKey(), w)} if _USE_C: def _element_to_dict(data, view, position, obj_end, opts): return _cbson._element_to_dict(data, position, obj_end, opts) else: def _element_to_dict(data, view, position, obj_end, opts): """Decode a single key, value pair.""" element_type = data[position] position += 1 element_name, position = _get_c_string(data, view, position, opts) try: value, position = _ELEMENT_GETTER[element_type](data, view, position, obj_end, opts, element_name) except KeyError: _raise_unknown_type(element_type, element_name) if opts.type_registry._decoder_map: custom_decoder = opts.type_registry._decoder_map.get(type(value)) if custom_decoder is not None: value = custom_decoder(value) return element_name, value, position def _raw_to_dict(data, position, obj_end, opts, result): data, view = get_data_and_view(data) return _elements_to_dict(data, view, position, obj_end, opts, result) def _elements_to_dict(data, view, position, obj_end, opts, result=None): """Decode a BSON document into result.""" if result is None: result = opts.document_class() end = obj_end - 1 while position < end: key, value, position = _element_to_dict(data, view, position, obj_end, opts) result[key] = value if position != obj_end: raise InvalidBSON('bad object or element length') return result def _bson_to_dict(data, opts): """Decode a BSON string to document_class.""" data, view = get_data_and_view(data) try: if _raw_document_class(opts.document_class): return opts.document_class(data, opts) _, end = _get_object_size(data, 0, len(data)) return _elements_to_dict(data, view, 4, end, opts) except InvalidBSON: raise except Exception: # Change exception type to InvalidBSON but preserve traceback. _, exc_value, exc_tb = sys.exc_info() reraise(InvalidBSON, exc_value, exc_tb) if _USE_C: _bson_to_dict = _cbson._bson_to_dict _PACK_FLOAT = struct.Struct(">> import collections # From Python standard library. >>> import bson >>> from bson.codec_options import CodecOptions >>> data = bson.encode({'a': 1}) >>> decoded_doc = bson.decode(data) >>> options = CodecOptions(document_class=collections.OrderedDict) >>> decoded_doc = bson.decode(data, codec_options=options) >>> type(decoded_doc) :Parameters: - `data`: the BSON to decode. Any bytes-like object that implements the buffer protocol. - `codec_options` (optional): An instance of :class:`~bson.codec_options.CodecOptions`. .. versionadded:: 3.9 """ if not isinstance(codec_options, CodecOptions): raise _CODEC_OPTIONS_TYPE_ERROR return _bson_to_dict(data, codec_options) def decode_all(data, codec_options=DEFAULT_CODEC_OPTIONS): """Decode BSON data to multiple documents. `data` must be a bytes-like object implementing the buffer protocol that provides concatenated, valid, BSON-encoded documents. :Parameters: - `data`: BSON data - `codec_options` (optional): An instance of :class:`~bson.codec_options.CodecOptions`. .. versionchanged:: 3.9 Supports bytes-like objects that implement the buffer protocol. .. versionchanged:: 3.0 Removed `compile_re` option: PyMongo now always represents BSON regular expressions as :class:`~bson.regex.Regex` objects. Use :meth:`~bson.regex.Regex.try_compile` to attempt to convert from a BSON regular expression to a Python regular expression object. Replaced `as_class`, `tz_aware`, and `uuid_subtype` options with `codec_options`. .. versionchanged:: 2.7 Added `compile_re` option. If set to False, PyMongo represented BSON regular expressions as :class:`~bson.regex.Regex` objects instead of attempting to compile BSON regular expressions as Python native regular expressions, thus preventing errors for some incompatible patterns, see `PYTHON-500`_. .. _PYTHON-500: https://jira.mongodb.org/browse/PYTHON-500 """ data, view = get_data_and_view(data) if not isinstance(codec_options, CodecOptions): raise _CODEC_OPTIONS_TYPE_ERROR data_len = len(data) docs = [] position = 0 end = data_len - 1 use_raw = _raw_document_class(codec_options.document_class) try: while position < end: obj_size = _UNPACK_INT_FROM(data, position)[0] if data_len - position < obj_size: raise InvalidBSON("invalid object size") obj_end = position + obj_size - 1 if data[obj_end] != _OBJEND: raise InvalidBSON("bad eoo") if use_raw: docs.append( codec_options.document_class( data[position:obj_end + 1], codec_options)) else: docs.append(_elements_to_dict(data, view, position + 4, obj_end, codec_options)) position += obj_size return docs except InvalidBSON: raise except Exception: # Change exception type to InvalidBSON but preserve traceback. _, exc_value, exc_tb = sys.exc_info() reraise(InvalidBSON, exc_value, exc_tb) if _USE_C: decode_all = _cbson.decode_all def _decode_selective(rawdoc, fields, codec_options): if _raw_document_class(codec_options.document_class): # If document_class is RawBSONDocument, use vanilla dictionary for # decoding command response. doc = {} else: # Else, use the specified document_class. doc = codec_options.document_class() for key, value in iteritems(rawdoc): if key in fields: if fields[key] == 1: doc[key] = _bson_to_dict(rawdoc.raw, codec_options)[key] else: doc[key] = _decode_selective(value, fields[key], codec_options) else: doc[key] = value return doc def _decode_all_selective(data, codec_options, fields): """Decode BSON data to a single document while using user-provided custom decoding logic. `data` must be a string representing a valid, BSON-encoded document. :Parameters: - `data`: BSON data - `codec_options`: An instance of :class:`~bson.codec_options.CodecOptions` with user-specified type decoders. If no decoders are found, this method is the same as ``decode_all``. - `fields`: Map of document namespaces where data that needs to be custom decoded lives or None. For example, to custom decode a list of objects in 'field1.subfield1', the specified value should be ``{'field1': {'subfield1': 1}}``. If ``fields`` is an empty map or None, this method is the same as ``decode_all``. :Returns: - `document_list`: Single-member list containing the decoded document. .. versionadded:: 3.8 """ if not codec_options.type_registry._decoder_map: return decode_all(data, codec_options) if not fields: return decode_all(data, codec_options.with_options(type_registry=None)) # Decode documents for internal use. from bson.raw_bson import RawBSONDocument internal_codec_options = codec_options.with_options( document_class=RawBSONDocument, type_registry=None) _doc = _bson_to_dict(data, internal_codec_options) return [_decode_selective(_doc, fields, codec_options,)] def decode_iter(data, codec_options=DEFAULT_CODEC_OPTIONS): """Decode BSON data to multiple documents as a generator. Works similarly to the decode_all function, but yields one document at a time. `data` must be a string of concatenated, valid, BSON-encoded documents. :Parameters: - `data`: BSON data - `codec_options` (optional): An instance of :class:`~bson.codec_options.CodecOptions`. .. versionchanged:: 3.0 Replaced `as_class`, `tz_aware`, and `uuid_subtype` options with `codec_options`. .. versionadded:: 2.8 """ if not isinstance(codec_options, CodecOptions): raise _CODEC_OPTIONS_TYPE_ERROR position = 0 end = len(data) - 1 while position < end: obj_size = _UNPACK_INT_FROM(data, position)[0] elements = data[position:position + obj_size] position += obj_size yield _bson_to_dict(elements, codec_options) def decode_file_iter(file_obj, codec_options=DEFAULT_CODEC_OPTIONS): """Decode bson data from a file to multiple documents as a generator. Works similarly to the decode_all function, but reads from the file object in chunks and parses bson in chunks, yielding one document at a time. :Parameters: - `file_obj`: A file object containing BSON data. - `codec_options` (optional): An instance of :class:`~bson.codec_options.CodecOptions`. .. versionchanged:: 3.0 Replaced `as_class`, `tz_aware`, and `uuid_subtype` options with `codec_options`. .. versionadded:: 2.8 """ while True: # Read size of next object. size_data = file_obj.read(4) if not size_data: break # Finished with file normaly. elif len(size_data) != 4: raise InvalidBSON("cut off in middle of objsize") obj_size = _UNPACK_INT_FROM(size_data, 0)[0] - 4 elements = size_data + file_obj.read(obj_size) yield _bson_to_dict(elements, codec_options) def is_valid(bson): """Check that the given string represents valid :class:`BSON` data. Raises :class:`TypeError` if `bson` is not an instance of :class:`str` (:class:`bytes` in python 3). Returns ``True`` if `bson` is valid :class:`BSON`, ``False`` otherwise. :Parameters: - `bson`: the data to be validated """ if not isinstance(bson, bytes): raise TypeError("BSON data must be an instance of a subclass of bytes") try: _bson_to_dict(bson, DEFAULT_CODEC_OPTIONS) return True except Exception: return False class BSON(bytes): """BSON (Binary JSON) data. .. warning:: Using this class to encode and decode BSON adds a performance cost. For better performance use the module level functions :func:`encode` and :func:`decode` instead. """ @classmethod def encode(cls, document, check_keys=False, codec_options=DEFAULT_CODEC_OPTIONS): """Encode a document to a new :class:`BSON` instance. A document can be any mapping type (like :class:`dict`). Raises :class:`TypeError` if `document` is not a mapping type, or contains keys that are not instances of :class:`basestring` (:class:`str` in python 3). Raises :class:`~bson.errors.InvalidDocument` if `document` cannot be converted to :class:`BSON`. :Parameters: - `document`: mapping type representing a document - `check_keys` (optional): check if keys start with '$' or contain '.', raising :class:`~bson.errors.InvalidDocument` in either case - `codec_options` (optional): An instance of :class:`~bson.codec_options.CodecOptions`. .. versionchanged:: 3.0 Replaced `uuid_subtype` option with `codec_options`. """ return cls(encode(document, check_keys, codec_options)) def decode(self, codec_options=DEFAULT_CODEC_OPTIONS): """Decode this BSON data. By default, returns a BSON document represented as a Python :class:`dict`. To use a different :class:`MutableMapping` class, configure a :class:`~bson.codec_options.CodecOptions`:: >>> import collections # From Python standard library. >>> import bson >>> from bson.codec_options import CodecOptions >>> data = bson.BSON.encode({'a': 1}) >>> decoded_doc = bson.BSON(data).decode() >>> options = CodecOptions(document_class=collections.OrderedDict) >>> decoded_doc = bson.BSON(data).decode(codec_options=options) >>> type(decoded_doc) :Parameters: - `codec_options` (optional): An instance of :class:`~bson.codec_options.CodecOptions`. .. versionchanged:: 3.0 Removed `compile_re` option: PyMongo now always represents BSON regular expressions as :class:`~bson.regex.Regex` objects. Use :meth:`~bson.regex.Regex.try_compile` to attempt to convert from a BSON regular expression to a Python regular expression object. Replaced `as_class`, `tz_aware`, and `uuid_subtype` options with `codec_options`. .. versionchanged:: 2.7 Added `compile_re` option. If set to False, PyMongo represented BSON regular expressions as :class:`~bson.regex.Regex` objects instead of attempting to compile BSON regular expressions as Python native regular expressions, thus preventing errors for some incompatible patterns, see `PYTHON-500`_. .. _PYTHON-500: https://jira.mongodb.org/browse/PYTHON-500 """ return decode(self, codec_options) def has_c(): """Is the C extension installed? """ return _USE_C ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/bson/binary.py ================================================ # Copyright 2009-present MongoDB, Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from uuid import UUID from bson.py3compat import PY3 """Tools for representing BSON binary data. """ BINARY_SUBTYPE = 0 """BSON binary subtype for binary data. This is the default subtype for binary data. """ FUNCTION_SUBTYPE = 1 """BSON binary subtype for functions. """ OLD_BINARY_SUBTYPE = 2 """Old BSON binary subtype for binary data. This is the old default subtype, the current default is :data:`BINARY_SUBTYPE`. """ OLD_UUID_SUBTYPE = 3 """Old BSON binary subtype for a UUID. :class:`uuid.UUID` instances will automatically be encoded by :mod:`bson` using this subtype. .. versionadded:: 2.1 """ UUID_SUBTYPE = 4 """BSON binary subtype for a UUID. This is the new BSON binary subtype for UUIDs. The current default is :data:`OLD_UUID_SUBTYPE`. .. versionchanged:: 2.1 Changed to subtype 4. """ STANDARD = UUID_SUBTYPE """The standard UUID representation. :class:`uuid.UUID` instances will automatically be encoded to and decoded from BSON binary, using RFC-4122 byte order with binary subtype :data:`UUID_SUBTYPE`. .. versionadded:: 3.0 """ PYTHON_LEGACY = OLD_UUID_SUBTYPE """The Python legacy UUID representation. :class:`uuid.UUID` instances will automatically be encoded to and decoded from BSON binary, using RFC-4122 byte order with binary subtype :data:`OLD_UUID_SUBTYPE`. .. versionadded:: 3.0 """ JAVA_LEGACY = 5 """The Java legacy UUID representation. :class:`uuid.UUID` instances will automatically be encoded to and decoded from BSON binary subtype :data:`OLD_UUID_SUBTYPE`, using the Java driver's legacy byte order. .. versionchanged:: 3.6 BSON binary subtype 4 is decoded using RFC-4122 byte order. .. versionadded:: 2.3 """ CSHARP_LEGACY = 6 """The C#/.net legacy UUID representation. :class:`uuid.UUID` instances will automatically be encoded to and decoded from BSON binary subtype :data:`OLD_UUID_SUBTYPE`, using the C# driver's legacy byte order. .. versionchanged:: 3.6 BSON binary subtype 4 is decoded using RFC-4122 byte order. .. versionadded:: 2.3 """ ALL_UUID_SUBTYPES = (OLD_UUID_SUBTYPE, UUID_SUBTYPE) ALL_UUID_REPRESENTATIONS = (STANDARD, PYTHON_LEGACY, JAVA_LEGACY, CSHARP_LEGACY) UUID_REPRESENTATION_NAMES = { PYTHON_LEGACY: 'PYTHON_LEGACY', STANDARD: 'STANDARD', JAVA_LEGACY: 'JAVA_LEGACY', CSHARP_LEGACY: 'CSHARP_LEGACY'} MD5_SUBTYPE = 5 """BSON binary subtype for an MD5 hash. """ USER_DEFINED_SUBTYPE = 128 """BSON binary subtype for any user defined structure. """ class Binary(bytes): """Representation of BSON binary data. This is necessary because we want to represent Python strings as the BSON string type. We need to wrap binary data so we can tell the difference between what should be considered binary data and what should be considered a string when we encode to BSON. Raises TypeError if `data` is not an instance of :class:`bytes` (:class:`str` in python 2) or `subtype` is not an instance of :class:`int`. Raises ValueError if `subtype` is not in [0, 256). .. note:: In python 3 instances of Binary with subtype 0 will be decoded directly to :class:`bytes`. :Parameters: - `data`: the binary data to represent. Can be any bytes-like type that implements the buffer protocol. - `subtype` (optional): the `binary subtype `_ to use .. versionchanged:: 3.9 Support any bytes-like type that implements the buffer protocol. """ _type_marker = 5 def __new__(cls, data, subtype=BINARY_SUBTYPE): if not isinstance(subtype, int): raise TypeError("subtype must be an instance of int") if subtype >= 256 or subtype < 0: raise ValueError("subtype must be contained in [0, 256)") # Support any type that implements the buffer protocol. self = bytes.__new__(cls, memoryview(data).tobytes()) self.__subtype = subtype return self @property def subtype(self): """Subtype of this binary data. """ return self.__subtype def __getnewargs__(self): # Work around http://bugs.python.org/issue7382 data = super(Binary, self).__getnewargs__()[0] if PY3 and not isinstance(data, bytes): data = data.encode('latin-1') return data, self.__subtype def __eq__(self, other): if isinstance(other, Binary): return ((self.__subtype, bytes(self)) == (other.subtype, bytes(other))) # We don't return NotImplemented here because if we did then # Binary("foo") == "foo" would return True, since Binary is a # subclass of str... return False def __hash__(self): return super(Binary, self).__hash__() ^ hash(self.__subtype) def __ne__(self, other): return not self == other def __repr__(self): return "Binary(%s, %s)" % (bytes.__repr__(self), self.__subtype) class UUIDLegacy(Binary): """UUID wrapper to support working with UUIDs stored as PYTHON_LEGACY. .. doctest:: >>> import uuid >>> from bson.binary import Binary, UUIDLegacy, STANDARD >>> from bson.codec_options import CodecOptions >>> my_uuid = uuid.uuid4() >>> coll = db.get_collection('test', ... CodecOptions(uuid_representation=STANDARD)) >>> coll.insert_one({'uuid': Binary(my_uuid.bytes, 3)}).inserted_id ObjectId('...') >>> coll.count_documents({'uuid': my_uuid}) 0 >>> coll.count_documents({'uuid': UUIDLegacy(my_uuid)}) 1 >>> coll.find({'uuid': UUIDLegacy(my_uuid)})[0]['uuid'] UUID('...') >>> >>> # Convert from subtype 3 to subtype 4 >>> doc = coll.find_one({'uuid': UUIDLegacy(my_uuid)}) >>> coll.replace_one({"_id": doc["_id"]}, doc).matched_count 1 >>> coll.count_documents({'uuid': UUIDLegacy(my_uuid)}) 0 >>> coll.count_documents({'uuid': {'$in': [UUIDLegacy(my_uuid), my_uuid]}}) 1 >>> coll.find_one({'uuid': my_uuid})['uuid'] UUID('...') Raises TypeError if `obj` is not an instance of :class:`~uuid.UUID`. :Parameters: - `obj`: An instance of :class:`~uuid.UUID`. """ def __new__(cls, obj): if not isinstance(obj, UUID): raise TypeError("obj must be an instance of uuid.UUID") self = Binary.__new__(cls, obj.bytes, OLD_UUID_SUBTYPE) self.__uuid = obj return self def __getnewargs__(self): # Support copy and deepcopy return (self.__uuid,) @property def uuid(self): """UUID instance wrapped by this UUIDLegacy instance. """ return self.__uuid def __repr__(self): return "UUIDLegacy('%s')" % self.__uuid ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/bson/code.py ================================================ # Copyright 2009-present MongoDB, Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Tools for representing JavaScript code in BSON. """ from bson.py3compat import abc, string_type, PY3, text_type class Code(str): """BSON's JavaScript code type. Raises :class:`TypeError` if `code` is not an instance of :class:`basestring` (:class:`str` in python 3) or `scope` is not ``None`` or an instance of :class:`dict`. Scope variables can be set by passing a dictionary as the `scope` argument or by using keyword arguments. If a variable is set as a keyword argument it will override any setting for that variable in the `scope` dictionary. :Parameters: - `code`: A string containing JavaScript code to be evaluated or another instance of Code. In the latter case, the scope of `code` becomes this Code's :attr:`scope`. - `scope` (optional): dictionary representing the scope in which `code` should be evaluated - a mapping from identifiers (as strings) to values. Defaults to ``None``. This is applied after any scope associated with a given `code` above. - `**kwargs` (optional): scope variables can also be passed as keyword arguments. These are applied after `scope` and `code`. .. versionchanged:: 3.4 The default value for :attr:`scope` is ``None`` instead of ``{}``. """ _type_marker = 13 def __new__(cls, code, scope=None, **kwargs): if not isinstance(code, string_type): raise TypeError("code must be an " "instance of %s" % (string_type.__name__)) if not PY3 and isinstance(code, text_type): self = str.__new__(cls, code.encode('utf8')) else: self = str.__new__(cls, code) try: self.__scope = code.scope except AttributeError: self.__scope = None if scope is not None: if not isinstance(scope, abc.Mapping): raise TypeError("scope must be an instance of dict") if self.__scope is not None: self.__scope.update(scope) else: self.__scope = scope if kwargs: if self.__scope is not None: self.__scope.update(kwargs) else: self.__scope = kwargs return self @property def scope(self): """Scope dictionary for this instance or ``None``. """ return self.__scope def __repr__(self): return "Code(%s, %r)" % (str.__repr__(self), self.__scope) def __eq__(self, other): if isinstance(other, Code): return (self.__scope, str(self)) == (other.__scope, str(other)) return False __hash__ = None def __ne__(self, other): return not self == other ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/bson/codec_options.py ================================================ # Copyright 2014-present MongoDB, Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Tools for specifying BSON codec options.""" import datetime from abc import abstractmethod from collections import namedtuple from bson.py3compat import ABC, abc, abstractproperty, string_type from bson.binary import (ALL_UUID_REPRESENTATIONS, PYTHON_LEGACY, UUID_REPRESENTATION_NAMES) _RAW_BSON_DOCUMENT_MARKER = 101 def _raw_document_class(document_class): """Determine if a document_class is a RawBSONDocument class.""" marker = getattr(document_class, '_type_marker', None) return marker == _RAW_BSON_DOCUMENT_MARKER class TypeEncoder(ABC): """Base class for defining type codec classes which describe how a custom type can be transformed to one of the types BSON understands. Codec classes must implement the ``python_type`` attribute, and the ``transform_python`` method to support encoding. See :ref:`custom-type-type-codec` documentation for an example. """ @abstractproperty def python_type(self): """The Python type to be converted into something serializable.""" pass @abstractmethod def transform_python(self, value): """Convert the given Python object into something serializable.""" pass class TypeDecoder(ABC): """Base class for defining type codec classes which describe how a BSON type can be transformed to a custom type. Codec classes must implement the ``bson_type`` attribute, and the ``transform_bson`` method to support decoding. See :ref:`custom-type-type-codec` documentation for an example. """ @abstractproperty def bson_type(self): """The BSON type to be converted into our own type.""" pass @abstractmethod def transform_bson(self, value): """Convert the given BSON value into our own type.""" pass class TypeCodec(TypeEncoder, TypeDecoder): """Base class for defining type codec classes which describe how a custom type can be transformed to/from one of the types :mod:`bson` can already encode/decode. Codec classes must implement the ``python_type`` attribute, and the ``transform_python`` method to support encoding, as well as the ``bson_type`` attribute, and the ``transform_bson`` method to support decoding. See :ref:`custom-type-type-codec` documentation for an example. """ pass class TypeRegistry(object): """Encapsulates type codecs used in encoding and / or decoding BSON, as well as the fallback encoder. Type registries cannot be modified after instantiation. ``TypeRegistry`` can be initialized with an iterable of type codecs, and a callable for the fallback encoder:: >>> from bson.codec_options import TypeRegistry >>> type_registry = TypeRegistry([Codec1, Codec2, Codec3, ...], ... fallback_encoder) See :ref:`custom-type-type-registry` documentation for an example. :Parameters: - `type_codecs` (optional): iterable of type codec instances. If ``type_codecs`` contains multiple codecs that transform a single python or BSON type, the transformation specified by the type codec occurring last prevails. A TypeError will be raised if one or more type codecs modify the encoding behavior of a built-in :mod:`bson` type. - `fallback_encoder` (optional): callable that accepts a single, unencodable python value and transforms it into a type that :mod:`bson` can encode. See :ref:`fallback-encoder-callable` documentation for an example. """ def __init__(self, type_codecs=None, fallback_encoder=None): self.__type_codecs = list(type_codecs or []) self._fallback_encoder = fallback_encoder self._encoder_map = {} self._decoder_map = {} if self._fallback_encoder is not None: if not callable(fallback_encoder): raise TypeError("fallback_encoder %r is not a callable" % ( fallback_encoder)) for codec in self.__type_codecs: is_valid_codec = False if isinstance(codec, TypeEncoder): self._validate_type_encoder(codec) is_valid_codec = True self._encoder_map[codec.python_type] = codec.transform_python if isinstance(codec, TypeDecoder): is_valid_codec = True self._decoder_map[codec.bson_type] = codec.transform_bson if not is_valid_codec: raise TypeError( "Expected an instance of %s, %s, or %s, got %r instead" % ( TypeEncoder.__name__, TypeDecoder.__name__, TypeCodec.__name__, codec)) def _validate_type_encoder(self, codec): from bson import _BUILT_IN_TYPES for pytype in _BUILT_IN_TYPES: if issubclass(codec.python_type, pytype): err_msg = ("TypeEncoders cannot change how built-in types are " "encoded (encoder %s transforms type %s)" % (codec, pytype)) raise TypeError(err_msg) def __repr__(self): return ('%s(type_codecs=%r, fallback_encoder=%r)' % ( self.__class__.__name__, self.__type_codecs, self._fallback_encoder)) def __eq__(self, other): if not isinstance(other, type(self)): return NotImplemented return ((self._decoder_map == other._decoder_map) and (self._encoder_map == other._encoder_map) and (self._fallback_encoder == other._fallback_encoder)) _options_base = namedtuple( 'CodecOptions', ('document_class', 'tz_aware', 'uuid_representation', 'unicode_decode_error_handler', 'tzinfo', 'type_registry')) class CodecOptions(_options_base): """Encapsulates options used encoding and / or decoding BSON. The `document_class` option is used to define a custom type for use decoding BSON documents. Access to the underlying raw BSON bytes for a document is available using the :class:`~bson.raw_bson.RawBSONDocument` type:: >>> from bson.raw_bson import RawBSONDocument >>> from bson.codec_options import CodecOptions >>> codec_options = CodecOptions(document_class=RawBSONDocument) >>> coll = db.get_collection('test', codec_options=codec_options) >>> doc = coll.find_one() >>> doc.raw '\\x16\\x00\\x00\\x00\\x07_id\\x00[0\\x165\\x91\\x10\\xea\\x14\\xe8\\xc5\\x8b\\x93\\x00' The document class can be any type that inherits from :class:`~collections.MutableMapping`:: >>> class AttributeDict(dict): ... # A dict that supports attribute access. ... def __getattr__(self, key): ... return self[key] ... def __setattr__(self, key, value): ... self[key] = value ... >>> codec_options = CodecOptions(document_class=AttributeDict) >>> coll = db.get_collection('test', codec_options=codec_options) >>> doc = coll.find_one() >>> doc._id ObjectId('5b3016359110ea14e8c58b93') See :doc:`/examples/datetimes` for examples using the `tz_aware` and `tzinfo` options. See :class:`~bson.binary.UUIDLegacy` for examples using the `uuid_representation` option. :Parameters: - `document_class`: BSON documents returned in queries will be decoded to an instance of this class. Must be a subclass of :class:`~collections.MutableMapping`. Defaults to :class:`dict`. - `tz_aware`: If ``True``, BSON datetimes will be decoded to timezone aware instances of :class:`~datetime.datetime`. Otherwise they will be naive. Defaults to ``False``. - `uuid_representation`: The BSON representation to use when encoding and decoding instances of :class:`~uuid.UUID`. Defaults to :data:`~bson.binary.PYTHON_LEGACY`. - `unicode_decode_error_handler`: The error handler to apply when a Unicode-related error occurs during BSON decoding that would otherwise raise :exc:`UnicodeDecodeError`. Valid options include 'strict', 'replace', and 'ignore'. Defaults to 'strict'. - `tzinfo`: A :class:`~datetime.tzinfo` subclass that specifies the timezone to/from which :class:`~datetime.datetime` objects should be encoded/decoded. - `type_registry`: Instance of :class:`TypeRegistry` used to customize encoding and decoding behavior. .. versionadded:: 3.8 `type_registry` attribute. .. warning:: Care must be taken when changing `unicode_decode_error_handler` from its default value ('strict'). The 'replace' and 'ignore' modes should not be used when documents retrieved from the server will be modified in the client application and stored back to the server. """ def __new__(cls, document_class=dict, tz_aware=False, uuid_representation=PYTHON_LEGACY, unicode_decode_error_handler="strict", tzinfo=None, type_registry=None): if not (issubclass(document_class, abc.MutableMapping) or _raw_document_class(document_class)): raise TypeError("document_class must be dict, bson.son.SON, " "bson.raw_bson.RawBSONDocument, or a " "sublass of collections.MutableMapping") if not isinstance(tz_aware, bool): raise TypeError("tz_aware must be True or False") if uuid_representation not in ALL_UUID_REPRESENTATIONS: raise ValueError("uuid_representation must be a value " "from bson.binary.ALL_UUID_REPRESENTATIONS") if not isinstance(unicode_decode_error_handler, (string_type, None)): raise ValueError("unicode_decode_error_handler must be a string " "or None") if tzinfo is not None: if not isinstance(tzinfo, datetime.tzinfo): raise TypeError( "tzinfo must be an instance of datetime.tzinfo") if not tz_aware: raise ValueError( "cannot specify tzinfo without also setting tz_aware=True") type_registry = type_registry or TypeRegistry() if not isinstance(type_registry, TypeRegistry): raise TypeError("type_registry must be an instance of TypeRegistry") return tuple.__new__( cls, (document_class, tz_aware, uuid_representation, unicode_decode_error_handler, tzinfo, type_registry)) def _arguments_repr(self): """Representation of the arguments used to create this object.""" document_class_repr = ( 'dict' if self.document_class is dict else repr(self.document_class)) uuid_rep_repr = UUID_REPRESENTATION_NAMES.get(self.uuid_representation, self.uuid_representation) return ('document_class=%s, tz_aware=%r, uuid_representation=%s, ' 'unicode_decode_error_handler=%r, tzinfo=%r, ' 'type_registry=%r' % (document_class_repr, self.tz_aware, uuid_rep_repr, self.unicode_decode_error_handler, self.tzinfo, self.type_registry)) def __repr__(self): return '%s(%s)' % (self.__class__.__name__, self._arguments_repr()) def with_options(self, **kwargs): """Make a copy of this CodecOptions, overriding some options:: >>> from bson.codec_options import DEFAULT_CODEC_OPTIONS >>> DEFAULT_CODEC_OPTIONS.tz_aware False >>> options = DEFAULT_CODEC_OPTIONS.with_options(tz_aware=True) >>> options.tz_aware True .. versionadded:: 3.5 """ return CodecOptions( kwargs.get('document_class', self.document_class), kwargs.get('tz_aware', self.tz_aware), kwargs.get('uuid_representation', self.uuid_representation), kwargs.get('unicode_decode_error_handler', self.unicode_decode_error_handler), kwargs.get('tzinfo', self.tzinfo), kwargs.get('type_registry', self.type_registry) ) DEFAULT_CODEC_OPTIONS = CodecOptions() def _parse_codec_options(options): """Parse BSON codec options.""" return CodecOptions( document_class=options.get( 'document_class', DEFAULT_CODEC_OPTIONS.document_class), tz_aware=options.get( 'tz_aware', DEFAULT_CODEC_OPTIONS.tz_aware), uuid_representation=options.get( 'uuidrepresentation', DEFAULT_CODEC_OPTIONS.uuid_representation), unicode_decode_error_handler=options.get( 'unicode_decode_error_handler', DEFAULT_CODEC_OPTIONS.unicode_decode_error_handler), tzinfo=options.get('tzinfo', DEFAULT_CODEC_OPTIONS.tzinfo), type_registry=options.get( 'type_registry', DEFAULT_CODEC_OPTIONS.type_registry)) ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/bson/dbref.py ================================================ # Copyright 2009-2015 MongoDB, Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Tools for manipulating DBRefs (references to MongoDB documents).""" from copy import deepcopy from bson.py3compat import iteritems, string_type from bson.son import SON class DBRef(object): """A reference to a document stored in MongoDB. """ # DBRef isn't actually a BSON "type" so this number was arbitrarily chosen. _type_marker = 100 def __init__(self, collection, id, database=None, _extra={}, **kwargs): """Initialize a new :class:`DBRef`. Raises :class:`TypeError` if `collection` or `database` is not an instance of :class:`basestring` (:class:`str` in python 3). `database` is optional and allows references to documents to work across databases. Any additional keyword arguments will create additional fields in the resultant embedded document. :Parameters: - `collection`: name of the collection the document is stored in - `id`: the value of the document's ``"_id"`` field - `database` (optional): name of the database to reference - `**kwargs` (optional): additional keyword arguments will create additional, custom fields .. mongodoc:: dbrefs """ if not isinstance(collection, string_type): raise TypeError("collection must be an " "instance of %s" % string_type.__name__) if database is not None and not isinstance(database, string_type): raise TypeError("database must be an " "instance of %s" % string_type.__name__) self.__collection = collection self.__id = id self.__database = database kwargs.update(_extra) self.__kwargs = kwargs @property def collection(self): """Get the name of this DBRef's collection as unicode. """ return self.__collection @property def id(self): """Get this DBRef's _id. """ return self.__id @property def database(self): """Get the name of this DBRef's database. Returns None if this DBRef doesn't specify a database. """ return self.__database def __getattr__(self, key): try: return self.__kwargs[key] except KeyError: raise AttributeError(key) # Have to provide __setstate__ to avoid # infinite recursion since we override # __getattr__. def __setstate__(self, state): self.__dict__.update(state) def as_doc(self): """Get the SON document representation of this DBRef. Generally not needed by application developers """ doc = SON([("$ref", self.collection), ("$id", self.id)]) if self.database is not None: doc["$db"] = self.database doc.update(self.__kwargs) return doc def __repr__(self): extra = "".join([", %s=%r" % (k, v) for k, v in iteritems(self.__kwargs)]) if self.database is None: return "DBRef(%r, %r%s)" % (self.collection, self.id, extra) return "DBRef(%r, %r, %r%s)" % (self.collection, self.id, self.database, extra) def __eq__(self, other): if isinstance(other, DBRef): us = (self.__database, self.__collection, self.__id, self.__kwargs) them = (other.__database, other.__collection, other.__id, other.__kwargs) return us == them return NotImplemented def __ne__(self, other): return not self == other def __hash__(self): """Get a hash value for this :class:`DBRef`.""" return hash((self.__collection, self.__id, self.__database, tuple(sorted(self.__kwargs.items())))) def __deepcopy__(self, memo): """Support function for `copy.deepcopy()`.""" return DBRef(deepcopy(self.__collection, memo), deepcopy(self.__id, memo), deepcopy(self.__database, memo), deepcopy(self.__kwargs, memo)) ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/bson/decimal128.py ================================================ # Copyright 2016-present MongoDB, Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Tools for working with the BSON decimal128 type. .. versionadded:: 3.4 .. note:: The Decimal128 BSON type requires MongoDB 3.4+. """ import decimal import struct import sys from bson.py3compat import (PY3 as _PY3, string_type as _string_type) if _PY3: _from_bytes = int.from_bytes # pylint: disable=no-member, invalid-name else: import binascii def _from_bytes(value, dummy, _int=int, _hexlify=binascii.hexlify): "An implementation of int.from_bytes for python 2.x." return _int(_hexlify(value), 16) _PACK_64 = struct.Struct("= 3.3, cdecimal decimal.Context(clamp=1) # pylint: disable=unexpected-keyword-arg _CTX_OPTIONS['clamp'] = 1 except TypeError: # Python < 3.3 _CTX_OPTIONS['_clamp'] = 1 _DEC128_CTX = decimal.Context(**_CTX_OPTIONS.copy()) def create_decimal128_context(): """Returns an instance of :class:`decimal.Context` appropriate for working with IEEE-754 128-bit decimal floating point values. """ opts = _CTX_OPTIONS.copy() opts['traps'] = [] return decimal.Context(**opts) def _decimal_to_128(value): """Converts a decimal.Decimal to BID (high bits, low bits). :Parameters: - `value`: An instance of decimal.Decimal """ with decimal.localcontext(_DEC128_CTX) as ctx: value = ctx.create_decimal(value) if value.is_infinite(): return _NINF if value.is_signed() else _PINF sign, digits, exponent = value.as_tuple() if value.is_nan(): if digits: raise ValueError("NaN with debug payload is not supported") if value.is_snan(): return _NSNAN if value.is_signed() else _PSNAN return _NNAN if value.is_signed() else _PNAN significand = int("".join([str(digit) for digit in digits])) bit_length = significand.bit_length() high = 0 low = 0 for i in range(min(64, bit_length)): if significand & (1 << i): low |= 1 << i for i in range(64, bit_length): if significand & (1 << i): high |= 1 << (i - 64) biased_exponent = exponent + _EXPONENT_BIAS if high >> 49 == 1: high = high & 0x7fffffffffff high |= _EXPONENT_MASK high |= (biased_exponent & 0x3fff) << 47 else: high |= biased_exponent << 49 if sign: high |= _SIGN return high, low class Decimal128(object): """BSON Decimal128 type:: >>> Decimal128(Decimal("0.0005")) Decimal128('0.0005') >>> Decimal128("0.0005") Decimal128('0.0005') >>> Decimal128((3474527112516337664, 5)) Decimal128('0.0005') :Parameters: - `value`: An instance of :class:`decimal.Decimal`, string, or tuple of (high bits, low bits) from Binary Integer Decimal (BID) format. .. note:: :class:`~Decimal128` uses an instance of :class:`decimal.Context` configured for IEEE-754 Decimal128 when validating parameters. Signals like :class:`decimal.InvalidOperation`, :class:`decimal.Inexact`, and :class:`decimal.Overflow` are trapped and raised as exceptions:: >>> Decimal128(".13.1") Traceback (most recent call last): File "", line 1, in ... decimal.InvalidOperation: [] >>> >>> Decimal128("1E-6177") Traceback (most recent call last): File "", line 1, in ... decimal.Inexact: [] >>> >>> Decimal128("1E6145") Traceback (most recent call last): File "", line 1, in ... decimal.Overflow: [, ] To ensure the result of a calculation can always be stored as BSON Decimal128 use the context returned by :func:`create_decimal128_context`:: >>> import decimal >>> decimal128_ctx = create_decimal128_context() >>> with decimal.localcontext(decimal128_ctx) as ctx: ... Decimal128(ctx.create_decimal(".13.3")) ... Decimal128('NaN') >>> >>> with decimal.localcontext(decimal128_ctx) as ctx: ... Decimal128(ctx.create_decimal("1E-6177")) ... Decimal128('0E-6176') >>> >>> with decimal.localcontext(DECIMAL128_CTX) as ctx: ... Decimal128(ctx.create_decimal("1E6145")) ... Decimal128('Infinity') To match the behavior of MongoDB's Decimal128 implementation str(Decimal(value)) may not match str(Decimal128(value)) for NaN values:: >>> Decimal128(Decimal('NaN')) Decimal128('NaN') >>> Decimal128(Decimal('-NaN')) Decimal128('NaN') >>> Decimal128(Decimal('sNaN')) Decimal128('NaN') >>> Decimal128(Decimal('-sNaN')) Decimal128('NaN') However, :meth:`~Decimal128.to_decimal` will return the exact value:: >>> Decimal128(Decimal('NaN')).to_decimal() Decimal('NaN') >>> Decimal128(Decimal('-NaN')).to_decimal() Decimal('-NaN') >>> Decimal128(Decimal('sNaN')).to_decimal() Decimal('sNaN') >>> Decimal128(Decimal('-sNaN')).to_decimal() Decimal('-sNaN') Two instances of :class:`Decimal128` compare equal if their Binary Integer Decimal encodings are equal:: >>> Decimal128('NaN') == Decimal128('NaN') True >>> Decimal128('NaN').bid == Decimal128('NaN').bid True This differs from :class:`decimal.Decimal` comparisons for NaN:: >>> Decimal('NaN') == Decimal('NaN') False """ __slots__ = ('__high', '__low') _type_marker = 19 def __init__(self, value): if isinstance(value, (_string_type, decimal.Decimal)): self.__high, self.__low = _decimal_to_128(value) elif isinstance(value, (list, tuple)): if len(value) != 2: raise ValueError('Invalid size for creation of Decimal128 ' 'from list or tuple. Must have exactly 2 ' 'elements.') self.__high, self.__low = value else: raise TypeError("Cannot convert %r to Decimal128" % (value,)) def to_decimal(self): """Returns an instance of :class:`decimal.Decimal` for this :class:`Decimal128`. """ high = self.__high low = self.__low sign = 1 if (high & _SIGN) else 0 if (high & _SNAN) == _SNAN: return decimal.Decimal((sign, (), 'N')) elif (high & _NAN) == _NAN: return decimal.Decimal((sign, (), 'n')) elif (high & _INF) == _INF: return decimal.Decimal((sign, (), 'F')) if (high & _EXPONENT_MASK) == _EXPONENT_MASK: exponent = ((high & 0x1fffe00000000000) >> 47) - _EXPONENT_BIAS return decimal.Decimal((sign, (0,), exponent)) else: exponent = ((high & 0x7fff800000000000) >> 49) - _EXPONENT_BIAS arr = bytearray(15) mask = 0x00000000000000ff for i in range(14, 6, -1): arr[i] = (low & mask) >> ((14 - i) << 3) mask = mask << 8 mask = 0x00000000000000ff for i in range(6, 0, -1): arr[i] = (high & mask) >> ((6 - i) << 3) mask = mask << 8 mask = 0x0001000000000000 arr[0] = (high & mask) >> 48 # cdecimal only accepts a tuple for digits. digits = tuple( int(digit) for digit in str(_from_bytes(arr, 'big'))) with decimal.localcontext(_DEC128_CTX) as ctx: return ctx.create_decimal((sign, digits, exponent)) @classmethod def from_bid(cls, value): """Create an instance of :class:`Decimal128` from Binary Integer Decimal string. :Parameters: - `value`: 16 byte string (128-bit IEEE 754-2008 decimal floating point in Binary Integer Decimal (BID) format). """ if not isinstance(value, bytes): raise TypeError("value must be an instance of bytes") if len(value) != 16: raise ValueError("value must be exactly 16 bytes") return cls((_UNPACK_64(value[8:])[0], _UNPACK_64(value[:8])[0])) @property def bid(self): """The Binary Integer Decimal (BID) encoding of this instance.""" return _PACK_64(self.__low) + _PACK_64(self.__high) def __str__(self): dec = self.to_decimal() if dec.is_nan(): # Required by the drivers spec to match MongoDB behavior. return "NaN" return str(dec) def __repr__(self): return "Decimal128('%s')" % (str(self),) def __setstate__(self, value): self.__high, self.__low = value def __getstate__(self): return self.__high, self.__low def __eq__(self, other): if isinstance(other, Decimal128): return self.bid == other.bid return NotImplemented def __ne__(self, other): return not self == other ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/bson/errors.py ================================================ # Copyright 2009-present MongoDB, Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Exceptions raised by the BSON package.""" class BSONError(Exception): """Base class for all BSON exceptions. """ class InvalidBSON(BSONError): """Raised when trying to create a BSON object from invalid data. """ class InvalidStringData(BSONError): """Raised when trying to encode a string containing non-UTF8 data. """ class InvalidDocument(BSONError): """Raised when trying to create a BSON object from an invalid document. """ class InvalidId(BSONError): """Raised when trying to create an ObjectId from invalid data. """ ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/bson/int64.py ================================================ # Copyright 2014-2015 MongoDB, Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """A BSON wrapper for long (int in python3)""" from bson.py3compat import PY3 if PY3: long = int class Int64(long): """Representation of the BSON int64 type. This is necessary because every integral number is an :class:`int` in Python 3. Small integral numbers are encoded to BSON int32 by default, but Int64 numbers will always be encoded to BSON int64. :Parameters: - `value`: the numeric value to represent """ _type_marker = 18 ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/bson/json_util.py ================================================ # Copyright 2009-present MongoDB, Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Tools for using Python's :mod:`json` module with BSON documents. This module provides two helper methods `dumps` and `loads` that wrap the native :mod:`json` methods and provide explicit BSON conversion to and from JSON. :class:`~bson.json_util.JSONOptions` provides a way to control how JSON is emitted and parsed, with the default being the legacy PyMongo format. :mod:`~bson.json_util` can also generate Canonical or Relaxed `Extended JSON`_ when :const:`CANONICAL_JSON_OPTIONS` or :const:`RELAXED_JSON_OPTIONS` is provided, respectively. .. _Extended JSON: https://github.com/mongodb/specifications/blob/master/source/extended-json.rst Example usage (deserialization): .. doctest:: >>> from bson.json_util import loads >>> loads('[{"foo": [1, 2]}, {"bar": {"hello": "world"}}, {"code": {"$scope": {}, "$code": "function x() { return 1; }"}}, {"bin": {"$type": "80", "$binary": "AQIDBA=="}}]') [{u'foo': [1, 2]}, {u'bar': {u'hello': u'world'}}, {u'code': Code('function x() { return 1; }', {})}, {u'bin': Binary('...', 128)}] Example usage (serialization): .. doctest:: >>> from bson import Binary, Code >>> from bson.json_util import dumps >>> dumps([{'foo': [1, 2]}, ... {'bar': {'hello': 'world'}}, ... {'code': Code("function x() { return 1; }", {})}, ... {'bin': Binary(b"\x01\x02\x03\x04")}]) '[{"foo": [1, 2]}, {"bar": {"hello": "world"}}, {"code": {"$code": "function x() { return 1; }", "$scope": {}}}, {"bin": {"$binary": "AQIDBA==", "$type": "00"}}]' Example usage (with :const:`CANONICAL_JSON_OPTIONS`): .. doctest:: >>> from bson import Binary, Code >>> from bson.json_util import dumps, CANONICAL_JSON_OPTIONS >>> dumps([{'foo': [1, 2]}, ... {'bar': {'hello': 'world'}}, ... {'code': Code("function x() { return 1; }")}, ... {'bin': Binary(b"\x01\x02\x03\x04")}], ... json_options=CANONICAL_JSON_OPTIONS) '[{"foo": [{"$numberInt": "1"}, {"$numberInt": "2"}]}, {"bar": {"hello": "world"}}, {"code": {"$code": "function x() { return 1; }"}}, {"bin": {"$binary": {"base64": "AQIDBA==", "subType": "00"}}}]' Example usage (with :const:`RELAXED_JSON_OPTIONS`): .. doctest:: >>> from bson import Binary, Code >>> from bson.json_util import dumps, RELAXED_JSON_OPTIONS >>> dumps([{'foo': [1, 2]}, ... {'bar': {'hello': 'world'}}, ... {'code': Code("function x() { return 1; }")}, ... {'bin': Binary(b"\x01\x02\x03\x04")}], ... json_options=RELAXED_JSON_OPTIONS) '[{"foo": [1, 2]}, {"bar": {"hello": "world"}}, {"code": {"$code": "function x() { return 1; }"}}, {"bin": {"$binary": {"base64": "AQIDBA==", "subType": "00"}}}]' Alternatively, you can manually pass the `default` to :func:`json.dumps`. It won't handle :class:`~bson.binary.Binary` and :class:`~bson.code.Code` instances (as they are extended strings you can't provide custom defaults), but it will be faster as there is less recursion. .. note:: If your application does not need the flexibility offered by :class:`JSONOptions` and spends a large amount of time in the `json_util` module, look to `python-bsonjs `_ for a nice performance improvement. `python-bsonjs` is a fast BSON to MongoDB Extended JSON converter for Python built on top of `libbson `_. `python-bsonjs` works best with PyMongo when using :class:`~bson.raw_bson.RawBSONDocument`. .. versionchanged:: 2.8 The output format for :class:`~bson.timestamp.Timestamp` has changed from '{"t": , "i": }' to '{"$timestamp": {"t": , "i": }}'. This new format will be decoded to an instance of :class:`~bson.timestamp.Timestamp`. The old format will continue to be decoded to a python dict as before. Encoding to the old format is no longer supported as it was never correct and loses type information. Added support for $numberLong and $undefined - new in MongoDB 2.6 - and parsing $date in ISO-8601 format. .. versionchanged:: 2.7 Preserves order when rendering SON, Timestamp, Code, Binary, and DBRef instances. .. versionchanged:: 2.3 Added dumps and loads helpers to automatically handle conversion to and from json and supports :class:`~bson.binary.Binary` and :class:`~bson.code.Code` """ import base64 import datetime import json import math import re import sys import uuid from pymongo.errors import ConfigurationError import bson from bson import EPOCH_AWARE, EPOCH_NAIVE, RE_TYPE, SON from bson.binary import (Binary, JAVA_LEGACY, CSHARP_LEGACY, OLD_UUID_SUBTYPE, UUID_SUBTYPE) from bson.code import Code from bson.codec_options import CodecOptions from bson.dbref import DBRef from bson.decimal128 import Decimal128 from bson.int64 import Int64 from bson.max_key import MaxKey from bson.min_key import MinKey from bson.objectid import ObjectId from bson.py3compat import (PY3, iteritems, integer_types, string_type, text_type) from bson.regex import Regex from bson.timestamp import Timestamp from bson.tz_util import utc _RE_OPT_TABLE = { "i": re.I, "l": re.L, "m": re.M, "s": re.S, "u": re.U, "x": re.X, } # Dollar-prefixed keys which may appear in DBRefs. _DBREF_KEYS = frozenset(['$id', '$ref', '$db']) class DatetimeRepresentation: LEGACY = 0 """Legacy MongoDB Extended JSON datetime representation. :class:`datetime.datetime` instances will be encoded to JSON in the format `{"$date": }`, where `dateAsMilliseconds` is a 64-bit signed integer giving the number of milliseconds since the Unix epoch UTC. This was the default encoding before PyMongo version 3.4. .. versionadded:: 3.4 """ NUMBERLONG = 1 """NumberLong datetime representation. :class:`datetime.datetime` instances will be encoded to JSON in the format `{"$date": {"$numberLong": ""}}`, where `dateAsMilliseconds` is the string representation of a 64-bit signed integer giving the number of milliseconds since the Unix epoch UTC. .. versionadded:: 3.4 """ ISO8601 = 2 """ISO-8601 datetime representation. :class:`datetime.datetime` instances greater than or equal to the Unix epoch UTC will be encoded to JSON in the format `{"$date": ""}`. :class:`datetime.datetime` instances before the Unix epoch UTC will be encoded as if the datetime representation is :const:`~DatetimeRepresentation.NUMBERLONG`. .. versionadded:: 3.4 """ class JSONMode: LEGACY = 0 """Legacy Extended JSON representation. In this mode, :func:`~bson.json_util.dumps` produces PyMongo's legacy non-standard JSON output. Consider using :const:`~bson.json_util.JSONMode.RELAXED` or :const:`~bson.json_util.JSONMode.CANONICAL` instead. .. versionadded:: 3.5 """ RELAXED = 1 """Relaxed Extended JSON representation. In this mode, :func:`~bson.json_util.dumps` produces Relaxed Extended JSON, a mostly JSON-like format. Consider using this for things like a web API, where one is sending a document (or a projection of a document) that only uses ordinary JSON type primitives. In particular, the ``int``, :class:`~bson.int64.Int64`, and ``float`` numeric types are represented in the native JSON number format. This output is also the most human readable and is useful for debugging and documentation. .. seealso:: The specification for Relaxed `Extended JSON`_. .. versionadded:: 3.5 """ CANONICAL = 2 """Canonical Extended JSON representation. In this mode, :func:`~bson.json_util.dumps` produces Canonical Extended JSON, a type preserving format. Consider using this for things like testing, where one has to precisely specify expected types in JSON. In particular, the ``int``, :class:`~bson.int64.Int64`, and ``float`` numeric types are encoded with type wrappers. .. seealso:: The specification for Canonical `Extended JSON`_. .. versionadded:: 3.5 """ class JSONOptions(CodecOptions): """Encapsulates JSON options for :func:`dumps` and :func:`loads`. :Parameters: - `strict_number_long`: If ``True``, :class:`~bson.int64.Int64` objects are encoded to MongoDB Extended JSON's *Strict mode* type `NumberLong`, ie ``'{"$numberLong": "" }'``. Otherwise they will be encoded as an `int`. Defaults to ``False``. - `datetime_representation`: The representation to use when encoding instances of :class:`datetime.datetime`. Defaults to :const:`~DatetimeRepresentation.LEGACY`. - `strict_uuid`: If ``True``, :class:`uuid.UUID` object are encoded to MongoDB Extended JSON's *Strict mode* type `Binary`. Otherwise it will be encoded as ``'{"$uuid": "" }'``. Defaults to ``False``. - `json_mode`: The :class:`JSONMode` to use when encoding BSON types to Extended JSON. Defaults to :const:`~JSONMode.LEGACY`. - `document_class`: BSON documents returned by :func:`loads` will be decoded to an instance of this class. Must be a subclass of :class:`collections.MutableMapping`. Defaults to :class:`dict`. - `uuid_representation`: The BSON representation to use when encoding and decoding instances of :class:`uuid.UUID`. Defaults to :const:`~bson.binary.PYTHON_LEGACY`. - `tz_aware`: If ``True``, MongoDB Extended JSON's *Strict mode* type `Date` will be decoded to timezone aware instances of :class:`datetime.datetime`. Otherwise they will be naive. Defaults to ``True``. - `tzinfo`: A :class:`datetime.tzinfo` subclass that specifies the timezone from which :class:`~datetime.datetime` objects should be decoded. Defaults to :const:`~bson.tz_util.utc`. - `args`: arguments to :class:`~bson.codec_options.CodecOptions` - `kwargs`: arguments to :class:`~bson.codec_options.CodecOptions` .. seealso:: The specification for Relaxed and Canonical `Extended JSON`_. .. versionadded:: 3.4 .. versionchanged:: 3.5 Accepts the optional parameter `json_mode`. """ def __new__(cls, strict_number_long=False, datetime_representation=DatetimeRepresentation.LEGACY, strict_uuid=False, json_mode=JSONMode.LEGACY, *args, **kwargs): kwargs["tz_aware"] = kwargs.get("tz_aware", True) if kwargs["tz_aware"]: kwargs["tzinfo"] = kwargs.get("tzinfo", utc) if datetime_representation not in (DatetimeRepresentation.LEGACY, DatetimeRepresentation.NUMBERLONG, DatetimeRepresentation.ISO8601): raise ConfigurationError( "JSONOptions.datetime_representation must be one of LEGACY, " "NUMBERLONG, or ISO8601 from DatetimeRepresentation.") self = super(JSONOptions, cls).__new__(cls, *args, **kwargs) if json_mode not in (JSONMode.LEGACY, JSONMode.RELAXED, JSONMode.CANONICAL): raise ConfigurationError( "JSONOptions.json_mode must be one of LEGACY, RELAXED, " "or CANONICAL from JSONMode.") self.json_mode = json_mode if self.json_mode == JSONMode.RELAXED: self.strict_number_long = False self.datetime_representation = DatetimeRepresentation.ISO8601 self.strict_uuid = True elif self.json_mode == JSONMode.CANONICAL: self.strict_number_long = True self.datetime_representation = DatetimeRepresentation.NUMBERLONG self.strict_uuid = True else: self.strict_number_long = strict_number_long self.datetime_representation = datetime_representation self.strict_uuid = strict_uuid return self def _arguments_repr(self): return ('strict_number_long=%r, ' 'datetime_representation=%r, ' 'strict_uuid=%r, json_mode=%r, %s' % ( self.strict_number_long, self.datetime_representation, self.strict_uuid, self.json_mode, super(JSONOptions, self)._arguments_repr())) LEGACY_JSON_OPTIONS = JSONOptions(json_mode=JSONMode.LEGACY) """:class:`JSONOptions` for encoding to PyMongo's legacy JSON format. .. seealso:: The documentation for :const:`bson.json_util.JSONMode.LEGACY`. .. versionadded:: 3.5 """ DEFAULT_JSON_OPTIONS = LEGACY_JSON_OPTIONS """The default :class:`JSONOptions` for JSON encoding/decoding. The same as :const:`LEGACY_JSON_OPTIONS`. This will change to :const:`RELAXED_JSON_OPTIONS` in a future release. .. versionadded:: 3.4 """ CANONICAL_JSON_OPTIONS = JSONOptions(json_mode=JSONMode.CANONICAL) """:class:`JSONOptions` for Canonical Extended JSON. .. seealso:: The documentation for :const:`bson.json_util.JSONMode.CANONICAL`. .. versionadded:: 3.5 """ RELAXED_JSON_OPTIONS = JSONOptions(json_mode=JSONMode.RELAXED) """:class:`JSONOptions` for Relaxed Extended JSON. .. seealso:: The documentation for :const:`bson.json_util.JSONMode.RELAXED`. .. versionadded:: 3.5 """ STRICT_JSON_OPTIONS = JSONOptions( strict_number_long=True, datetime_representation=DatetimeRepresentation.ISO8601, strict_uuid=True) """**DEPRECATED** - :class:`JSONOptions` for MongoDB Extended JSON's *Strict mode* encoding. .. versionadded:: 3.4 .. versionchanged:: 3.5 Deprecated. Use :const:`RELAXED_JSON_OPTIONS` or :const:`CANONICAL_JSON_OPTIONS` instead. """ def dumps(obj, *args, **kwargs): """Helper function that wraps :func:`json.dumps`. Recursive function that handles all BSON types including :class:`~bson.binary.Binary` and :class:`~bson.code.Code`. :Parameters: - `json_options`: A :class:`JSONOptions` instance used to modify the encoding of MongoDB Extended JSON types. Defaults to :const:`DEFAULT_JSON_OPTIONS`. .. versionchanged:: 3.4 Accepts optional parameter `json_options`. See :class:`JSONOptions`. .. versionchanged:: 2.7 Preserves order when rendering SON, Timestamp, Code, Binary, and DBRef instances. """ json_options = kwargs.pop("json_options", DEFAULT_JSON_OPTIONS) return json.dumps(_json_convert(obj, json_options), *args, **kwargs) def loads(s, *args, **kwargs): """Helper function that wraps :func:`json.loads`. Automatically passes the object_hook for BSON type conversion. Raises ``TypeError``, ``ValueError``, ``KeyError``, or :exc:`~bson.errors.InvalidId` on invalid MongoDB Extended JSON. :Parameters: - `json_options`: A :class:`JSONOptions` instance used to modify the decoding of MongoDB Extended JSON types. Defaults to :const:`DEFAULT_JSON_OPTIONS`. .. versionchanged:: 3.5 Parses Relaxed and Canonical Extended JSON as well as PyMongo's legacy format. Now raises ``TypeError`` or ``ValueError`` when parsing JSON type wrappers with values of the wrong type or any extra keys. .. versionchanged:: 3.4 Accepts optional parameter `json_options`. See :class:`JSONOptions`. """ json_options = kwargs.pop("json_options", DEFAULT_JSON_OPTIONS) kwargs["object_pairs_hook"] = lambda pairs: object_pairs_hook( pairs, json_options) return json.loads(s, *args, **kwargs) def _json_convert(obj, json_options=DEFAULT_JSON_OPTIONS): """Recursive helper method that converts BSON types so they can be converted into json. """ if hasattr(obj, 'iteritems') or hasattr(obj, 'items'): # PY3 support return SON(((k, _json_convert(v, json_options)) for k, v in iteritems(obj))) elif hasattr(obj, '__iter__') and not isinstance(obj, (text_type, bytes)): return list((_json_convert(v, json_options) for v in obj)) try: return default(obj, json_options) except TypeError: return obj def object_pairs_hook(pairs, json_options=DEFAULT_JSON_OPTIONS): return object_hook(json_options.document_class(pairs), json_options) def object_hook(dct, json_options=DEFAULT_JSON_OPTIONS): if "$oid" in dct: return _parse_canonical_oid(dct) if "$ref" in dct: return _parse_canonical_dbref(dct) if "$date" in dct: return _parse_canonical_datetime(dct, json_options) if "$regex" in dct: return _parse_legacy_regex(dct) if "$minKey" in dct: return _parse_canonical_minkey(dct) if "$maxKey" in dct: return _parse_canonical_maxkey(dct) if "$binary" in dct: if "$type" in dct: return _parse_legacy_binary(dct, json_options) else: return _parse_canonical_binary(dct, json_options) if "$code" in dct: return _parse_canonical_code(dct) if "$uuid" in dct: return _parse_legacy_uuid(dct) if "$undefined" in dct: return None if "$numberLong" in dct: return _parse_canonical_int64(dct) if "$timestamp" in dct: tsp = dct["$timestamp"] return Timestamp(tsp["t"], tsp["i"]) if "$numberDecimal" in dct: return _parse_canonical_decimal128(dct) if "$dbPointer" in dct: return _parse_canonical_dbpointer(dct) if "$regularExpression" in dct: return _parse_canonical_regex(dct) if "$symbol" in dct: return _parse_canonical_symbol(dct) if "$numberInt" in dct: return _parse_canonical_int32(dct) if "$numberDouble" in dct: return _parse_canonical_double(dct) return dct def _parse_legacy_regex(doc): pattern = doc["$regex"] # Check if this is the $regex query operator. if isinstance(pattern, Regex): return doc flags = 0 # PyMongo always adds $options but some other tools may not. for opt in doc.get("$options", ""): flags |= _RE_OPT_TABLE.get(opt, 0) return Regex(pattern, flags) def _parse_legacy_uuid(doc): """Decode a JSON legacy $uuid to Python UUID.""" if len(doc) != 1: raise TypeError('Bad $uuid, extra field(s): %s' % (doc,)) return uuid.UUID(doc["$uuid"]) def _binary_or_uuid(data, subtype, json_options): # special handling for UUID if subtype == OLD_UUID_SUBTYPE: if json_options.uuid_representation == CSHARP_LEGACY: return uuid.UUID(bytes_le=data) if json_options.uuid_representation == JAVA_LEGACY: data = data[7::-1] + data[:7:-1] return uuid.UUID(bytes=data) if subtype == UUID_SUBTYPE: return uuid.UUID(bytes=data) if PY3 and subtype == 0: return data return Binary(data, subtype) def _parse_legacy_binary(doc, json_options): if isinstance(doc["$type"], int): doc["$type"] = "%02x" % doc["$type"] subtype = int(doc["$type"], 16) if subtype >= 0xffffff80: # Handle mongoexport values subtype = int(doc["$type"][6:], 16) data = base64.b64decode(doc["$binary"].encode()) return _binary_or_uuid(data, subtype, json_options) def _parse_canonical_binary(doc, json_options): binary = doc["$binary"] b64 = binary["base64"] subtype = binary["subType"] if not isinstance(b64, string_type): raise TypeError('$binary base64 must be a string: %s' % (doc,)) if not isinstance(subtype, string_type) or len(subtype) > 2: raise TypeError('$binary subType must be a string at most 2 ' 'characters: %s' % (doc,)) if len(binary) != 2: raise TypeError('$binary must include only "base64" and "subType" ' 'components: %s' % (doc,)) data = base64.b64decode(b64.encode()) return _binary_or_uuid(data, int(subtype, 16), json_options) def _parse_canonical_datetime(doc, json_options): """Decode a JSON datetime to python datetime.datetime.""" dtm = doc["$date"] if len(doc) != 1: raise TypeError('Bad $date, extra field(s): %s' % (doc,)) # mongoexport 2.6 and newer if isinstance(dtm, string_type): # Parse offset if dtm[-1] == 'Z': dt = dtm[:-1] offset = 'Z' elif dtm[-6] in ('+', '-') and dtm[-3] == ':': # (+|-)HH:MM dt = dtm[:-6] offset = dtm[-6:] elif dtm[-5] in ('+', '-'): # (+|-)HHMM dt = dtm[:-5] offset = dtm[-5:] elif dtm[-3] in ('+', '-'): # (+|-)HH dt = dtm[:-3] offset = dtm[-3:] else: dt = dtm offset = '' # Parse the optional factional seconds portion. dot_index = dt.rfind('.') microsecond = 0 if dot_index != -1: microsecond = int(float(dt[dot_index:]) * 1000000) dt = dt[:dot_index] aware = datetime.datetime.strptime( dt, "%Y-%m-%dT%H:%M:%S").replace(microsecond=microsecond, tzinfo=utc) if offset and offset != 'Z': if len(offset) == 6: hours, minutes = offset[1:].split(':') secs = (int(hours) * 3600 + int(minutes) * 60) elif len(offset) == 5: secs = (int(offset[1:3]) * 3600 + int(offset[3:]) * 60) elif len(offset) == 3: secs = int(offset[1:3]) * 3600 if offset[0] == "-": secs *= -1 aware = aware - datetime.timedelta(seconds=secs) if json_options.tz_aware: if json_options.tzinfo: aware = aware.astimezone(json_options.tzinfo) return aware else: return aware.replace(tzinfo=None) return bson._millis_to_datetime(int(dtm), json_options) def _parse_canonical_oid(doc): """Decode a JSON ObjectId to bson.objectid.ObjectId.""" if len(doc) != 1: raise TypeError('Bad $oid, extra field(s): %s' % (doc,)) return ObjectId(doc['$oid']) def _parse_canonical_symbol(doc): """Decode a JSON symbol to Python string.""" symbol = doc['$symbol'] if len(doc) != 1: raise TypeError('Bad $symbol, extra field(s): %s' % (doc,)) return text_type(symbol) def _parse_canonical_code(doc): """Decode a JSON code to bson.code.Code.""" for key in doc: if key not in ('$code', '$scope'): raise TypeError('Bad $code, extra field(s): %s' % (doc,)) return Code(doc['$code'], scope=doc.get('$scope')) def _parse_canonical_regex(doc): """Decode a JSON regex to bson.regex.Regex.""" regex = doc['$regularExpression'] if len(doc) != 1: raise TypeError('Bad $regularExpression, extra field(s): %s' % (doc,)) if len(regex) != 2: raise TypeError('Bad $regularExpression must include only "pattern"' 'and "options" components: %s' % (doc,)) return Regex(regex['pattern'], regex['options']) def _parse_canonical_dbref(doc): """Decode a JSON DBRef to bson.dbref.DBRef.""" for key in doc: if key.startswith('$') and key not in _DBREF_KEYS: # Other keys start with $, so dct cannot be parsed as a DBRef. return doc return DBRef(doc.pop('$ref'), doc.pop('$id'), database=doc.pop('$db', None), **doc) def _parse_canonical_dbpointer(doc): """Decode a JSON (deprecated) DBPointer to bson.dbref.DBRef.""" dbref = doc['$dbPointer'] if len(doc) != 1: raise TypeError('Bad $dbPointer, extra field(s): %s' % (doc,)) if isinstance(dbref, DBRef): dbref_doc = dbref.as_doc() # DBPointer must not contain $db in its value. if dbref.database is not None: raise TypeError( 'Bad $dbPointer, extra field $db: %s' % (dbref_doc,)) if not isinstance(dbref.id, ObjectId): raise TypeError( 'Bad $dbPointer, $id must be an ObjectId: %s' % (dbref_doc,)) if len(dbref_doc) != 2: raise TypeError( 'Bad $dbPointer, extra field(s) in DBRef: %s' % (dbref_doc,)) return dbref else: raise TypeError('Bad $dbPointer, expected a DBRef: %s' % (doc,)) def _parse_canonical_int32(doc): """Decode a JSON int32 to python int.""" i_str = doc['$numberInt'] if len(doc) != 1: raise TypeError('Bad $numberInt, extra field(s): %s' % (doc,)) if not isinstance(i_str, string_type): raise TypeError('$numberInt must be string: %s' % (doc,)) return int(i_str) def _parse_canonical_int64(doc): """Decode a JSON int64 to bson.int64.Int64.""" l_str = doc['$numberLong'] if len(doc) != 1: raise TypeError('Bad $numberLong, extra field(s): %s' % (doc,)) return Int64(l_str) def _parse_canonical_double(doc): """Decode a JSON double to python float.""" d_str = doc['$numberDouble'] if len(doc) != 1: raise TypeError('Bad $numberDouble, extra field(s): %s' % (doc,)) if not isinstance(d_str, string_type): raise TypeError('$numberDouble must be string: %s' % (doc,)) return float(d_str) def _parse_canonical_decimal128(doc): """Decode a JSON decimal128 to bson.decimal128.Decimal128.""" d_str = doc['$numberDecimal'] if len(doc) != 1: raise TypeError('Bad $numberDecimal, extra field(s): %s' % (doc,)) if not isinstance(d_str, string_type): raise TypeError('$numberDecimal must be string: %s' % (doc,)) return Decimal128(d_str) def _parse_canonical_minkey(doc): """Decode a JSON MinKey to bson.min_key.MinKey.""" if doc['$minKey'] is not 1: raise TypeError('$minKey value must be 1: %s' % (doc,)) if len(doc) != 1: raise TypeError('Bad $minKey, extra field(s): %s' % (doc,)) return MinKey() def _parse_canonical_maxkey(doc): """Decode a JSON MaxKey to bson.max_key.MaxKey.""" if doc['$maxKey'] is not 1: raise TypeError('$maxKey value must be 1: %s', (doc,)) if len(doc) != 1: raise TypeError('Bad $minKey, extra field(s): %s' % (doc,)) return MaxKey() def _encode_binary(data, subtype, json_options): if json_options.json_mode == JSONMode.LEGACY: return SON([ ('$binary', base64.b64encode(data).decode()), ('$type', "%02x" % subtype)]) return {'$binary': SON([ ('base64', base64.b64encode(data).decode()), ('subType', "%02x" % subtype)])} def default(obj, json_options=DEFAULT_JSON_OPTIONS): # We preserve key order when rendering SON, DBRef, etc. as JSON by # returning a SON for those types instead of a dict. if isinstance(obj, ObjectId): return {"$oid": str(obj)} if isinstance(obj, DBRef): return _json_convert(obj.as_doc(), json_options=json_options) if isinstance(obj, datetime.datetime): if (json_options.datetime_representation == DatetimeRepresentation.ISO8601): if not obj.tzinfo: obj = obj.replace(tzinfo=utc) if obj >= EPOCH_AWARE: off = obj.tzinfo.utcoffset(obj) if (off.days, off.seconds, off.microseconds) == (0, 0, 0): tz_string = 'Z' else: tz_string = obj.strftime('%z') millis = int(obj.microsecond / 1000) fracsecs = ".%03d" % (millis,) if millis else "" return {"$date": "%s%s%s" % ( obj.strftime("%Y-%m-%dT%H:%M:%S"), fracsecs, tz_string)} millis = bson._datetime_to_millis(obj) if (json_options.datetime_representation == DatetimeRepresentation.LEGACY): return {"$date": millis} return {"$date": {"$numberLong": str(millis)}} if json_options.strict_number_long and isinstance(obj, Int64): return {"$numberLong": str(obj)} if isinstance(obj, (RE_TYPE, Regex)): flags = "" if obj.flags & re.IGNORECASE: flags += "i" if obj.flags & re.LOCALE: flags += "l" if obj.flags & re.MULTILINE: flags += "m" if obj.flags & re.DOTALL: flags += "s" if obj.flags & re.UNICODE: flags += "u" if obj.flags & re.VERBOSE: flags += "x" if isinstance(obj.pattern, text_type): pattern = obj.pattern else: pattern = obj.pattern.decode('utf-8') if json_options.json_mode == JSONMode.LEGACY: return SON([("$regex", pattern), ("$options", flags)]) return {'$regularExpression': SON([("pattern", pattern), ("options", flags)])} if isinstance(obj, MinKey): return {"$minKey": 1} if isinstance(obj, MaxKey): return {"$maxKey": 1} if isinstance(obj, Timestamp): return {"$timestamp": SON([("t", obj.time), ("i", obj.inc)])} if isinstance(obj, Code): if obj.scope is None: return {'$code': str(obj)} return SON([ ('$code', str(obj)), ('$scope', _json_convert(obj.scope, json_options))]) if isinstance(obj, Binary): return _encode_binary(obj, obj.subtype, json_options) if PY3 and isinstance(obj, bytes): return _encode_binary(obj, 0, json_options) if isinstance(obj, uuid.UUID): if json_options.strict_uuid: data = obj.bytes subtype = OLD_UUID_SUBTYPE if json_options.uuid_representation == CSHARP_LEGACY: data = obj.bytes_le elif json_options.uuid_representation == JAVA_LEGACY: data = data[7::-1] + data[:7:-1] elif json_options.uuid_representation == UUID_SUBTYPE: subtype = UUID_SUBTYPE return _encode_binary(data, subtype, json_options) else: return {"$uuid": obj.hex} if isinstance(obj, Decimal128): return {"$numberDecimal": str(obj)} if isinstance(obj, bool): return obj if (json_options.json_mode == JSONMode.CANONICAL and isinstance(obj, integer_types)): if -2 ** 31 <= obj < 2 ** 31: return {'$numberInt': text_type(obj)} return {'$numberLong': text_type(obj)} if json_options.json_mode != JSONMode.LEGACY and isinstance(obj, float): if math.isnan(obj): return {'$numberDouble': 'NaN'} elif math.isinf(obj): representation = 'Infinity' if obj > 0 else '-Infinity' return {'$numberDouble': representation} elif json_options.json_mode == JSONMode.CANONICAL: # repr() will return the shortest string guaranteed to produce the # original value, when float() is called on it. str produces a # shorter string in Python 2. return {'$numberDouble': text_type(repr(obj))} raise TypeError("%r is not JSON serializable" % obj) ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/bson/max_key.py ================================================ # Copyright 2010-present MongoDB, Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Representation for the MongoDB internal MaxKey type. """ class MaxKey(object): """MongoDB internal MaxKey type. .. versionchanged:: 2.7 ``MaxKey`` now implements comparison operators. """ _type_marker = 127 def __eq__(self, other): return isinstance(other, MaxKey) def __hash__(self): return hash(self._type_marker) def __ne__(self, other): return not self == other def __le__(self, other): return isinstance(other, MaxKey) def __lt__(self, dummy): return False def __ge__(self, dummy): return True def __gt__(self, other): return not isinstance(other, MaxKey) def __repr__(self): return "MaxKey()" ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/bson/min_key.py ================================================ # Copyright 2010-present MongoDB, Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Representation for the MongoDB internal MinKey type. """ class MinKey(object): """MongoDB internal MinKey type. .. versionchanged:: 2.7 ``MinKey`` now implements comparison operators. """ _type_marker = 255 def __eq__(self, other): return isinstance(other, MinKey) def __hash__(self): return hash(self._type_marker) def __ne__(self, other): return not self == other def __le__(self, dummy): return True def __lt__(self, other): return not isinstance(other, MinKey) def __ge__(self, other): return isinstance(other, MinKey) def __gt__(self, dummy): return False def __repr__(self): return "MinKey()" ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/bson/objectid.py ================================================ # Copyright 2009-2015 MongoDB, Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Tools for working with MongoDB `ObjectIds `_. """ import binascii import calendar import datetime import os import struct import threading import time from random import SystemRandom from bson.errors import InvalidId from bson.py3compat import PY3, bytes_from_hex, string_type, text_type from bson.tz_util import utc _MAX_COUNTER_VALUE = 0xFFFFFF def _raise_invalid_id(oid): raise InvalidId( "%r is not a valid ObjectId, it must be a 12-byte input" " or a 24-character hex string" % oid) def _random_bytes(): """Get the 5-byte random field of an ObjectId.""" return os.urandom(5) class ObjectId(object): """A MongoDB ObjectId. """ _pid = os.getpid() _inc = SystemRandom().randint(0, _MAX_COUNTER_VALUE) _inc_lock = threading.Lock() __random = _random_bytes() __slots__ = ('__id',) _type_marker = 7 def __init__(self, oid=None): """Initialize a new ObjectId. An ObjectId is a 12-byte unique identifier consisting of: - a 4-byte value representing the seconds since the Unix epoch, - a 5-byte random value, - a 3-byte counter, starting with a random value. By default, ``ObjectId()`` creates a new unique identifier. The optional parameter `oid` can be an :class:`ObjectId`, or any 12 :class:`bytes` or, in Python 2, any 12-character :class:`str`. For example, the 12 bytes b'foo-bar-quux' do not follow the ObjectId specification but they are acceptable input:: >>> ObjectId(b'foo-bar-quux') ObjectId('666f6f2d6261722d71757578') `oid` can also be a :class:`unicode` or :class:`str` of 24 hex digits:: >>> ObjectId('0123456789ab0123456789ab') ObjectId('0123456789ab0123456789ab') >>> >>> # A u-prefixed unicode literal: >>> ObjectId(u'0123456789ab0123456789ab') ObjectId('0123456789ab0123456789ab') Raises :class:`~bson.errors.InvalidId` if `oid` is not 12 bytes nor 24 hex digits, or :class:`TypeError` if `oid` is not an accepted type. :Parameters: - `oid` (optional): a valid ObjectId. .. mongodoc:: objectids .. versionchanged:: 3.8 :class:`~bson.objectid.ObjectId` now implements the `ObjectID specification version 0.2 `_. """ if oid is None: self.__generate() elif isinstance(oid, bytes) and len(oid) == 12: self.__id = oid else: self.__validate(oid) @classmethod def from_datetime(cls, generation_time): """Create a dummy ObjectId instance with a specific generation time. This method is useful for doing range queries on a field containing :class:`ObjectId` instances. .. warning:: It is not safe to insert a document containing an ObjectId generated using this method. This method deliberately eliminates the uniqueness guarantee that ObjectIds generally provide. ObjectIds generated with this method should be used exclusively in queries. `generation_time` will be converted to UTC. Naive datetime instances will be treated as though they already contain UTC. An example using this helper to get documents where ``"_id"`` was generated before January 1, 2010 would be: >>> gen_time = datetime.datetime(2010, 1, 1) >>> dummy_id = ObjectId.from_datetime(gen_time) >>> result = collection.find({"_id": {"$lt": dummy_id}}) :Parameters: - `generation_time`: :class:`~datetime.datetime` to be used as the generation time for the resulting ObjectId. """ if generation_time.utcoffset() is not None: generation_time = generation_time - generation_time.utcoffset() timestamp = calendar.timegm(generation_time.timetuple()) oid = struct.pack( ">I", int(timestamp)) + b"\x00\x00\x00\x00\x00\x00\x00\x00" return cls(oid) @classmethod def is_valid(cls, oid): """Checks if a `oid` string is valid or not. :Parameters: - `oid`: the object id to validate .. versionadded:: 2.3 """ if not oid: return False try: ObjectId(oid) return True except (InvalidId, TypeError): return False @classmethod def _random(cls): """Generate a 5-byte random number once per process. """ pid = os.getpid() if pid != cls._pid: cls._pid = pid cls.__random = _random_bytes() return cls.__random def __generate(self): """Generate a new value for this ObjectId. """ # 4 bytes current time oid = struct.pack(">I", int(time.time())) # 5 bytes random oid += ObjectId._random() # 3 bytes inc with ObjectId._inc_lock: oid += struct.pack(">I", ObjectId._inc)[1:4] ObjectId._inc = (ObjectId._inc + 1) % (_MAX_COUNTER_VALUE + 1) self.__id = oid def __validate(self, oid): """Validate and use the given id for this ObjectId. Raises TypeError if id is not an instance of (:class:`basestring` (:class:`str` or :class:`bytes` in python 3), ObjectId) and InvalidId if it is not a valid ObjectId. :Parameters: - `oid`: a valid ObjectId """ if isinstance(oid, ObjectId): self.__id = oid.binary # bytes or unicode in python 2, str in python 3 elif isinstance(oid, string_type): if len(oid) == 24: try: self.__id = bytes_from_hex(oid) except (TypeError, ValueError): _raise_invalid_id(oid) else: _raise_invalid_id(oid) else: raise TypeError("id must be an instance of (bytes, %s, ObjectId), " "not %s" % (text_type.__name__, type(oid))) @property def binary(self): """12-byte binary representation of this ObjectId. """ return self.__id @property def generation_time(self): """A :class:`datetime.datetime` instance representing the time of generation for this :class:`ObjectId`. The :class:`datetime.datetime` is timezone aware, and represents the generation time in UTC. It is precise to the second. """ timestamp = struct.unpack(">I", self.__id[0:4])[0] return datetime.datetime.fromtimestamp(timestamp, utc) def __getstate__(self): """return value of object for pickling. needed explicitly because __slots__() defined. """ return self.__id def __setstate__(self, value): """explicit state set from pickling """ # Provide backwards compatability with OIDs # pickled with pymongo-1.9 or older. if isinstance(value, dict): oid = value["_ObjectId__id"] else: oid = value # ObjectIds pickled in python 2.x used `str` for __id. # In python 3.x this has to be converted to `bytes` # by encoding latin-1. if PY3 and isinstance(oid, text_type): self.__id = oid.encode('latin-1') else: self.__id = oid def __str__(self): if PY3: return binascii.hexlify(self.__id).decode() return binascii.hexlify(self.__id) def __repr__(self): return "ObjectId('%s')" % (str(self),) def __eq__(self, other): if isinstance(other, ObjectId): return self.__id == other.binary return NotImplemented def __ne__(self, other): if isinstance(other, ObjectId): return self.__id != other.binary return NotImplemented def __lt__(self, other): if isinstance(other, ObjectId): return self.__id < other.binary return NotImplemented def __le__(self, other): if isinstance(other, ObjectId): return self.__id <= other.binary return NotImplemented def __gt__(self, other): if isinstance(other, ObjectId): return self.__id > other.binary return NotImplemented def __ge__(self, other): if isinstance(other, ObjectId): return self.__id >= other.binary return NotImplemented def __hash__(self): """Get a hash value for this :class:`ObjectId`.""" return hash(self.__id) ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/bson/py3compat.py ================================================ # Copyright 2009-present MongoDB, Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); you # may not use this file except in compliance with the License. You # may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or # implied. See the License for the specific language governing # permissions and limitations under the License. """Utility functions and definitions for python3 compatibility.""" import sys PY3 = sys.version_info[0] == 3 if PY3: import codecs import collections.abc as abc import _thread as thread from abc import ABC, abstractmethod from io import BytesIO as StringIO def abstractproperty(func): return property(abstractmethod(func)) MAXSIZE = sys.maxsize imap = map def b(s): # BSON and socket operations deal in binary data. In # python 3 that means instances of `bytes`. In python # 2.7 you can create an alias for `bytes` using # the b prefix (e.g. b'foo'). # See http://python3porting.com/problems.html#nicer-solutions return codecs.latin_1_encode(s)[0] def bytes_from_hex(h): return bytes.fromhex(h) def iteritems(d): return iter(d.items()) def itervalues(d): return iter(d.values()) def reraise(exctype, value, trace=None): raise exctype(str(value)).with_traceback(trace) def reraise_instance(exc_instance, trace=None): raise exc_instance.with_traceback(trace) def _unicode(s): return s text_type = str string_type = str integer_types = int else: import collections as abc import thread from abc import ABCMeta, abstractproperty from itertools import imap try: from cStringIO import StringIO except ImportError: from StringIO import StringIO ABC = ABCMeta('ABC', (object,), {}) MAXSIZE = sys.maxint def b(s): # See comments above. In python 2.x b('foo') is just 'foo'. return s def bytes_from_hex(h): return h.decode('hex') def iteritems(d): return d.iteritems() def itervalues(d): return d.itervalues() def reraise(exctype, value, trace=None): _reraise(exctype, str(value), trace) def reraise_instance(exc_instance, trace=None): _reraise(exc_instance, None, trace) # "raise x, y, z" raises SyntaxError in Python 3 exec("""def _reraise(exc, value, trace): raise exc, value, trace """) _unicode = unicode string_type = basestring text_type = unicode integer_types = (int, long) ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/bson/raw_bson.py ================================================ # Copyright 2015-present MongoDB, Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Tools for representing raw BSON documents. """ from bson import _raw_to_dict, _get_object_size from bson.py3compat import abc, iteritems from bson.codec_options import ( DEFAULT_CODEC_OPTIONS as DEFAULT, _RAW_BSON_DOCUMENT_MARKER) from bson.son import SON class RawBSONDocument(abc.Mapping): """Representation for a MongoDB document that provides access to the raw BSON bytes that compose it. Only when a field is accessed or modified within the document does RawBSONDocument decode its bytes. """ __slots__ = ('__raw', '__inflated_doc', '__codec_options') _type_marker = _RAW_BSON_DOCUMENT_MARKER def __init__(self, bson_bytes, codec_options=None): """Create a new :class:`RawBSONDocument` :class:`RawBSONDocument` is a representation of a BSON document that provides access to the underlying raw BSON bytes. Only when a field is accessed or modified within the document does RawBSONDocument decode its bytes. :class:`RawBSONDocument` implements the ``Mapping`` abstract base class from the standard library so it can be used like a read-only ``dict``:: >>> raw_doc = RawBSONDocument(BSON.encode({'_id': 'my_doc'})) >>> raw_doc.raw b'...' >>> raw_doc['_id'] 'my_doc' :Parameters: - `bson_bytes`: the BSON bytes that compose this document - `codec_options` (optional): An instance of :class:`~bson.codec_options.CodecOptions` whose ``document_class`` must be :class:`RawBSONDocument`. The default is :attr:`DEFAULT_RAW_BSON_OPTIONS`. .. versionchanged:: 3.8 :class:`RawBSONDocument` now validates that the ``bson_bytes`` passed in represent a single bson document. .. versionchanged:: 3.5 If a :class:`~bson.codec_options.CodecOptions` is passed in, its `document_class` must be :class:`RawBSONDocument`. """ self.__raw = bson_bytes self.__inflated_doc = None # Can't default codec_options to DEFAULT_RAW_BSON_OPTIONS in signature, # it refers to this class RawBSONDocument. if codec_options is None: codec_options = DEFAULT_RAW_BSON_OPTIONS elif codec_options.document_class is not RawBSONDocument: raise TypeError( "RawBSONDocument cannot use CodecOptions with document " "class %s" % (codec_options.document_class, )) self.__codec_options = codec_options # Validate the bson object size. _get_object_size(bson_bytes, 0, len(bson_bytes)) @property def raw(self): """The raw BSON bytes composing this document.""" return self.__raw def items(self): """Lazily decode and iterate elements in this document.""" return iteritems(self.__inflated) @property def __inflated(self): if self.__inflated_doc is None: # We already validated the object's size when this document was # created, so no need to do that again. # Use SON to preserve ordering of elements. self.__inflated_doc = _inflate_bson( self.__raw, self.__codec_options) return self.__inflated_doc def __getitem__(self, item): return self.__inflated[item] def __iter__(self): return iter(self.__inflated) def __len__(self): return len(self.__inflated) def __eq__(self, other): if isinstance(other, RawBSONDocument): return self.__raw == other.raw return NotImplemented def __repr__(self): return ("RawBSONDocument(%r, codec_options=%r)" % (self.raw, self.__codec_options)) def _inflate_bson(bson_bytes, codec_options): """Inflates the top level fields of a BSON document. :Parameters: - `bson_bytes`: the BSON bytes that compose this document - `codec_options`: An instance of :class:`~bson.codec_options.CodecOptions` whose ``document_class`` must be :class:`RawBSONDocument`. """ # Use SON to preserve ordering of elements. return _raw_to_dict( bson_bytes, 4, len(bson_bytes)-1, codec_options, SON()) DEFAULT_RAW_BSON_OPTIONS = DEFAULT.with_options(document_class=RawBSONDocument) """The default :class:`~bson.codec_options.CodecOptions` for :class:`RawBSONDocument`. """ ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/bson/regex.py ================================================ # Copyright 2013-present MongoDB, Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Tools for representing MongoDB regular expressions. """ import re from bson.son import RE_TYPE from bson.py3compat import string_type, text_type def str_flags_to_int(str_flags): flags = 0 if "i" in str_flags: flags |= re.IGNORECASE if "l" in str_flags: flags |= re.LOCALE if "m" in str_flags: flags |= re.MULTILINE if "s" in str_flags: flags |= re.DOTALL if "u" in str_flags: flags |= re.UNICODE if "x" in str_flags: flags |= re.VERBOSE return flags class Regex(object): """BSON regular expression data.""" _type_marker = 11 @classmethod def from_native(cls, regex): """Convert a Python regular expression into a ``Regex`` instance. Note that in Python 3, a regular expression compiled from a :class:`str` has the ``re.UNICODE`` flag set. If it is undesirable to store this flag in a BSON regular expression, unset it first:: >>> pattern = re.compile('.*') >>> regex = Regex.from_native(pattern) >>> regex.flags ^= re.UNICODE >>> db.collection.insert({'pattern': regex}) :Parameters: - `regex`: A regular expression object from ``re.compile()``. .. warning:: Python regular expressions use a different syntax and different set of flags than MongoDB, which uses `PCRE`_. A regular expression retrieved from the server may not compile in Python, or may match a different set of strings in Python than when used in a MongoDB query. .. _PCRE: http://www.pcre.org/ """ if not isinstance(regex, RE_TYPE): raise TypeError( "regex must be a compiled regular expression, not %s" % type(regex)) return Regex(regex.pattern, regex.flags) def __init__(self, pattern, flags=0): """BSON regular expression data. This class is useful to store and retrieve regular expressions that are incompatible with Python's regular expression dialect. :Parameters: - `pattern`: string - `flags`: (optional) an integer bitmask, or a string of flag characters like "im" for IGNORECASE and MULTILINE """ if not isinstance(pattern, (text_type, bytes)): raise TypeError("pattern must be a string, not %s" % type(pattern)) self.pattern = pattern if isinstance(flags, string_type): self.flags = str_flags_to_int(flags) elif isinstance(flags, int): self.flags = flags else: raise TypeError( "flags must be a string or int, not %s" % type(flags)) def __eq__(self, other): if isinstance(other, Regex): return self.pattern == other.pattern and self.flags == other.flags else: return NotImplemented __hash__ = None def __ne__(self, other): return not self == other def __repr__(self): return "Regex(%r, %r)" % (self.pattern, self.flags) def try_compile(self): """Compile this :class:`Regex` as a Python regular expression. .. warning:: Python regular expressions use a different syntax and different set of flags than MongoDB, which uses `PCRE`_. A regular expression retrieved from the server may not compile in Python, or may match a different set of strings in Python than when used in a MongoDB query. :meth:`try_compile()` may raise :exc:`re.error`. .. _PCRE: http://www.pcre.org/ """ return re.compile(self.pattern, self.flags) ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/bson/son.py ================================================ # Copyright 2009-present MongoDB, Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Tools for creating and manipulating SON, the Serialized Ocument Notation. Regular dictionaries can be used instead of SON objects, but not when the order of keys is important. A SON object can be used just like a normal Python dictionary.""" import copy import re from bson.py3compat import abc, iteritems # This sort of sucks, but seems to be as good as it gets... # This is essentially the same as re._pattern_type RE_TYPE = type(re.compile("")) class SON(dict): """SON data. A subclass of dict that maintains ordering of keys and provides a few extra niceties for dealing with SON. SON provides an API similar to collections.OrderedDict from Python 2.7+. """ def __init__(self, data=None, **kwargs): self.__keys = [] dict.__init__(self) self.update(data) self.update(kwargs) def __new__(cls, *args, **kwargs): instance = super(SON, cls).__new__(cls, *args, **kwargs) instance.__keys = [] return instance def __repr__(self): result = [] for key in self.__keys: result.append("(%r, %r)" % (key, self[key])) return "SON([%s])" % ", ".join(result) def __setitem__(self, key, value): if key not in self.__keys: self.__keys.append(key) dict.__setitem__(self, key, value) def __delitem__(self, key): self.__keys.remove(key) dict.__delitem__(self, key) def keys(self): return list(self.__keys) def copy(self): other = SON() other.update(self) return other # TODO this is all from UserDict.DictMixin. it could probably be made more # efficient. # second level definitions support higher levels def __iter__(self): for k in self.__keys: yield k def has_key(self, key): return key in self.__keys # third level takes advantage of second level definitions def iteritems(self): for k in self: yield (k, self[k]) def iterkeys(self): return self.__iter__() # fourth level uses definitions from lower levels def itervalues(self): for _, v in self.iteritems(): yield v def values(self): return [v for _, v in self.iteritems()] def items(self): return [(key, self[key]) for key in self] def clear(self): self.__keys = [] super(SON, self).clear() def setdefault(self, key, default=None): try: return self[key] except KeyError: self[key] = default return default def pop(self, key, *args): if len(args) > 1: raise TypeError("pop expected at most 2 arguments, got "\ + repr(1 + len(args))) try: value = self[key] except KeyError: if args: return args[0] raise del self[key] return value def popitem(self): try: k, v = next(self.iteritems()) except StopIteration: raise KeyError('container is empty') del self[k] return (k, v) def update(self, other=None, **kwargs): # Make progressively weaker assumptions about "other" if other is None: pass elif hasattr(other, 'iteritems'): # iteritems saves memory and lookups for k, v in other.iteritems(): self[k] = v elif hasattr(other, 'keys'): for k in other.keys(): self[k] = other[k] else: for k, v in other: self[k] = v if kwargs: self.update(kwargs) def get(self, key, default=None): try: return self[key] except KeyError: return default def __eq__(self, other): """Comparison to another SON is order-sensitive while comparison to a regular dictionary is order-insensitive. """ if isinstance(other, SON): return len(self) == len(other) and self.items() == other.items() return self.to_dict() == other def __ne__(self, other): return not self == other def __len__(self): return len(self.__keys) def to_dict(self): """Convert a SON document to a normal Python dictionary instance. This is trickier than just *dict(...)* because it needs to be recursive. """ def transform_value(value): if isinstance(value, list): return [transform_value(v) for v in value] elif isinstance(value, abc.Mapping): return dict([ (k, transform_value(v)) for k, v in iteritems(value)]) else: return value return transform_value(dict(self)) def __deepcopy__(self, memo): out = SON() val_id = id(self) if val_id in memo: return memo.get(val_id) memo[val_id] = out for k, v in self.iteritems(): if not isinstance(v, RE_TYPE): v = copy.deepcopy(v, memo) out[k] = v return out ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/bson/timestamp.py ================================================ # Copyright 2010-2015 MongoDB, Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Tools for representing MongoDB internal Timestamps. """ import calendar import datetime from bson.py3compat import integer_types from bson.tz_util import utc UPPERBOUND = 4294967296 class Timestamp(object): """MongoDB internal timestamps used in the opLog. """ _type_marker = 17 def __init__(self, time, inc): """Create a new :class:`Timestamp`. This class is only for use with the MongoDB opLog. If you need to store a regular timestamp, please use a :class:`~datetime.datetime`. Raises :class:`TypeError` if `time` is not an instance of :class: `int` or :class:`~datetime.datetime`, or `inc` is not an instance of :class:`int`. Raises :class:`ValueError` if `time` or `inc` is not in [0, 2**32). :Parameters: - `time`: time in seconds since epoch UTC, or a naive UTC :class:`~datetime.datetime`, or an aware :class:`~datetime.datetime` - `inc`: the incrementing counter """ if isinstance(time, datetime.datetime): if time.utcoffset() is not None: time = time - time.utcoffset() time = int(calendar.timegm(time.timetuple())) if not isinstance(time, integer_types): raise TypeError("time must be an instance of int") if not isinstance(inc, integer_types): raise TypeError("inc must be an instance of int") if not 0 <= time < UPPERBOUND: raise ValueError("time must be contained in [0, 2**32)") if not 0 <= inc < UPPERBOUND: raise ValueError("inc must be contained in [0, 2**32)") self.__time = time self.__inc = inc @property def time(self): """Get the time portion of this :class:`Timestamp`. """ return self.__time @property def inc(self): """Get the inc portion of this :class:`Timestamp`. """ return self.__inc def __eq__(self, other): if isinstance(other, Timestamp): return (self.__time == other.time and self.__inc == other.inc) else: return NotImplemented def __hash__(self): return hash(self.time) ^ hash(self.inc) def __ne__(self, other): return not self == other def __lt__(self, other): if isinstance(other, Timestamp): return (self.time, self.inc) < (other.time, other.inc) return NotImplemented def __le__(self, other): if isinstance(other, Timestamp): return (self.time, self.inc) <= (other.time, other.inc) return NotImplemented def __gt__(self, other): if isinstance(other, Timestamp): return (self.time, self.inc) > (other.time, other.inc) return NotImplemented def __ge__(self, other): if isinstance(other, Timestamp): return (self.time, self.inc) >= (other.time, other.inc) return NotImplemented def __repr__(self): return "Timestamp(%s, %s)" % (self.__time, self.__inc) def as_datetime(self): """Return a :class:`~datetime.datetime` instance corresponding to the time portion of this :class:`Timestamp`. The returned datetime's timezone is UTC. """ return datetime.datetime.fromtimestamp(self.__time, utc) ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/bson/tz_util.py ================================================ # Copyright 2010-2015 MongoDB, Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Timezone related utilities for BSON.""" from datetime import (timedelta, tzinfo) ZERO = timedelta(0) class FixedOffset(tzinfo): """Fixed offset timezone, in minutes east from UTC. Implementation based from the Python `standard library documentation `_. Defining __getinitargs__ enables pickling / copying. """ def __init__(self, offset, name): if isinstance(offset, timedelta): self.__offset = offset else: self.__offset = timedelta(minutes=offset) self.__name = name def __getinitargs__(self): return self.__offset, self.__name def utcoffset(self, dt): return self.__offset def tzname(self, dt): return self.__name def dst(self, dt): return ZERO utc = FixedOffset(0, "UTC") """Fixed offset timezone representing UTC.""" ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/cffi/__init__.py ================================================ __all__ = ['FFI', 'VerificationError', 'VerificationMissing', 'CDefError', 'FFIError'] from .api import FFI from .error import CDefError, FFIError, VerificationError, VerificationMissing from .error import PkgConfigError __version__ = "1.13.1" __version_info__ = (1, 13, 1) # The verifier module file names are based on the CRC32 of a string that # contains the following version number. It may be older than __version__ # if nothing is clearly incompatible. __version_verifier_modules__ = "0.8.6" ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/cffi/_cffi_errors.h ================================================ #ifndef CFFI_MESSAGEBOX # ifdef _MSC_VER # define CFFI_MESSAGEBOX 1 # else # define CFFI_MESSAGEBOX 0 # endif #endif #if CFFI_MESSAGEBOX /* Windows only: logic to take the Python-CFFI embedding logic initialization errors and display them in a background thread with MessageBox. The idea is that if the whole program closes as a result of this problem, then likely it is already a console program and you can read the stderr output in the console too. If it is not a console program, then it will likely show its own dialog to complain, or generally not abruptly close, and for this case the background thread should stay alive. */ static void *volatile _cffi_bootstrap_text; static PyObject *_cffi_start_error_capture(void) { PyObject *result = NULL; PyObject *x, *m, *bi; if (InterlockedCompareExchangePointer(&_cffi_bootstrap_text, (void *)1, NULL) != NULL) return (PyObject *)1; m = PyImport_AddModule("_cffi_error_capture"); if (m == NULL) goto error; result = PyModule_GetDict(m); if (result == NULL) goto error; #if PY_MAJOR_VERSION >= 3 bi = PyImport_ImportModule("builtins"); #else bi = PyImport_ImportModule("__builtin__"); #endif if (bi == NULL) goto error; PyDict_SetItemString(result, "__builtins__", bi); Py_DECREF(bi); x = PyRun_String( "import sys\n" "class FileLike:\n" " def write(self, x):\n" " try:\n" " of.write(x)\n" " except: pass\n" " self.buf += x\n" "fl = FileLike()\n" "fl.buf = ''\n" "of = sys.stderr\n" "sys.stderr = fl\n" "def done():\n" " sys.stderr = of\n" " return fl.buf\n", /* make sure the returned value stays alive */ Py_file_input, result, result); Py_XDECREF(x); error: if (PyErr_Occurred()) { PyErr_WriteUnraisable(Py_None); PyErr_Clear(); } return result; } #pragma comment(lib, "user32.lib") static DWORD WINAPI _cffi_bootstrap_dialog(LPVOID ignored) { Sleep(666); /* may be interrupted if the whole process is closing */ #if PY_MAJOR_VERSION >= 3 MessageBoxW(NULL, (wchar_t *)_cffi_bootstrap_text, L"Python-CFFI error", MB_OK | MB_ICONERROR); #else MessageBoxA(NULL, (char *)_cffi_bootstrap_text, "Python-CFFI error", MB_OK | MB_ICONERROR); #endif _cffi_bootstrap_text = NULL; return 0; } static void _cffi_stop_error_capture(PyObject *ecap) { PyObject *s; void *text; if (ecap == (PyObject *)1) return; if (ecap == NULL) goto error; s = PyRun_String("done()", Py_eval_input, ecap, ecap); if (s == NULL) goto error; /* Show a dialog box, but in a background thread, and never show multiple dialog boxes at once. */ #if PY_MAJOR_VERSION >= 3 text = PyUnicode_AsWideCharString(s, NULL); #else text = PyString_AsString(s); #endif _cffi_bootstrap_text = text; if (text != NULL) { HANDLE h; h = CreateThread(NULL, 0, _cffi_bootstrap_dialog, NULL, 0, NULL); if (h != NULL) CloseHandle(h); } /* decref the string, but it should stay alive as 'fl.buf' in the small module above. It will really be freed only if we later get another similar error. So it's a leak of at most one copy of the small module. That's fine for this situation which is usually a "fatal error" anyway. */ Py_DECREF(s); PyErr_Clear(); return; error: _cffi_bootstrap_text = NULL; PyErr_Clear(); } #else static PyObject *_cffi_start_error_capture(void) { return NULL; } static void _cffi_stop_error_capture(PyObject *ecap) { } #endif ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/cffi/_cffi_include.h ================================================ #define _CFFI_ /* We try to define Py_LIMITED_API before including Python.h. Mess: we can only define it if Py_DEBUG, Py_TRACE_REFS and Py_REF_DEBUG are not defined. This is a best-effort approximation: we can learn about Py_DEBUG from pyconfig.h, but it is unclear if the same works for the other two macros. Py_DEBUG implies them, but not the other way around. Issue #350 is still open: on Windows, the code here causes it to link with PYTHON36.DLL (for example) instead of PYTHON3.DLL. A fix was attempted in 164e526a5515 and 14ce6985e1c3, but reverted: virtualenv does not make PYTHON3.DLL available, and so the "correctly" compiled version would not run inside a virtualenv. We will re-apply the fix after virtualenv has been fixed for some time. For explanation, see issue #355. For a workaround if you want PYTHON3.DLL and don't worry about virtualenv, see issue #350. See also 'py_limited_api' in setuptools_ext.py. */ #if !defined(_CFFI_USE_EMBEDDING) && !defined(Py_LIMITED_API) # include # if !defined(Py_DEBUG) && !defined(Py_TRACE_REFS) && !defined(Py_REF_DEBUG) # define Py_LIMITED_API # endif #endif #include #ifdef __cplusplus extern "C" { #endif #include #include "parse_c_type.h" /* this block of #ifs should be kept exactly identical between c/_cffi_backend.c, cffi/vengine_cpy.py, cffi/vengine_gen.py and cffi/_cffi_include.h */ #if defined(_MSC_VER) # include /* for alloca() */ # if _MSC_VER < 1600 /* MSVC < 2010 */ typedef __int8 int8_t; typedef __int16 int16_t; typedef __int32 int32_t; typedef __int64 int64_t; typedef unsigned __int8 uint8_t; typedef unsigned __int16 uint16_t; typedef unsigned __int32 uint32_t; typedef unsigned __int64 uint64_t; typedef __int8 int_least8_t; typedef __int16 int_least16_t; typedef __int32 int_least32_t; typedef __int64 int_least64_t; typedef unsigned __int8 uint_least8_t; typedef unsigned __int16 uint_least16_t; typedef unsigned __int32 uint_least32_t; typedef unsigned __int64 uint_least64_t; typedef __int8 int_fast8_t; typedef __int16 int_fast16_t; typedef __int32 int_fast32_t; typedef __int64 int_fast64_t; typedef unsigned __int8 uint_fast8_t; typedef unsigned __int16 uint_fast16_t; typedef unsigned __int32 uint_fast32_t; typedef unsigned __int64 uint_fast64_t; typedef __int64 intmax_t; typedef unsigned __int64 uintmax_t; # else # include # endif # if _MSC_VER < 1800 /* MSVC < 2013 */ # ifndef __cplusplus typedef unsigned char _Bool; # endif # endif #else # include # if (defined (__SVR4) && defined (__sun)) || defined(_AIX) || defined(__hpux) # include # endif #endif #ifdef __GNUC__ # define _CFFI_UNUSED_FN __attribute__((unused)) #else # define _CFFI_UNUSED_FN /* nothing */ #endif #ifdef __cplusplus # ifndef _Bool typedef bool _Bool; /* semi-hackish: C++ has no _Bool; bool is builtin */ # endif #endif /********** CPython-specific section **********/ #ifndef PYPY_VERSION #if PY_MAJOR_VERSION >= 3 # define PyInt_FromLong PyLong_FromLong #endif #define _cffi_from_c_double PyFloat_FromDouble #define _cffi_from_c_float PyFloat_FromDouble #define _cffi_from_c_long PyInt_FromLong #define _cffi_from_c_ulong PyLong_FromUnsignedLong #define _cffi_from_c_longlong PyLong_FromLongLong #define _cffi_from_c_ulonglong PyLong_FromUnsignedLongLong #define _cffi_from_c__Bool PyBool_FromLong #define _cffi_to_c_double PyFloat_AsDouble #define _cffi_to_c_float PyFloat_AsDouble #define _cffi_from_c_int(x, type) \ (((type)-1) > 0 ? /* unsigned */ \ (sizeof(type) < sizeof(long) ? \ PyInt_FromLong((long)x) : \ sizeof(type) == sizeof(long) ? \ PyLong_FromUnsignedLong((unsigned long)x) : \ PyLong_FromUnsignedLongLong((unsigned long long)x)) : \ (sizeof(type) <= sizeof(long) ? \ PyInt_FromLong((long)x) : \ PyLong_FromLongLong((long long)x))) #define _cffi_to_c_int(o, type) \ ((type)( \ sizeof(type) == 1 ? (((type)-1) > 0 ? (type)_cffi_to_c_u8(o) \ : (type)_cffi_to_c_i8(o)) : \ sizeof(type) == 2 ? (((type)-1) > 0 ? (type)_cffi_to_c_u16(o) \ : (type)_cffi_to_c_i16(o)) : \ sizeof(type) == 4 ? (((type)-1) > 0 ? (type)_cffi_to_c_u32(o) \ : (type)_cffi_to_c_i32(o)) : \ sizeof(type) == 8 ? (((type)-1) > 0 ? (type)_cffi_to_c_u64(o) \ : (type)_cffi_to_c_i64(o)) : \ (Py_FatalError("unsupported size for type " #type), (type)0))) #define _cffi_to_c_i8 \ ((int(*)(PyObject *))_cffi_exports[1]) #define _cffi_to_c_u8 \ ((int(*)(PyObject *))_cffi_exports[2]) #define _cffi_to_c_i16 \ ((int(*)(PyObject *))_cffi_exports[3]) #define _cffi_to_c_u16 \ ((int(*)(PyObject *))_cffi_exports[4]) #define _cffi_to_c_i32 \ ((int(*)(PyObject *))_cffi_exports[5]) #define _cffi_to_c_u32 \ ((unsigned int(*)(PyObject *))_cffi_exports[6]) #define _cffi_to_c_i64 \ ((long long(*)(PyObject *))_cffi_exports[7]) #define _cffi_to_c_u64 \ ((unsigned long long(*)(PyObject *))_cffi_exports[8]) #define _cffi_to_c_char \ ((int(*)(PyObject *))_cffi_exports[9]) #define _cffi_from_c_pointer \ ((PyObject *(*)(char *, struct _cffi_ctypedescr *))_cffi_exports[10]) #define _cffi_to_c_pointer \ ((char *(*)(PyObject *, struct _cffi_ctypedescr *))_cffi_exports[11]) #define _cffi_get_struct_layout \ not used any more #define _cffi_restore_errno \ ((void(*)(void))_cffi_exports[13]) #define _cffi_save_errno \ ((void(*)(void))_cffi_exports[14]) #define _cffi_from_c_char \ ((PyObject *(*)(char))_cffi_exports[15]) #define _cffi_from_c_deref \ ((PyObject *(*)(char *, struct _cffi_ctypedescr *))_cffi_exports[16]) #define _cffi_to_c \ ((int(*)(char *, struct _cffi_ctypedescr *, PyObject *))_cffi_exports[17]) #define _cffi_from_c_struct \ ((PyObject *(*)(char *, struct _cffi_ctypedescr *))_cffi_exports[18]) #define _cffi_to_c_wchar_t \ ((_cffi_wchar_t(*)(PyObject *))_cffi_exports[19]) #define _cffi_from_c_wchar_t \ ((PyObject *(*)(_cffi_wchar_t))_cffi_exports[20]) #define _cffi_to_c_long_double \ ((long double(*)(PyObject *))_cffi_exports[21]) #define _cffi_to_c__Bool \ ((_Bool(*)(PyObject *))_cffi_exports[22]) #define _cffi_prepare_pointer_call_argument \ ((Py_ssize_t(*)(struct _cffi_ctypedescr *, \ PyObject *, char **))_cffi_exports[23]) #define _cffi_convert_array_from_object \ ((int(*)(char *, struct _cffi_ctypedescr *, PyObject *))_cffi_exports[24]) #define _CFFI_CPIDX 25 #define _cffi_call_python \ ((void(*)(struct _cffi_externpy_s *, char *))_cffi_exports[_CFFI_CPIDX]) #define _cffi_to_c_wchar3216_t \ ((int(*)(PyObject *))_cffi_exports[26]) #define _cffi_from_c_wchar3216_t \ ((PyObject *(*)(int))_cffi_exports[27]) #define _CFFI_NUM_EXPORTS 28 struct _cffi_ctypedescr; static void *_cffi_exports[_CFFI_NUM_EXPORTS]; #define _cffi_type(index) ( \ assert((((uintptr_t)_cffi_types[index]) & 1) == 0), \ (struct _cffi_ctypedescr *)_cffi_types[index]) static PyObject *_cffi_init(const char *module_name, Py_ssize_t version, const struct _cffi_type_context_s *ctx) { PyObject *module, *o_arg, *new_module; void *raw[] = { (void *)module_name, (void *)version, (void *)_cffi_exports, (void *)ctx, }; module = PyImport_ImportModule("_cffi_backend"); if (module == NULL) goto failure; o_arg = PyLong_FromVoidPtr((void *)raw); if (o_arg == NULL) goto failure; new_module = PyObject_CallMethod( module, (char *)"_init_cffi_1_0_external_module", (char *)"O", o_arg); Py_DECREF(o_arg); Py_DECREF(module); return new_module; failure: Py_XDECREF(module); return NULL; } #ifdef HAVE_WCHAR_H typedef wchar_t _cffi_wchar_t; #else typedef uint16_t _cffi_wchar_t; /* same random pick as _cffi_backend.c */ #endif _CFFI_UNUSED_FN static uint16_t _cffi_to_c_char16_t(PyObject *o) { if (sizeof(_cffi_wchar_t) == 2) return (uint16_t)_cffi_to_c_wchar_t(o); else return (uint16_t)_cffi_to_c_wchar3216_t(o); } _CFFI_UNUSED_FN static PyObject *_cffi_from_c_char16_t(uint16_t x) { if (sizeof(_cffi_wchar_t) == 2) return _cffi_from_c_wchar_t((_cffi_wchar_t)x); else return _cffi_from_c_wchar3216_t((int)x); } _CFFI_UNUSED_FN static int _cffi_to_c_char32_t(PyObject *o) { if (sizeof(_cffi_wchar_t) == 4) return (int)_cffi_to_c_wchar_t(o); else return (int)_cffi_to_c_wchar3216_t(o); } _CFFI_UNUSED_FN static PyObject *_cffi_from_c_char32_t(int x) { if (sizeof(_cffi_wchar_t) == 4) return _cffi_from_c_wchar_t((_cffi_wchar_t)x); else return _cffi_from_c_wchar3216_t(x); } /********** end CPython-specific section **********/ #else _CFFI_UNUSED_FN static void (*_cffi_call_python_org)(struct _cffi_externpy_s *, char *); # define _cffi_call_python _cffi_call_python_org #endif #define _cffi_array_len(array) (sizeof(array) / sizeof((array)[0])) #define _cffi_prim_int(size, sign) \ ((size) == 1 ? ((sign) ? _CFFI_PRIM_INT8 : _CFFI_PRIM_UINT8) : \ (size) == 2 ? ((sign) ? _CFFI_PRIM_INT16 : _CFFI_PRIM_UINT16) : \ (size) == 4 ? ((sign) ? _CFFI_PRIM_INT32 : _CFFI_PRIM_UINT32) : \ (size) == 8 ? ((sign) ? _CFFI_PRIM_INT64 : _CFFI_PRIM_UINT64) : \ _CFFI__UNKNOWN_PRIM) #define _cffi_prim_float(size) \ ((size) == sizeof(float) ? _CFFI_PRIM_FLOAT : \ (size) == sizeof(double) ? _CFFI_PRIM_DOUBLE : \ (size) == sizeof(long double) ? _CFFI__UNKNOWN_LONG_DOUBLE : \ _CFFI__UNKNOWN_FLOAT_PRIM) #define _cffi_check_int(got, got_nonpos, expected) \ ((got_nonpos) == (expected <= 0) && \ (got) == (unsigned long long)expected) #ifdef MS_WIN32 # define _cffi_stdcall __stdcall #else # define _cffi_stdcall /* nothing */ #endif #ifdef __cplusplus } #endif ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/cffi/_embedding.h ================================================ /***** Support code for embedding *****/ #ifdef __cplusplus extern "C" { #endif #if defined(_WIN32) # define CFFI_DLLEXPORT __declspec(dllexport) #elif defined(__GNUC__) # define CFFI_DLLEXPORT __attribute__((visibility("default"))) #else # define CFFI_DLLEXPORT /* nothing */ #endif /* There are two global variables of type _cffi_call_python_fnptr: * _cffi_call_python, which we declare just below, is the one called by ``extern "Python"`` implementations. * _cffi_call_python_org, which on CPython is actually part of the _cffi_exports[] array, is the function pointer copied from _cffi_backend. After initialization is complete, both are equal. However, the first one remains equal to &_cffi_start_and_call_python until the very end of initialization, when we are (or should be) sure that concurrent threads also see a completely initialized world, and only then is it changed. */ #undef _cffi_call_python typedef void (*_cffi_call_python_fnptr)(struct _cffi_externpy_s *, char *); static void _cffi_start_and_call_python(struct _cffi_externpy_s *, char *); static _cffi_call_python_fnptr _cffi_call_python = &_cffi_start_and_call_python; #ifndef _MSC_VER /* --- Assuming a GCC not infinitely old --- */ # define cffi_compare_and_swap(l,o,n) __sync_bool_compare_and_swap(l,o,n) # define cffi_write_barrier() __sync_synchronize() # if !defined(__amd64__) && !defined(__x86_64__) && \ !defined(__i386__) && !defined(__i386) # define cffi_read_barrier() __sync_synchronize() # else # define cffi_read_barrier() (void)0 # endif #else /* --- Windows threads version --- */ # include # define cffi_compare_and_swap(l,o,n) \ (InterlockedCompareExchangePointer(l,n,o) == (o)) # define cffi_write_barrier() InterlockedCompareExchange(&_cffi_dummy,0,0) # define cffi_read_barrier() (void)0 static volatile LONG _cffi_dummy; #endif #ifdef WITH_THREAD # ifndef _MSC_VER # include static pthread_mutex_t _cffi_embed_startup_lock; # else static CRITICAL_SECTION _cffi_embed_startup_lock; # endif static char _cffi_embed_startup_lock_ready = 0; #endif static void _cffi_acquire_reentrant_mutex(void) { static void *volatile lock = NULL; while (!cffi_compare_and_swap(&lock, NULL, (void *)1)) { /* should ideally do a spin loop instruction here, but hard to do it portably and doesn't really matter I think: pthread_mutex_init() should be very fast, and this is only run at start-up anyway. */ } #ifdef WITH_THREAD if (!_cffi_embed_startup_lock_ready) { # ifndef _MSC_VER pthread_mutexattr_t attr; pthread_mutexattr_init(&attr); pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); pthread_mutex_init(&_cffi_embed_startup_lock, &attr); # else InitializeCriticalSection(&_cffi_embed_startup_lock); # endif _cffi_embed_startup_lock_ready = 1; } #endif while (!cffi_compare_and_swap(&lock, (void *)1, NULL)) ; #ifndef _MSC_VER pthread_mutex_lock(&_cffi_embed_startup_lock); #else EnterCriticalSection(&_cffi_embed_startup_lock); #endif } static void _cffi_release_reentrant_mutex(void) { #ifndef _MSC_VER pthread_mutex_unlock(&_cffi_embed_startup_lock); #else LeaveCriticalSection(&_cffi_embed_startup_lock); #endif } /********** CPython-specific section **********/ #ifndef PYPY_VERSION #include "_cffi_errors.h" #define _cffi_call_python_org _cffi_exports[_CFFI_CPIDX] PyMODINIT_FUNC _CFFI_PYTHON_STARTUP_FUNC(void); /* forward */ static void _cffi_py_initialize(void) { /* XXX use initsigs=0, which "skips initialization registration of signal handlers, which might be useful when Python is embedded" according to the Python docs. But review and think if it should be a user-controllable setting. XXX we should also give a way to write errors to a buffer instead of to stderr. XXX if importing 'site' fails, CPython (any version) calls exit(). Should we try to work around this behavior here? */ Py_InitializeEx(0); } static int _cffi_initialize_python(void) { /* This initializes Python, imports _cffi_backend, and then the present .dll/.so is set up as a CPython C extension module. */ int result; PyGILState_STATE state; PyObject *pycode=NULL, *global_dict=NULL, *x; PyObject *builtins; state = PyGILState_Ensure(); /* Call the initxxx() function from the present module. It will create and initialize us as a CPython extension module, instead of letting the startup Python code do it---it might reimport the same .dll/.so and get maybe confused on some platforms. It might also have troubles locating the .dll/.so again for all I know. */ (void)_CFFI_PYTHON_STARTUP_FUNC(); if (PyErr_Occurred()) goto error; /* Now run the Python code provided to ffi.embedding_init_code(). */ pycode = Py_CompileString(_CFFI_PYTHON_STARTUP_CODE, "", Py_file_input); if (pycode == NULL) goto error; global_dict = PyDict_New(); if (global_dict == NULL) goto error; builtins = PyEval_GetBuiltins(); if (builtins == NULL) goto error; if (PyDict_SetItemString(global_dict, "__builtins__", builtins) < 0) goto error; x = PyEval_EvalCode( #if PY_MAJOR_VERSION < 3 (PyCodeObject *) #endif pycode, global_dict, global_dict); if (x == NULL) goto error; Py_DECREF(x); /* Done! Now if we've been called from _cffi_start_and_call_python() in an ``extern "Python"``, we can only hope that the Python code did correctly set up the corresponding @ffi.def_extern() function. Otherwise, the general logic of ``extern "Python"`` functions (inside the _cffi_backend module) will find that the reference is still missing and print an error. */ result = 0; done: Py_XDECREF(pycode); Py_XDECREF(global_dict); PyGILState_Release(state); return result; error:; { /* Print as much information as potentially useful. Debugging load-time failures with embedding is not fun */ PyObject *ecap; PyObject *exception, *v, *tb, *f, *modules, *mod; PyErr_Fetch(&exception, &v, &tb); ecap = _cffi_start_error_capture(); f = PySys_GetObject((char *)"stderr"); if (f != NULL && f != Py_None) { PyFile_WriteString( "Failed to initialize the Python-CFFI embedding logic:\n\n", f); } if (exception != NULL) { PyErr_NormalizeException(&exception, &v, &tb); PyErr_Display(exception, v, tb); } Py_XDECREF(exception); Py_XDECREF(v); Py_XDECREF(tb); if (f != NULL && f != Py_None) { PyFile_WriteString("\nFrom: " _CFFI_MODULE_NAME "\ncompiled with cffi version: 1.13.1" "\n_cffi_backend module: ", f); modules = PyImport_GetModuleDict(); mod = PyDict_GetItemString(modules, "_cffi_backend"); if (mod == NULL) { PyFile_WriteString("not loaded", f); } else { v = PyObject_GetAttrString(mod, "__file__"); PyFile_WriteObject(v, f, 0); Py_XDECREF(v); } PyFile_WriteString("\nsys.path: ", f); PyFile_WriteObject(PySys_GetObject((char *)"path"), f, 0); PyFile_WriteString("\n\n", f); } _cffi_stop_error_capture(ecap); } result = -1; goto done; } PyAPI_DATA(char *) _PyParser_TokenNames[]; /* from CPython */ static int _cffi_carefully_make_gil(void) { /* This does the basic initialization of Python. It can be called completely concurrently from unrelated threads. It assumes that we don't hold the GIL before (if it exists), and we don't hold it afterwards. (What it really does used to be completely different in Python 2 and Python 3, with the Python 2 solution avoiding the spin-lock around the Py_InitializeEx() call. However, after recent changes to CPython 2.7 (issue #358) it no longer works. So we use the Python 3 solution everywhere.) This initializes Python by calling Py_InitializeEx(). Important: this must not be called concurrently at all. So we use a global variable as a simple spin lock. This global variable must be from 'libpythonX.Y.so', not from this cffi-based extension module, because it must be shared from different cffi-based extension modules. In Python < 3.8, we choose _PyParser_TokenNames[0] as a completely arbitrary pointer value that is never written to. The default is to point to the string "ENDMARKER". We change it temporarily to point to the next character in that string. (Yes, I know it's REALLY obscure.) In Python >= 3.8, this string array is no longer writable, so instead we pick PyCapsuleType.tp_version_tag. We can't change Python < 3.8 because someone might use a mixture of cffi embedded modules, some of which were compiled before this file changed. */ #ifdef WITH_THREAD # if PY_VERSION_HEX < 0x03080000 char *volatile *lock = (char *volatile *)_PyParser_TokenNames; char *old_value, *locked_value; while (1) { /* spin loop */ old_value = *lock; locked_value = old_value + 1; if (old_value[0] == 'E') { assert(old_value[1] == 'N'); if (cffi_compare_and_swap(lock, old_value, locked_value)) break; } else { assert(old_value[0] == 'N'); /* should ideally do a spin loop instruction here, but hard to do it portably and doesn't really matter I think: PyEval_InitThreads() should be very fast, and this is only run at start-up anyway. */ } } # else int volatile *lock = (int volatile *)&PyCapsule_Type.tp_version_tag; int old_value, locked_value; assert(!(PyCapsule_Type.tp_flags & Py_TPFLAGS_HAVE_VERSION_TAG)); while (1) { /* spin loop */ old_value = *lock; locked_value = -42; if (old_value == 0) { if (cffi_compare_and_swap(lock, old_value, locked_value)) break; } else { assert(old_value == locked_value); /* should ideally do a spin loop instruction here, but hard to do it portably and doesn't really matter I think: PyEval_InitThreads() should be very fast, and this is only run at start-up anyway. */ } } # endif #endif /* call Py_InitializeEx() */ if (!Py_IsInitialized()) { _cffi_py_initialize(); PyEval_InitThreads(); PyEval_SaveThread(); /* release the GIL */ /* the returned tstate must be the one that has been stored into the autoTLSkey by _PyGILState_Init() called from Py_Initialize(). */ } else { PyGILState_STATE state = PyGILState_Ensure(); PyEval_InitThreads(); PyGILState_Release(state); } #ifdef WITH_THREAD /* release the lock */ while (!cffi_compare_and_swap(lock, locked_value, old_value)) ; #endif return 0; } /********** end CPython-specific section **********/ #else /********** PyPy-specific section **********/ PyMODINIT_FUNC _CFFI_PYTHON_STARTUP_FUNC(const void *[]); /* forward */ static struct _cffi_pypy_init_s { const char *name; void (*func)(const void *[]); const char *code; } _cffi_pypy_init = { _CFFI_MODULE_NAME, (void(*)(const void *[]))_CFFI_PYTHON_STARTUP_FUNC, _CFFI_PYTHON_STARTUP_CODE, }; extern int pypy_carefully_make_gil(const char *); extern int pypy_init_embedded_cffi_module(int, struct _cffi_pypy_init_s *); static int _cffi_carefully_make_gil(void) { return pypy_carefully_make_gil(_CFFI_MODULE_NAME); } static int _cffi_initialize_python(void) { return pypy_init_embedded_cffi_module(0xB011, &_cffi_pypy_init); } /********** end PyPy-specific section **********/ #endif #ifdef __GNUC__ __attribute__((noinline)) #endif static _cffi_call_python_fnptr _cffi_start_python(void) { /* Delicate logic to initialize Python. This function can be called multiple times concurrently, e.g. when the process calls its first ``extern "Python"`` functions in multiple threads at once. It can also be called recursively, in which case we must ignore it. We also have to consider what occurs if several different cffi-based extensions reach this code in parallel threads---it is a different copy of the code, then, and we can't have any shared global variable unless it comes from 'libpythonX.Y.so'. Idea: * _cffi_carefully_make_gil(): "carefully" call PyEval_InitThreads() (possibly with Py_InitializeEx() first). * then we use a (local) custom lock to make sure that a call to this cffi-based extension will wait if another call to the *same* extension is running the initialization in another thread. It is reentrant, so that a recursive call will not block, but only one from a different thread. * then we grab the GIL and (Python 2) we call Py_InitializeEx(). At this point, concurrent calls to Py_InitializeEx() are not possible: we have the GIL. * do the rest of the specific initialization, which may temporarily release the GIL but not the custom lock. Only release the custom lock when we are done. */ static char called = 0; if (_cffi_carefully_make_gil() != 0) return NULL; _cffi_acquire_reentrant_mutex(); /* Here the GIL exists, but we don't have it. We're only protected from concurrency by the reentrant mutex. */ /* This file only initializes the embedded module once, the first time this is called, even if there are subinterpreters. */ if (!called) { called = 1; /* invoke _cffi_initialize_python() only once, but don't set '_cffi_call_python' right now, otherwise concurrent threads won't call this function at all (we need them to wait) */ if (_cffi_initialize_python() == 0) { /* now initialization is finished. Switch to the fast-path. */ /* We would like nobody to see the new value of '_cffi_call_python' without also seeing the rest of the data initialized. However, this is not possible. But the new value of '_cffi_call_python' is the function 'cffi_call_python()' from _cffi_backend. So: */ cffi_write_barrier(); /* ^^^ we put a write barrier here, and a corresponding read barrier at the start of cffi_call_python(). This ensures that after that read barrier, we see everything done here before the write barrier. */ assert(_cffi_call_python_org != NULL); _cffi_call_python = (_cffi_call_python_fnptr)_cffi_call_python_org; } else { /* initialization failed. Reset this to NULL, even if it was already set to some other value. Future calls to _cffi_start_python() are still forced to occur, and will always return NULL from now on. */ _cffi_call_python_org = NULL; } } _cffi_release_reentrant_mutex(); return (_cffi_call_python_fnptr)_cffi_call_python_org; } static void _cffi_start_and_call_python(struct _cffi_externpy_s *externpy, char *args) { _cffi_call_python_fnptr fnptr; int current_err = errno; #ifdef _MSC_VER int current_lasterr = GetLastError(); #endif fnptr = _cffi_start_python(); if (fnptr == NULL) { fprintf(stderr, "function %s() called, but initialization code " "failed. Returning 0.\n", externpy->name); memset(args, 0, externpy->size_of_result); } #ifdef _MSC_VER SetLastError(current_lasterr); #endif errno = current_err; if (fnptr != NULL) fnptr(externpy, args); } /* The cffi_start_python() function makes sure Python is initialized and our cffi module is set up. It can be called manually from the user C code. The same effect is obtained automatically from any dll-exported ``extern "Python"`` function. This function returns -1 if initialization failed, 0 if all is OK. */ _CFFI_UNUSED_FN static int cffi_start_python(void) { if (_cffi_call_python == &_cffi_start_and_call_python) { if (_cffi_start_python() == NULL) return -1; } cffi_read_barrier(); return 0; } #undef cffi_compare_and_swap #undef cffi_write_barrier #undef cffi_read_barrier #ifdef __cplusplus } #endif ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/cffi/api.py ================================================ import sys, types from .lock import allocate_lock from .error import CDefError from . import model try: callable except NameError: # Python 3.1 from collections import Callable callable = lambda x: isinstance(x, Callable) try: basestring except NameError: # Python 3.x basestring = str _unspecified = object() class FFI(object): r''' The main top-level class that you instantiate once, or once per module. Example usage: ffi = FFI() ffi.cdef(""" int printf(const char *, ...); """) C = ffi.dlopen(None) # standard library -or- C = ffi.verify() # use a C compiler: verify the decl above is right C.printf("hello, %s!\n", ffi.new("char[]", "world")) ''' def __init__(self, backend=None): """Create an FFI instance. The 'backend' argument is used to select a non-default backend, mostly for tests. """ if backend is None: # You need PyPy (>= 2.0 beta), or a CPython (>= 2.6) with # _cffi_backend.so compiled. import _cffi_backend as backend from . import __version__ if backend.__version__ != __version__: # bad version! Try to be as explicit as possible. if hasattr(backend, '__file__'): # CPython raise Exception("Version mismatch: this is the 'cffi' package version %s, located in %r. When we import the top-level '_cffi_backend' extension module, we get version %s, located in %r. The two versions should be equal; check your installation." % ( __version__, __file__, backend.__version__, backend.__file__)) else: # PyPy raise Exception("Version mismatch: this is the 'cffi' package version %s, located in %r. This interpreter comes with a built-in '_cffi_backend' module, which is version %s. The two versions should be equal; check your installation." % ( __version__, __file__, backend.__version__)) # (If you insist you can also try to pass the option # 'backend=backend_ctypes.CTypesBackend()', but don't # rely on it! It's probably not going to work well.) from . import cparser self._backend = backend self._lock = allocate_lock() self._parser = cparser.Parser() self._cached_btypes = {} self._parsed_types = types.ModuleType('parsed_types').__dict__ self._new_types = types.ModuleType('new_types').__dict__ self._function_caches = [] self._libraries = [] self._cdefsources = [] self._included_ffis = [] self._windows_unicode = None self._init_once_cache = {} self._cdef_version = None self._embedding = None self._typecache = model.get_typecache(backend) if hasattr(backend, 'set_ffi'): backend.set_ffi(self) for name in list(backend.__dict__): if name.startswith('RTLD_'): setattr(self, name, getattr(backend, name)) # with self._lock: self.BVoidP = self._get_cached_btype(model.voidp_type) self.BCharA = self._get_cached_btype(model.char_array_type) if isinstance(backend, types.ModuleType): # _cffi_backend: attach these constants to the class if not hasattr(FFI, 'NULL'): FFI.NULL = self.cast(self.BVoidP, 0) FFI.CData, FFI.CType = backend._get_types() else: # ctypes backend: attach these constants to the instance self.NULL = self.cast(self.BVoidP, 0) self.CData, self.CType = backend._get_types() self.buffer = backend.buffer def cdef(self, csource, override=False, packed=False, pack=None): """Parse the given C source. This registers all declared functions, types, and global variables. The functions and global variables can then be accessed via either 'ffi.dlopen()' or 'ffi.verify()'. The types can be used in 'ffi.new()' and other functions. If 'packed' is specified as True, all structs declared inside this cdef are packed, i.e. laid out without any field alignment at all. Alternatively, 'pack' can be a small integer, and requests for alignment greater than that are ignored (pack=1 is equivalent to packed=True). """ self._cdef(csource, override=override, packed=packed, pack=pack) def embedding_api(self, csource, packed=False, pack=None): self._cdef(csource, packed=packed, pack=pack, dllexport=True) if self._embedding is None: self._embedding = '' def _cdef(self, csource, override=False, **options): if not isinstance(csource, str): # unicode, on Python 2 if not isinstance(csource, basestring): raise TypeError("cdef() argument must be a string") csource = csource.encode('ascii') with self._lock: self._cdef_version = object() self._parser.parse(csource, override=override, **options) self._cdefsources.append(csource) if override: for cache in self._function_caches: cache.clear() finishlist = self._parser._recomplete if finishlist: self._parser._recomplete = [] for tp in finishlist: tp.finish_backend_type(self, finishlist) def dlopen(self, name, flags=0): """Load and return a dynamic library identified by 'name'. The standard C library can be loaded by passing None. Note that functions and types declared by 'ffi.cdef()' are not linked to a particular library, just like C headers; in the library we only look for the actual (untyped) symbols. """ assert isinstance(name, basestring) or name is None with self._lock: lib, function_cache = _make_ffi_library(self, name, flags) self._function_caches.append(function_cache) self._libraries.append(lib) return lib def dlclose(self, lib): """Close a library obtained with ffi.dlopen(). After this call, access to functions or variables from the library will fail (possibly with a segmentation fault). """ type(lib).__cffi_close__(lib) def _typeof_locked(self, cdecl): # call me with the lock! key = cdecl if key in self._parsed_types: return self._parsed_types[key] # if not isinstance(cdecl, str): # unicode, on Python 2 cdecl = cdecl.encode('ascii') # type = self._parser.parse_type(cdecl) really_a_function_type = type.is_raw_function if really_a_function_type: type = type.as_function_pointer() btype = self._get_cached_btype(type) result = btype, really_a_function_type self._parsed_types[key] = result return result def _typeof(self, cdecl, consider_function_as_funcptr=False): # string -> ctype object try: result = self._parsed_types[cdecl] except KeyError: with self._lock: result = self._typeof_locked(cdecl) # btype, really_a_function_type = result if really_a_function_type and not consider_function_as_funcptr: raise CDefError("the type %r is a function type, not a " "pointer-to-function type" % (cdecl,)) return btype def typeof(self, cdecl): """Parse the C type given as a string and return the corresponding object. It can also be used on 'cdata' instance to get its C type. """ if isinstance(cdecl, basestring): return self._typeof(cdecl) if isinstance(cdecl, self.CData): return self._backend.typeof(cdecl) if isinstance(cdecl, types.BuiltinFunctionType): res = _builtin_function_type(cdecl) if res is not None: return res if (isinstance(cdecl, types.FunctionType) and hasattr(cdecl, '_cffi_base_type')): with self._lock: return self._get_cached_btype(cdecl._cffi_base_type) raise TypeError(type(cdecl)) def sizeof(self, cdecl): """Return the size in bytes of the argument. It can be a string naming a C type, or a 'cdata' instance. """ if isinstance(cdecl, basestring): BType = self._typeof(cdecl) return self._backend.sizeof(BType) else: return self._backend.sizeof(cdecl) def alignof(self, cdecl): """Return the natural alignment size in bytes of the C type given as a string. """ if isinstance(cdecl, basestring): cdecl = self._typeof(cdecl) return self._backend.alignof(cdecl) def offsetof(self, cdecl, *fields_or_indexes): """Return the offset of the named field inside the given structure or array, which must be given as a C type name. You can give several field names in case of nested structures. You can also give numeric values which correspond to array items, in case of an array type. """ if isinstance(cdecl, basestring): cdecl = self._typeof(cdecl) return self._typeoffsetof(cdecl, *fields_or_indexes)[1] def new(self, cdecl, init=None): """Allocate an instance according to the specified C type and return a pointer to it. The specified C type must be either a pointer or an array: ``new('X *')`` allocates an X and returns a pointer to it, whereas ``new('X[n]')`` allocates an array of n X'es and returns an array referencing it (which works mostly like a pointer, like in C). You can also use ``new('X[]', n)`` to allocate an array of a non-constant length n. The memory is initialized following the rules of declaring a global variable in C: by default it is zero-initialized, but an explicit initializer can be given which can be used to fill all or part of the memory. When the returned object goes out of scope, the memory is freed. In other words the returned object has ownership of the value of type 'cdecl' that it points to. This means that the raw data can be used as long as this object is kept alive, but must not be used for a longer time. Be careful about that when copying the pointer to the memory somewhere else, e.g. into another structure. """ if isinstance(cdecl, basestring): cdecl = self._typeof(cdecl) return self._backend.newp(cdecl, init) def new_allocator(self, alloc=None, free=None, should_clear_after_alloc=True): """Return a new allocator, i.e. a function that behaves like ffi.new() but uses the provided low-level 'alloc' and 'free' functions. 'alloc' is called with the size as argument. If it returns NULL, a MemoryError is raised. 'free' is called with the result of 'alloc' as argument. Both can be either Python function or directly C functions. If 'free' is None, then no free function is called. If both 'alloc' and 'free' are None, the default is used. If 'should_clear_after_alloc' is set to False, then the memory returned by 'alloc' is assumed to be already cleared (or you are fine with garbage); otherwise CFFI will clear it. """ compiled_ffi = self._backend.FFI() allocator = compiled_ffi.new_allocator(alloc, free, should_clear_after_alloc) def allocate(cdecl, init=None): if isinstance(cdecl, basestring): cdecl = self._typeof(cdecl) return allocator(cdecl, init) return allocate def cast(self, cdecl, source): """Similar to a C cast: returns an instance of the named C type initialized with the given 'source'. The source is casted between integers or pointers of any type. """ if isinstance(cdecl, basestring): cdecl = self._typeof(cdecl) return self._backend.cast(cdecl, source) def string(self, cdata, maxlen=-1): """Return a Python string (or unicode string) from the 'cdata'. If 'cdata' is a pointer or array of characters or bytes, returns the null-terminated string. The returned string extends until the first null character, or at most 'maxlen' characters. If 'cdata' is an array then 'maxlen' defaults to its length. If 'cdata' is a pointer or array of wchar_t, returns a unicode string following the same rules. If 'cdata' is a single character or byte or a wchar_t, returns it as a string or unicode string. If 'cdata' is an enum, returns the value of the enumerator as a string, or 'NUMBER' if the value is out of range. """ return self._backend.string(cdata, maxlen) def unpack(self, cdata, length): """Unpack an array of C data of the given length, returning a Python string/unicode/list. If 'cdata' is a pointer to 'char', returns a byte string. It does not stop at the first null. This is equivalent to: ffi.buffer(cdata, length)[:] If 'cdata' is a pointer to 'wchar_t', returns a unicode string. 'length' is measured in wchar_t's; it is not the size in bytes. If 'cdata' is a pointer to anything else, returns a list of 'length' items. This is a faster equivalent to: [cdata[i] for i in range(length)] """ return self._backend.unpack(cdata, length) #def buffer(self, cdata, size=-1): # """Return a read-write buffer object that references the raw C data # pointed to by the given 'cdata'. The 'cdata' must be a pointer or # an array. Can be passed to functions expecting a buffer, or directly # manipulated with: # # buf[:] get a copy of it in a regular string, or # buf[idx] as a single character # buf[:] = ... # buf[idx] = ... change the content # """ # note that 'buffer' is a type, set on this instance by __init__ def from_buffer(self, cdecl, python_buffer=_unspecified, require_writable=False): """Return a cdata of the given type pointing to the data of the given Python object, which must support the buffer interface. Note that this is not meant to be used on the built-in types str or unicode (you can build 'char[]' arrays explicitly) but only on objects containing large quantities of raw data in some other format, like 'array.array' or numpy arrays. The first argument is optional and default to 'char[]'. """ if python_buffer is _unspecified: cdecl, python_buffer = self.BCharA, cdecl elif isinstance(cdecl, basestring): cdecl = self._typeof(cdecl) return self._backend.from_buffer(cdecl, python_buffer, require_writable) def memmove(self, dest, src, n): """ffi.memmove(dest, src, n) copies n bytes of memory from src to dest. Like the C function memmove(), the memory areas may overlap; apart from that it behaves like the C function memcpy(). 'src' can be any cdata ptr or array, or any Python buffer object. 'dest' can be any cdata ptr or array, or a writable Python buffer object. The size to copy, 'n', is always measured in bytes. Unlike other methods, this one supports all Python buffer including byte strings and bytearrays---but it still does not support non-contiguous buffers. """ return self._backend.memmove(dest, src, n) def callback(self, cdecl, python_callable=None, error=None, onerror=None): """Return a callback object or a decorator making such a callback object. 'cdecl' must name a C function pointer type. The callback invokes the specified 'python_callable' (which may be provided either directly or via a decorator). Important: the callback object must be manually kept alive for as long as the callback may be invoked from the C level. """ def callback_decorator_wrap(python_callable): if not callable(python_callable): raise TypeError("the 'python_callable' argument " "is not callable") return self._backend.callback(cdecl, python_callable, error, onerror) if isinstance(cdecl, basestring): cdecl = self._typeof(cdecl, consider_function_as_funcptr=True) if python_callable is None: return callback_decorator_wrap # decorator mode else: return callback_decorator_wrap(python_callable) # direct mode def getctype(self, cdecl, replace_with=''): """Return a string giving the C type 'cdecl', which may be itself a string or a object. If 'replace_with' is given, it gives extra text to append (or insert for more complicated C types), like a variable name, or '*' to get actually the C type 'pointer-to-cdecl'. """ if isinstance(cdecl, basestring): cdecl = self._typeof(cdecl) replace_with = replace_with.strip() if (replace_with.startswith('*') and '&[' in self._backend.getcname(cdecl, '&')): replace_with = '(%s)' % replace_with elif replace_with and not replace_with[0] in '[(': replace_with = ' ' + replace_with return self._backend.getcname(cdecl, replace_with) def gc(self, cdata, destructor, size=0): """Return a new cdata object that points to the same data. Later, when this new cdata object is garbage-collected, 'destructor(old_cdata_object)' will be called. The optional 'size' gives an estimate of the size, used to trigger the garbage collection more eagerly. So far only used on PyPy. It tells the GC that the returned object keeps alive roughly 'size' bytes of external memory. """ return self._backend.gcp(cdata, destructor, size) def _get_cached_btype(self, type): assert self._lock.acquire(False) is False # call me with the lock! try: BType = self._cached_btypes[type] except KeyError: finishlist = [] BType = type.get_cached_btype(self, finishlist) for type in finishlist: type.finish_backend_type(self, finishlist) return BType def verify(self, source='', tmpdir=None, **kwargs): """Verify that the current ffi signatures compile on this machine, and return a dynamic library object. The dynamic library can be used to call functions and access global variables declared in this 'ffi'. The library is compiled by the C compiler: it gives you C-level API compatibility (including calling macros). This is unlike 'ffi.dlopen()', which requires binary compatibility in the signatures. """ from .verifier import Verifier, _caller_dir_pycache # # If set_unicode(True) was called, insert the UNICODE and # _UNICODE macro declarations if self._windows_unicode: self._apply_windows_unicode(kwargs) # # Set the tmpdir here, and not in Verifier.__init__: it picks # up the caller's directory, which we want to be the caller of # ffi.verify(), as opposed to the caller of Veritier(). tmpdir = tmpdir or _caller_dir_pycache() # # Make a Verifier() and use it to load the library. self.verifier = Verifier(self, source, tmpdir, **kwargs) lib = self.verifier.load_library() # # Save the loaded library for keep-alive purposes, even # if the caller doesn't keep it alive itself (it should). self._libraries.append(lib) return lib def _get_errno(self): return self._backend.get_errno() def _set_errno(self, errno): self._backend.set_errno(errno) errno = property(_get_errno, _set_errno, None, "the value of 'errno' from/to the C calls") def getwinerror(self, code=-1): return self._backend.getwinerror(code) def _pointer_to(self, ctype): with self._lock: return model.pointer_cache(self, ctype) def addressof(self, cdata, *fields_or_indexes): """Return the address of a . If 'fields_or_indexes' are given, returns the address of that field or array item in the structure or array, recursively in case of nested structures. """ try: ctype = self._backend.typeof(cdata) except TypeError: if '__addressof__' in type(cdata).__dict__: return type(cdata).__addressof__(cdata, *fields_or_indexes) raise if fields_or_indexes: ctype, offset = self._typeoffsetof(ctype, *fields_or_indexes) else: if ctype.kind == "pointer": raise TypeError("addressof(pointer)") offset = 0 ctypeptr = self._pointer_to(ctype) return self._backend.rawaddressof(ctypeptr, cdata, offset) def _typeoffsetof(self, ctype, field_or_index, *fields_or_indexes): ctype, offset = self._backend.typeoffsetof(ctype, field_or_index) for field1 in fields_or_indexes: ctype, offset1 = self._backend.typeoffsetof(ctype, field1, 1) offset += offset1 return ctype, offset def include(self, ffi_to_include): """Includes the typedefs, structs, unions and enums defined in another FFI instance. Usage is similar to a #include in C, where a part of the program might include types defined in another part for its own usage. Note that the include() method has no effect on functions, constants and global variables, which must anyway be accessed directly from the lib object returned by the original FFI instance. """ if not isinstance(ffi_to_include, FFI): raise TypeError("ffi.include() expects an argument that is also of" " type cffi.FFI, not %r" % ( type(ffi_to_include).__name__,)) if ffi_to_include is self: raise ValueError("self.include(self)") with ffi_to_include._lock: with self._lock: self._parser.include(ffi_to_include._parser) self._cdefsources.append('[') self._cdefsources.extend(ffi_to_include._cdefsources) self._cdefsources.append(']') self._included_ffis.append(ffi_to_include) def new_handle(self, x): return self._backend.newp_handle(self.BVoidP, x) def from_handle(self, x): return self._backend.from_handle(x) def release(self, x): self._backend.release(x) def set_unicode(self, enabled_flag): """Windows: if 'enabled_flag' is True, enable the UNICODE and _UNICODE defines in C, and declare the types like TCHAR and LPTCSTR to be (pointers to) wchar_t. If 'enabled_flag' is False, declare these types to be (pointers to) plain 8-bit characters. This is mostly for backward compatibility; you usually want True. """ if self._windows_unicode is not None: raise ValueError("set_unicode() can only be called once") enabled_flag = bool(enabled_flag) if enabled_flag: self.cdef("typedef wchar_t TBYTE;" "typedef wchar_t TCHAR;" "typedef const wchar_t *LPCTSTR;" "typedef const wchar_t *PCTSTR;" "typedef wchar_t *LPTSTR;" "typedef wchar_t *PTSTR;" "typedef TBYTE *PTBYTE;" "typedef TCHAR *PTCHAR;") else: self.cdef("typedef char TBYTE;" "typedef char TCHAR;" "typedef const char *LPCTSTR;" "typedef const char *PCTSTR;" "typedef char *LPTSTR;" "typedef char *PTSTR;" "typedef TBYTE *PTBYTE;" "typedef TCHAR *PTCHAR;") self._windows_unicode = enabled_flag def _apply_windows_unicode(self, kwds): defmacros = kwds.get('define_macros', ()) if not isinstance(defmacros, (list, tuple)): raise TypeError("'define_macros' must be a list or tuple") defmacros = list(defmacros) + [('UNICODE', '1'), ('_UNICODE', '1')] kwds['define_macros'] = defmacros def _apply_embedding_fix(self, kwds): # must include an argument like "-lpython2.7" for the compiler def ensure(key, value): lst = kwds.setdefault(key, []) if value not in lst: lst.append(value) # if '__pypy__' in sys.builtin_module_names: import os if sys.platform == "win32": # we need 'libpypy-c.lib'. Current distributions of # pypy (>= 4.1) contain it as 'libs/python27.lib'. pythonlib = "python{0[0]}{0[1]}".format(sys.version_info) if hasattr(sys, 'prefix'): ensure('library_dirs', os.path.join(sys.prefix, 'libs')) else: # we need 'libpypy-c.{so,dylib}', which should be by # default located in 'sys.prefix/bin' for installed # systems. if sys.version_info < (3,): pythonlib = "pypy-c" else: pythonlib = "pypy3-c" if hasattr(sys, 'prefix'): ensure('library_dirs', os.path.join(sys.prefix, 'bin')) # On uninstalled pypy's, the libpypy-c is typically found in # .../pypy/goal/. if hasattr(sys, 'prefix'): ensure('library_dirs', os.path.join(sys.prefix, 'pypy', 'goal')) else: if sys.platform == "win32": template = "python%d%d" if hasattr(sys, 'gettotalrefcount'): template += '_d' else: try: import sysconfig except ImportError: # 2.6 from distutils import sysconfig template = "python%d.%d" if sysconfig.get_config_var('DEBUG_EXT'): template += sysconfig.get_config_var('DEBUG_EXT') pythonlib = (template % (sys.hexversion >> 24, (sys.hexversion >> 16) & 0xff)) if hasattr(sys, 'abiflags'): pythonlib += sys.abiflags ensure('libraries', pythonlib) if sys.platform == "win32": ensure('extra_link_args', '/MANIFEST') def set_source(self, module_name, source, source_extension='.c', **kwds): import os if hasattr(self, '_assigned_source'): raise ValueError("set_source() cannot be called several times " "per ffi object") if not isinstance(module_name, basestring): raise TypeError("'module_name' must be a string") if os.sep in module_name or (os.altsep and os.altsep in module_name): raise ValueError("'module_name' must not contain '/': use a dotted " "name to make a 'package.module' location") self._assigned_source = (str(module_name), source, source_extension, kwds) def set_source_pkgconfig(self, module_name, pkgconfig_libs, source, source_extension='.c', **kwds): from . import pkgconfig if not isinstance(pkgconfig_libs, list): raise TypeError("the pkgconfig_libs argument must be a list " "of package names") kwds2 = pkgconfig.flags_from_pkgconfig(pkgconfig_libs) pkgconfig.merge_flags(kwds, kwds2) self.set_source(module_name, source, source_extension, **kwds) def distutils_extension(self, tmpdir='build', verbose=True): from distutils.dir_util import mkpath from .recompiler import recompile # if not hasattr(self, '_assigned_source'): if hasattr(self, 'verifier'): # fallback, 'tmpdir' ignored return self.verifier.get_extension() raise ValueError("set_source() must be called before" " distutils_extension()") module_name, source, source_extension, kwds = self._assigned_source if source is None: raise TypeError("distutils_extension() is only for C extension " "modules, not for dlopen()-style pure Python " "modules") mkpath(tmpdir) ext, updated = recompile(self, module_name, source, tmpdir=tmpdir, extradir=tmpdir, source_extension=source_extension, call_c_compiler=False, **kwds) if verbose: if updated: sys.stderr.write("regenerated: %r\n" % (ext.sources[0],)) else: sys.stderr.write("not modified: %r\n" % (ext.sources[0],)) return ext def emit_c_code(self, filename): from .recompiler import recompile # if not hasattr(self, '_assigned_source'): raise ValueError("set_source() must be called before emit_c_code()") module_name, source, source_extension, kwds = self._assigned_source if source is None: raise TypeError("emit_c_code() is only for C extension modules, " "not for dlopen()-style pure Python modules") recompile(self, module_name, source, c_file=filename, call_c_compiler=False, **kwds) def emit_python_code(self, filename): from .recompiler import recompile # if not hasattr(self, '_assigned_source'): raise ValueError("set_source() must be called before emit_c_code()") module_name, source, source_extension, kwds = self._assigned_source if source is not None: raise TypeError("emit_python_code() is only for dlopen()-style " "pure Python modules, not for C extension modules") recompile(self, module_name, source, c_file=filename, call_c_compiler=False, **kwds) def compile(self, tmpdir='.', verbose=0, target=None, debug=None): """The 'target' argument gives the final file name of the compiled DLL. Use '*' to force distutils' choice, suitable for regular CPython C API modules. Use a file name ending in '.*' to ask for the system's default extension for dynamic libraries (.so/.dll/.dylib). The default is '*' when building a non-embedded C API extension, and (module_name + '.*') when building an embedded library. """ from .recompiler import recompile # if not hasattr(self, '_assigned_source'): raise ValueError("set_source() must be called before compile()") module_name, source, source_extension, kwds = self._assigned_source return recompile(self, module_name, source, tmpdir=tmpdir, target=target, source_extension=source_extension, compiler_verbose=verbose, debug=debug, **kwds) def init_once(self, func, tag): # Read _init_once_cache[tag], which is either (False, lock) if # we're calling the function now in some thread, or (True, result). # Don't call setdefault() in most cases, to avoid allocating and # immediately freeing a lock; but still use setdefaut() to avoid # races. try: x = self._init_once_cache[tag] except KeyError: x = self._init_once_cache.setdefault(tag, (False, allocate_lock())) # Common case: we got (True, result), so we return the result. if x[0]: return x[1] # Else, it's a lock. Acquire it to serialize the following tests. with x[1]: # Read again from _init_once_cache the current status. x = self._init_once_cache[tag] if x[0]: return x[1] # Call the function and store the result back. result = func() self._init_once_cache[tag] = (True, result) return result def embedding_init_code(self, pysource): if self._embedding: raise ValueError("embedding_init_code() can only be called once") # fix 'pysource' before it gets dumped into the C file: # - remove empty lines at the beginning, so it starts at "line 1" # - dedent, if all non-empty lines are indented # - check for SyntaxErrors import re match = re.match(r'\s*\n', pysource) if match: pysource = pysource[match.end():] lines = pysource.splitlines() or [''] prefix = re.match(r'\s*', lines[0]).group() for i in range(1, len(lines)): line = lines[i] if line.rstrip(): while not line.startswith(prefix): prefix = prefix[:-1] i = len(prefix) lines = [line[i:]+'\n' for line in lines] pysource = ''.join(lines) # compile(pysource, "cffi_init", "exec") # self._embedding = pysource def def_extern(self, *args, **kwds): raise ValueError("ffi.def_extern() is only available on API-mode FFI " "objects") def list_types(self): """Returns the user type names known to this FFI instance. This returns a tuple containing three lists of names: (typedef_names, names_of_structs, names_of_unions) """ typedefs = [] structs = [] unions = [] for key in self._parser._declarations: if key.startswith('typedef '): typedefs.append(key[8:]) elif key.startswith('struct '): structs.append(key[7:]) elif key.startswith('union '): unions.append(key[6:]) typedefs.sort() structs.sort() unions.sort() return (typedefs, structs, unions) def _load_backend_lib(backend, name, flags): import os if name is None: if sys.platform != "win32": return backend.load_library(None, flags) name = "c" # Windows: load_library(None) fails, but this works # on Python 2 (backward compatibility hack only) first_error = None if '.' in name or '/' in name or os.sep in name: try: return backend.load_library(name, flags) except OSError as e: first_error = e import ctypes.util path = ctypes.util.find_library(name) if path is None: if name == "c" and sys.platform == "win32" and sys.version_info >= (3,): raise OSError("dlopen(None) cannot work on Windows for Python 3 " "(see http://bugs.python.org/issue23606)") msg = ("ctypes.util.find_library() did not manage " "to locate a library called %r" % (name,)) if first_error is not None: msg = "%s. Additionally, %s" % (first_error, msg) raise OSError(msg) return backend.load_library(path, flags) def _make_ffi_library(ffi, libname, flags): backend = ffi._backend backendlib = _load_backend_lib(backend, libname, flags) # def accessor_function(name): key = 'function ' + name tp, _ = ffi._parser._declarations[key] BType = ffi._get_cached_btype(tp) value = backendlib.load_function(BType, name) library.__dict__[name] = value # def accessor_variable(name): key = 'variable ' + name tp, _ = ffi._parser._declarations[key] BType = ffi._get_cached_btype(tp) read_variable = backendlib.read_variable write_variable = backendlib.write_variable setattr(FFILibrary, name, property( lambda self: read_variable(BType, name), lambda self, value: write_variable(BType, name, value))) # def addressof_var(name): try: return addr_variables[name] except KeyError: with ffi._lock: if name not in addr_variables: key = 'variable ' + name tp, _ = ffi._parser._declarations[key] BType = ffi._get_cached_btype(tp) if BType.kind != 'array': BType = model.pointer_cache(ffi, BType) p = backendlib.load_function(BType, name) addr_variables[name] = p return addr_variables[name] # def accessor_constant(name): raise NotImplementedError("non-integer constant '%s' cannot be " "accessed from a dlopen() library" % (name,)) # def accessor_int_constant(name): library.__dict__[name] = ffi._parser._int_constants[name] # accessors = {} accessors_version = [False] addr_variables = {} # def update_accessors(): if accessors_version[0] is ffi._cdef_version: return # for key, (tp, _) in ffi._parser._declarations.items(): if not isinstance(tp, model.EnumType): tag, name = key.split(' ', 1) if tag == 'function': accessors[name] = accessor_function elif tag == 'variable': accessors[name] = accessor_variable elif tag == 'constant': accessors[name] = accessor_constant else: for i, enumname in enumerate(tp.enumerators): def accessor_enum(name, tp=tp, i=i): tp.check_not_partial() library.__dict__[name] = tp.enumvalues[i] accessors[enumname] = accessor_enum for name in ffi._parser._int_constants: accessors.setdefault(name, accessor_int_constant) accessors_version[0] = ffi._cdef_version # def make_accessor(name): with ffi._lock: if name in library.__dict__ or name in FFILibrary.__dict__: return # added by another thread while waiting for the lock if name not in accessors: update_accessors() if name not in accessors: raise AttributeError(name) accessors[name](name) # class FFILibrary(object): def __getattr__(self, name): make_accessor(name) return getattr(self, name) def __setattr__(self, name, value): try: property = getattr(self.__class__, name) except AttributeError: make_accessor(name) setattr(self, name, value) else: property.__set__(self, value) def __dir__(self): with ffi._lock: update_accessors() return accessors.keys() def __addressof__(self, name): if name in library.__dict__: return library.__dict__[name] if name in FFILibrary.__dict__: return addressof_var(name) make_accessor(name) if name in library.__dict__: return library.__dict__[name] if name in FFILibrary.__dict__: return addressof_var(name) raise AttributeError("cffi library has no function or " "global variable named '%s'" % (name,)) def __cffi_close__(self): backendlib.close_lib() self.__dict__.clear() # if libname is not None: try: if not isinstance(libname, str): # unicode, on Python 2 libname = libname.encode('utf-8') FFILibrary.__name__ = 'FFILibrary_%s' % libname except UnicodeError: pass library = FFILibrary() return library, library.__dict__ def _builtin_function_type(func): # a hack to make at least ffi.typeof(builtin_function) work, # if the builtin function was obtained by 'vengine_cpy'. import sys try: module = sys.modules[func.__module__] ffi = module._cffi_original_ffi types_of_builtin_funcs = module._cffi_types_of_builtin_funcs tp = types_of_builtin_funcs[func] except (KeyError, AttributeError, TypeError): return None else: with ffi._lock: return ffi._get_cached_btype(tp) ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/cffi/backend_ctypes.py ================================================ import ctypes, ctypes.util, operator, sys from . import model if sys.version_info < (3,): bytechr = chr else: unicode = str long = int xrange = range bytechr = lambda num: bytes([num]) class CTypesType(type): pass class CTypesData(object): __metaclass__ = CTypesType __slots__ = ['__weakref__'] __name__ = '' def __init__(self, *args): raise TypeError("cannot instantiate %r" % (self.__class__,)) @classmethod def _newp(cls, init): raise TypeError("expected a pointer or array ctype, got '%s'" % (cls._get_c_name(),)) @staticmethod def _to_ctypes(value): raise TypeError @classmethod def _arg_to_ctypes(cls, *value): try: ctype = cls._ctype except AttributeError: raise TypeError("cannot create an instance of %r" % (cls,)) if value: res = cls._to_ctypes(*value) if not isinstance(res, ctype): res = cls._ctype(res) else: res = cls._ctype() return res @classmethod def _create_ctype_obj(cls, init): if init is None: return cls._arg_to_ctypes() else: return cls._arg_to_ctypes(init) @staticmethod def _from_ctypes(ctypes_value): raise TypeError @classmethod def _get_c_name(cls, replace_with=''): return cls._reftypename.replace(' &', replace_with) @classmethod def _fix_class(cls): cls.__name__ = 'CData<%s>' % (cls._get_c_name(),) cls.__qualname__ = 'CData<%s>' % (cls._get_c_name(),) cls.__module__ = 'ffi' def _get_own_repr(self): raise NotImplementedError def _addr_repr(self, address): if address == 0: return 'NULL' else: if address < 0: address += 1 << (8*ctypes.sizeof(ctypes.c_void_p)) return '0x%x' % address def __repr__(self, c_name=None): own = self._get_own_repr() return '' % (c_name or self._get_c_name(), own) def _convert_to_address(self, BClass): if BClass is None: raise TypeError("cannot convert %r to an address" % ( self._get_c_name(),)) else: raise TypeError("cannot convert %r to %r" % ( self._get_c_name(), BClass._get_c_name())) @classmethod def _get_size(cls): return ctypes.sizeof(cls._ctype) def _get_size_of_instance(self): return ctypes.sizeof(self._ctype) @classmethod def _cast_from(cls, source): raise TypeError("cannot cast to %r" % (cls._get_c_name(),)) def _cast_to_integer(self): return self._convert_to_address(None) @classmethod def _alignment(cls): return ctypes.alignment(cls._ctype) def __iter__(self): raise TypeError("cdata %r does not support iteration" % ( self._get_c_name()),) def _make_cmp(name): cmpfunc = getattr(operator, name) def cmp(self, other): v_is_ptr = not isinstance(self, CTypesGenericPrimitive) w_is_ptr = (isinstance(other, CTypesData) and not isinstance(other, CTypesGenericPrimitive)) if v_is_ptr and w_is_ptr: return cmpfunc(self._convert_to_address(None), other._convert_to_address(None)) elif v_is_ptr or w_is_ptr: return NotImplemented else: if isinstance(self, CTypesGenericPrimitive): self = self._value if isinstance(other, CTypesGenericPrimitive): other = other._value return cmpfunc(self, other) cmp.func_name = name return cmp __eq__ = _make_cmp('__eq__') __ne__ = _make_cmp('__ne__') __lt__ = _make_cmp('__lt__') __le__ = _make_cmp('__le__') __gt__ = _make_cmp('__gt__') __ge__ = _make_cmp('__ge__') def __hash__(self): return hash(self._convert_to_address(None)) def _to_string(self, maxlen): raise TypeError("string(): %r" % (self,)) class CTypesGenericPrimitive(CTypesData): __slots__ = [] def __hash__(self): return hash(self._value) def _get_own_repr(self): return repr(self._from_ctypes(self._value)) class CTypesGenericArray(CTypesData): __slots__ = [] @classmethod def _newp(cls, init): return cls(init) def __iter__(self): for i in xrange(len(self)): yield self[i] def _get_own_repr(self): return self._addr_repr(ctypes.addressof(self._blob)) class CTypesGenericPtr(CTypesData): __slots__ = ['_address', '_as_ctype_ptr'] _automatic_casts = False kind = "pointer" @classmethod def _newp(cls, init): return cls(init) @classmethod def _cast_from(cls, source): if source is None: address = 0 elif isinstance(source, CTypesData): address = source._cast_to_integer() elif isinstance(source, (int, long)): address = source else: raise TypeError("bad type for cast to %r: %r" % (cls, type(source).__name__)) return cls._new_pointer_at(address) @classmethod def _new_pointer_at(cls, address): self = cls.__new__(cls) self._address = address self._as_ctype_ptr = ctypes.cast(address, cls._ctype) return self def _get_own_repr(self): try: return self._addr_repr(self._address) except AttributeError: return '???' def _cast_to_integer(self): return self._address def __nonzero__(self): return bool(self._address) __bool__ = __nonzero__ @classmethod def _to_ctypes(cls, value): if not isinstance(value, CTypesData): raise TypeError("unexpected %s object" % type(value).__name__) address = value._convert_to_address(cls) return ctypes.cast(address, cls._ctype) @classmethod def _from_ctypes(cls, ctypes_ptr): address = ctypes.cast(ctypes_ptr, ctypes.c_void_p).value or 0 return cls._new_pointer_at(address) @classmethod def _initialize(cls, ctypes_ptr, value): if value: ctypes_ptr.contents = cls._to_ctypes(value).contents def _convert_to_address(self, BClass): if (BClass in (self.__class__, None) or BClass._automatic_casts or self._automatic_casts): return self._address else: return CTypesData._convert_to_address(self, BClass) class CTypesBaseStructOrUnion(CTypesData): __slots__ = ['_blob'] @classmethod def _create_ctype_obj(cls, init): # may be overridden raise TypeError("cannot instantiate opaque type %s" % (cls,)) def _get_own_repr(self): return self._addr_repr(ctypes.addressof(self._blob)) @classmethod def _offsetof(cls, fieldname): return getattr(cls._ctype, fieldname).offset def _convert_to_address(self, BClass): if getattr(BClass, '_BItem', None) is self.__class__: return ctypes.addressof(self._blob) else: return CTypesData._convert_to_address(self, BClass) @classmethod def _from_ctypes(cls, ctypes_struct_or_union): self = cls.__new__(cls) self._blob = ctypes_struct_or_union return self @classmethod def _to_ctypes(cls, value): return value._blob def __repr__(self, c_name=None): return CTypesData.__repr__(self, c_name or self._get_c_name(' &')) class CTypesBackend(object): PRIMITIVE_TYPES = { 'char': ctypes.c_char, 'short': ctypes.c_short, 'int': ctypes.c_int, 'long': ctypes.c_long, 'long long': ctypes.c_longlong, 'signed char': ctypes.c_byte, 'unsigned char': ctypes.c_ubyte, 'unsigned short': ctypes.c_ushort, 'unsigned int': ctypes.c_uint, 'unsigned long': ctypes.c_ulong, 'unsigned long long': ctypes.c_ulonglong, 'float': ctypes.c_float, 'double': ctypes.c_double, '_Bool': ctypes.c_bool, } for _name in ['unsigned long long', 'unsigned long', 'unsigned int', 'unsigned short', 'unsigned char']: _size = ctypes.sizeof(PRIMITIVE_TYPES[_name]) PRIMITIVE_TYPES['uint%d_t' % (8*_size)] = PRIMITIVE_TYPES[_name] if _size == ctypes.sizeof(ctypes.c_void_p): PRIMITIVE_TYPES['uintptr_t'] = PRIMITIVE_TYPES[_name] if _size == ctypes.sizeof(ctypes.c_size_t): PRIMITIVE_TYPES['size_t'] = PRIMITIVE_TYPES[_name] for _name in ['long long', 'long', 'int', 'short', 'signed char']: _size = ctypes.sizeof(PRIMITIVE_TYPES[_name]) PRIMITIVE_TYPES['int%d_t' % (8*_size)] = PRIMITIVE_TYPES[_name] if _size == ctypes.sizeof(ctypes.c_void_p): PRIMITIVE_TYPES['intptr_t'] = PRIMITIVE_TYPES[_name] PRIMITIVE_TYPES['ptrdiff_t'] = PRIMITIVE_TYPES[_name] if _size == ctypes.sizeof(ctypes.c_size_t): PRIMITIVE_TYPES['ssize_t'] = PRIMITIVE_TYPES[_name] def __init__(self): self.RTLD_LAZY = 0 # not supported anyway by ctypes self.RTLD_NOW = 0 self.RTLD_GLOBAL = ctypes.RTLD_GLOBAL self.RTLD_LOCAL = ctypes.RTLD_LOCAL def set_ffi(self, ffi): self.ffi = ffi def _get_types(self): return CTypesData, CTypesType def load_library(self, path, flags=0): cdll = ctypes.CDLL(path, flags) return CTypesLibrary(self, cdll) def new_void_type(self): class CTypesVoid(CTypesData): __slots__ = [] _reftypename = 'void &' @staticmethod def _from_ctypes(novalue): return None @staticmethod def _to_ctypes(novalue): if novalue is not None: raise TypeError("None expected, got %s object" % (type(novalue).__name__,)) return None CTypesVoid._fix_class() return CTypesVoid def new_primitive_type(self, name): if name == 'wchar_t': raise NotImplementedError(name) ctype = self.PRIMITIVE_TYPES[name] if name == 'char': kind = 'char' elif name in ('float', 'double'): kind = 'float' else: if name in ('signed char', 'unsigned char'): kind = 'byte' elif name == '_Bool': kind = 'bool' else: kind = 'int' is_signed = (ctype(-1).value == -1) # def _cast_source_to_int(source): if isinstance(source, (int, long, float)): source = int(source) elif isinstance(source, CTypesData): source = source._cast_to_integer() elif isinstance(source, bytes): source = ord(source) elif source is None: source = 0 else: raise TypeError("bad type for cast to %r: %r" % (CTypesPrimitive, type(source).__name__)) return source # kind1 = kind class CTypesPrimitive(CTypesGenericPrimitive): __slots__ = ['_value'] _ctype = ctype _reftypename = '%s &' % name kind = kind1 def __init__(self, value): self._value = value @staticmethod def _create_ctype_obj(init): if init is None: return ctype() return ctype(CTypesPrimitive._to_ctypes(init)) if kind == 'int' or kind == 'byte': @classmethod def _cast_from(cls, source): source = _cast_source_to_int(source) source = ctype(source).value # cast within range return cls(source) def __int__(self): return self._value if kind == 'bool': @classmethod def _cast_from(cls, source): if not isinstance(source, (int, long, float)): source = _cast_source_to_int(source) return cls(bool(source)) def __int__(self): return int(self._value) if kind == 'char': @classmethod def _cast_from(cls, source): source = _cast_source_to_int(source) source = bytechr(source & 0xFF) return cls(source) def __int__(self): return ord(self._value) if kind == 'float': @classmethod def _cast_from(cls, source): if isinstance(source, float): pass elif isinstance(source, CTypesGenericPrimitive): if hasattr(source, '__float__'): source = float(source) else: source = int(source) else: source = _cast_source_to_int(source) source = ctype(source).value # fix precision return cls(source) def __int__(self): return int(self._value) def __float__(self): return self._value _cast_to_integer = __int__ if kind == 'int' or kind == 'byte' or kind == 'bool': @staticmethod def _to_ctypes(x): if not isinstance(x, (int, long)): if isinstance(x, CTypesData): x = int(x) else: raise TypeError("integer expected, got %s" % type(x).__name__) if ctype(x).value != x: if not is_signed and x < 0: raise OverflowError("%s: negative integer" % name) else: raise OverflowError("%s: integer out of bounds" % name) return x if kind == 'char': @staticmethod def _to_ctypes(x): if isinstance(x, bytes) and len(x) == 1: return x if isinstance(x, CTypesPrimitive): # > return x._value raise TypeError("character expected, got %s" % type(x).__name__) def __nonzero__(self): return ord(self._value) != 0 else: def __nonzero__(self): return self._value != 0 __bool__ = __nonzero__ if kind == 'float': @staticmethod def _to_ctypes(x): if not isinstance(x, (int, long, float, CTypesData)): raise TypeError("float expected, got %s" % type(x).__name__) return ctype(x).value @staticmethod def _from_ctypes(value): return getattr(value, 'value', value) @staticmethod def _initialize(blob, init): blob.value = CTypesPrimitive._to_ctypes(init) if kind == 'char': def _to_string(self, maxlen): return self._value if kind == 'byte': def _to_string(self, maxlen): return chr(self._value & 0xff) # CTypesPrimitive._fix_class() return CTypesPrimitive def new_pointer_type(self, BItem): getbtype = self.ffi._get_cached_btype if BItem is getbtype(model.PrimitiveType('char')): kind = 'charp' elif BItem in (getbtype(model.PrimitiveType('signed char')), getbtype(model.PrimitiveType('unsigned char'))): kind = 'bytep' elif BItem is getbtype(model.void_type): kind = 'voidp' else: kind = 'generic' # class CTypesPtr(CTypesGenericPtr): __slots__ = ['_own'] if kind == 'charp': __slots__ += ['__as_strbuf'] _BItem = BItem if hasattr(BItem, '_ctype'): _ctype = ctypes.POINTER(BItem._ctype) _bitem_size = ctypes.sizeof(BItem._ctype) else: _ctype = ctypes.c_void_p if issubclass(BItem, CTypesGenericArray): _reftypename = BItem._get_c_name('(* &)') else: _reftypename = BItem._get_c_name(' * &') def __init__(self, init): ctypeobj = BItem._create_ctype_obj(init) if kind == 'charp': self.__as_strbuf = ctypes.create_string_buffer( ctypeobj.value + b'\x00') self._as_ctype_ptr = ctypes.cast( self.__as_strbuf, self._ctype) else: self._as_ctype_ptr = ctypes.pointer(ctypeobj) self._address = ctypes.cast(self._as_ctype_ptr, ctypes.c_void_p).value self._own = True def __add__(self, other): if isinstance(other, (int, long)): return self._new_pointer_at(self._address + other * self._bitem_size) else: return NotImplemented def __sub__(self, other): if isinstance(other, (int, long)): return self._new_pointer_at(self._address - other * self._bitem_size) elif type(self) is type(other): return (self._address - other._address) // self._bitem_size else: return NotImplemented def __getitem__(self, index): if getattr(self, '_own', False) and index != 0: raise IndexError return BItem._from_ctypes(self._as_ctype_ptr[index]) def __setitem__(self, index, value): self._as_ctype_ptr[index] = BItem._to_ctypes(value) if kind == 'charp' or kind == 'voidp': @classmethod def _arg_to_ctypes(cls, *value): if value and isinstance(value[0], bytes): return ctypes.c_char_p(value[0]) else: return super(CTypesPtr, cls)._arg_to_ctypes(*value) if kind == 'charp' or kind == 'bytep': def _to_string(self, maxlen): if maxlen < 0: maxlen = sys.maxsize p = ctypes.cast(self._as_ctype_ptr, ctypes.POINTER(ctypes.c_char)) n = 0 while n < maxlen and p[n] != b'\x00': n += 1 return b''.join([p[i] for i in range(n)]) def _get_own_repr(self): if getattr(self, '_own', False): return 'owning %d bytes' % ( ctypes.sizeof(self._as_ctype_ptr.contents),) return super(CTypesPtr, self)._get_own_repr() # if (BItem is self.ffi._get_cached_btype(model.void_type) or BItem is self.ffi._get_cached_btype(model.PrimitiveType('char'))): CTypesPtr._automatic_casts = True # CTypesPtr._fix_class() return CTypesPtr def new_array_type(self, CTypesPtr, length): if length is None: brackets = ' &[]' else: brackets = ' &[%d]' % length BItem = CTypesPtr._BItem getbtype = self.ffi._get_cached_btype if BItem is getbtype(model.PrimitiveType('char')): kind = 'char' elif BItem in (getbtype(model.PrimitiveType('signed char')), getbtype(model.PrimitiveType('unsigned char'))): kind = 'byte' else: kind = 'generic' # class CTypesArray(CTypesGenericArray): __slots__ = ['_blob', '_own'] if length is not None: _ctype = BItem._ctype * length else: __slots__.append('_ctype') _reftypename = BItem._get_c_name(brackets) _declared_length = length _CTPtr = CTypesPtr def __init__(self, init): if length is None: if isinstance(init, (int, long)): len1 = init init = None elif kind == 'char' and isinstance(init, bytes): len1 = len(init) + 1 # extra null else: init = tuple(init) len1 = len(init) self._ctype = BItem._ctype * len1 self._blob = self._ctype() self._own = True if init is not None: self._initialize(self._blob, init) @staticmethod def _initialize(blob, init): if isinstance(init, bytes): init = [init[i:i+1] for i in range(len(init))] else: if isinstance(init, CTypesGenericArray): if (len(init) != len(blob) or not isinstance(init, CTypesArray)): raise TypeError("length/type mismatch: %s" % (init,)) init = tuple(init) if len(init) > len(blob): raise IndexError("too many initializers") addr = ctypes.cast(blob, ctypes.c_void_p).value PTR = ctypes.POINTER(BItem._ctype) itemsize = ctypes.sizeof(BItem._ctype) for i, value in enumerate(init): p = ctypes.cast(addr + i * itemsize, PTR) BItem._initialize(p.contents, value) def __len__(self): return len(self._blob) def __getitem__(self, index): if not (0 <= index < len(self._blob)): raise IndexError return BItem._from_ctypes(self._blob[index]) def __setitem__(self, index, value): if not (0 <= index < len(self._blob)): raise IndexError self._blob[index] = BItem._to_ctypes(value) if kind == 'char' or kind == 'byte': def _to_string(self, maxlen): if maxlen < 0: maxlen = len(self._blob) p = ctypes.cast(self._blob, ctypes.POINTER(ctypes.c_char)) n = 0 while n < maxlen and p[n] != b'\x00': n += 1 return b''.join([p[i] for i in range(n)]) def _get_own_repr(self): if getattr(self, '_own', False): return 'owning %d bytes' % (ctypes.sizeof(self._blob),) return super(CTypesArray, self)._get_own_repr() def _convert_to_address(self, BClass): if BClass in (CTypesPtr, None) or BClass._automatic_casts: return ctypes.addressof(self._blob) else: return CTypesData._convert_to_address(self, BClass) @staticmethod def _from_ctypes(ctypes_array): self = CTypesArray.__new__(CTypesArray) self._blob = ctypes_array return self @staticmethod def _arg_to_ctypes(value): return CTypesPtr._arg_to_ctypes(value) def __add__(self, other): if isinstance(other, (int, long)): return CTypesPtr._new_pointer_at( ctypes.addressof(self._blob) + other * ctypes.sizeof(BItem._ctype)) else: return NotImplemented @classmethod def _cast_from(cls, source): raise NotImplementedError("casting to %r" % ( cls._get_c_name(),)) # CTypesArray._fix_class() return CTypesArray def _new_struct_or_union(self, kind, name, base_ctypes_class): # class struct_or_union(base_ctypes_class): pass struct_or_union.__name__ = '%s_%s' % (kind, name) kind1 = kind # class CTypesStructOrUnion(CTypesBaseStructOrUnion): __slots__ = ['_blob'] _ctype = struct_or_union _reftypename = '%s &' % (name,) _kind = kind = kind1 # CTypesStructOrUnion._fix_class() return CTypesStructOrUnion def new_struct_type(self, name): return self._new_struct_or_union('struct', name, ctypes.Structure) def new_union_type(self, name): return self._new_struct_or_union('union', name, ctypes.Union) def complete_struct_or_union(self, CTypesStructOrUnion, fields, tp, totalsize=-1, totalalignment=-1, sflags=0, pack=0): if totalsize >= 0 or totalalignment >= 0: raise NotImplementedError("the ctypes backend of CFFI does not support " "structures completed by verify(); please " "compile and install the _cffi_backend module.") struct_or_union = CTypesStructOrUnion._ctype fnames = [fname for (fname, BField, bitsize) in fields] btypes = [BField for (fname, BField, bitsize) in fields] bitfields = [bitsize for (fname, BField, bitsize) in fields] # bfield_types = {} cfields = [] for (fname, BField, bitsize) in fields: if bitsize < 0: cfields.append((fname, BField._ctype)) bfield_types[fname] = BField else: cfields.append((fname, BField._ctype, bitsize)) bfield_types[fname] = Ellipsis if sflags & 8: struct_or_union._pack_ = 1 elif pack: struct_or_union._pack_ = pack struct_or_union._fields_ = cfields CTypesStructOrUnion._bfield_types = bfield_types # @staticmethod def _create_ctype_obj(init): result = struct_or_union() if init is not None: initialize(result, init) return result CTypesStructOrUnion._create_ctype_obj = _create_ctype_obj # def initialize(blob, init): if is_union: if len(init) > 1: raise ValueError("union initializer: %d items given, but " "only one supported (use a dict if needed)" % (len(init),)) if not isinstance(init, dict): if isinstance(init, (bytes, unicode)): raise TypeError("union initializer: got a str") init = tuple(init) if len(init) > len(fnames): raise ValueError("too many values for %s initializer" % CTypesStructOrUnion._get_c_name()) init = dict(zip(fnames, init)) addr = ctypes.addressof(blob) for fname, value in init.items(): BField, bitsize = name2fieldtype[fname] assert bitsize < 0, \ "not implemented: initializer with bit fields" offset = CTypesStructOrUnion._offsetof(fname) PTR = ctypes.POINTER(BField._ctype) p = ctypes.cast(addr + offset, PTR) BField._initialize(p.contents, value) is_union = CTypesStructOrUnion._kind == 'union' name2fieldtype = dict(zip(fnames, zip(btypes, bitfields))) # for fname, BField, bitsize in fields: if fname == '': raise NotImplementedError("nested anonymous structs/unions") if hasattr(CTypesStructOrUnion, fname): raise ValueError("the field name %r conflicts in " "the ctypes backend" % fname) if bitsize < 0: def getter(self, fname=fname, BField=BField, offset=CTypesStructOrUnion._offsetof(fname), PTR=ctypes.POINTER(BField._ctype)): addr = ctypes.addressof(self._blob) p = ctypes.cast(addr + offset, PTR) return BField._from_ctypes(p.contents) def setter(self, value, fname=fname, BField=BField): setattr(self._blob, fname, BField._to_ctypes(value)) # if issubclass(BField, CTypesGenericArray): setter = None if BField._declared_length == 0: def getter(self, fname=fname, BFieldPtr=BField._CTPtr, offset=CTypesStructOrUnion._offsetof(fname), PTR=ctypes.POINTER(BField._ctype)): addr = ctypes.addressof(self._blob) p = ctypes.cast(addr + offset, PTR) return BFieldPtr._from_ctypes(p) # else: def getter(self, fname=fname, BField=BField): return BField._from_ctypes(getattr(self._blob, fname)) def setter(self, value, fname=fname, BField=BField): # xxx obscure workaround value = BField._to_ctypes(value) oldvalue = getattr(self._blob, fname) setattr(self._blob, fname, value) if value != getattr(self._blob, fname): setattr(self._blob, fname, oldvalue) raise OverflowError("value too large for bitfield") setattr(CTypesStructOrUnion, fname, property(getter, setter)) # CTypesPtr = self.ffi._get_cached_btype(model.PointerType(tp)) for fname in fnames: if hasattr(CTypesPtr, fname): raise ValueError("the field name %r conflicts in " "the ctypes backend" % fname) def getter(self, fname=fname): return getattr(self[0], fname) def setter(self, value, fname=fname): setattr(self[0], fname, value) setattr(CTypesPtr, fname, property(getter, setter)) def new_function_type(self, BArgs, BResult, has_varargs): nameargs = [BArg._get_c_name() for BArg in BArgs] if has_varargs: nameargs.append('...') nameargs = ', '.join(nameargs) # class CTypesFunctionPtr(CTypesGenericPtr): __slots__ = ['_own_callback', '_name'] _ctype = ctypes.CFUNCTYPE(getattr(BResult, '_ctype', None), *[BArg._ctype for BArg in BArgs], use_errno=True) _reftypename = BResult._get_c_name('(* &)(%s)' % (nameargs,)) def __init__(self, init, error=None): # create a callback to the Python callable init() import traceback assert not has_varargs, "varargs not supported for callbacks" if getattr(BResult, '_ctype', None) is not None: error = BResult._from_ctypes( BResult._create_ctype_obj(error)) else: error = None def callback(*args): args2 = [] for arg, BArg in zip(args, BArgs): args2.append(BArg._from_ctypes(arg)) try: res2 = init(*args2) res2 = BResult._to_ctypes(res2) except: traceback.print_exc() res2 = error if issubclass(BResult, CTypesGenericPtr): if res2: res2 = ctypes.cast(res2, ctypes.c_void_p).value # .value: http://bugs.python.org/issue1574593 else: res2 = None #print repr(res2) return res2 if issubclass(BResult, CTypesGenericPtr): # The only pointers callbacks can return are void*s: # http://bugs.python.org/issue5710 callback_ctype = ctypes.CFUNCTYPE( ctypes.c_void_p, *[BArg._ctype for BArg in BArgs], use_errno=True) else: callback_ctype = CTypesFunctionPtr._ctype self._as_ctype_ptr = callback_ctype(callback) self._address = ctypes.cast(self._as_ctype_ptr, ctypes.c_void_p).value self._own_callback = init @staticmethod def _initialize(ctypes_ptr, value): if value: raise NotImplementedError("ctypes backend: not supported: " "initializers for function pointers") def __repr__(self): c_name = getattr(self, '_name', None) if c_name: i = self._reftypename.index('(* &)') if self._reftypename[i-1] not in ' )*': c_name = ' ' + c_name c_name = self._reftypename.replace('(* &)', c_name) return CTypesData.__repr__(self, c_name) def _get_own_repr(self): if getattr(self, '_own_callback', None) is not None: return 'calling %r' % (self._own_callback,) return super(CTypesFunctionPtr, self)._get_own_repr() def __call__(self, *args): if has_varargs: assert len(args) >= len(BArgs) extraargs = args[len(BArgs):] args = args[:len(BArgs)] else: assert len(args) == len(BArgs) ctypes_args = [] for arg, BArg in zip(args, BArgs): ctypes_args.append(BArg._arg_to_ctypes(arg)) if has_varargs: for i, arg in enumerate(extraargs): if arg is None: ctypes_args.append(ctypes.c_void_p(0)) # NULL continue if not isinstance(arg, CTypesData): raise TypeError( "argument %d passed in the variadic part " "needs to be a cdata object (got %s)" % (1 + len(BArgs) + i, type(arg).__name__)) ctypes_args.append(arg._arg_to_ctypes(arg)) result = self._as_ctype_ptr(*ctypes_args) return BResult._from_ctypes(result) # CTypesFunctionPtr._fix_class() return CTypesFunctionPtr def new_enum_type(self, name, enumerators, enumvalues, CTypesInt): assert isinstance(name, str) reverse_mapping = dict(zip(reversed(enumvalues), reversed(enumerators))) # class CTypesEnum(CTypesInt): __slots__ = [] _reftypename = '%s &' % name def _get_own_repr(self): value = self._value try: return '%d: %s' % (value, reverse_mapping[value]) except KeyError: return str(value) def _to_string(self, maxlen): value = self._value try: return reverse_mapping[value] except KeyError: return str(value) # CTypesEnum._fix_class() return CTypesEnum def get_errno(self): return ctypes.get_errno() def set_errno(self, value): ctypes.set_errno(value) def string(self, b, maxlen=-1): return b._to_string(maxlen) def buffer(self, bptr, size=-1): raise NotImplementedError("buffer() with ctypes backend") def sizeof(self, cdata_or_BType): if isinstance(cdata_or_BType, CTypesData): return cdata_or_BType._get_size_of_instance() else: assert issubclass(cdata_or_BType, CTypesData) return cdata_or_BType._get_size() def alignof(self, BType): assert issubclass(BType, CTypesData) return BType._alignment() def newp(self, BType, source): if not issubclass(BType, CTypesData): raise TypeError return BType._newp(source) def cast(self, BType, source): return BType._cast_from(source) def callback(self, BType, source, error, onerror): assert onerror is None # XXX not implemented return BType(source, error) _weakref_cache_ref = None def gcp(self, cdata, destructor, size=0): if self._weakref_cache_ref is None: import weakref class MyRef(weakref.ref): def __eq__(self, other): myref = self() return self is other or ( myref is not None and myref is other()) def __ne__(self, other): return not (self == other) def __hash__(self): try: return self._hash except AttributeError: self._hash = hash(self()) return self._hash self._weakref_cache_ref = {}, MyRef weak_cache, MyRef = self._weakref_cache_ref if destructor is None: try: del weak_cache[MyRef(cdata)] except KeyError: raise TypeError("Can remove destructor only on a object " "previously returned by ffi.gc()") return None def remove(k): cdata, destructor = weak_cache.pop(k, (None, None)) if destructor is not None: destructor(cdata) new_cdata = self.cast(self.typeof(cdata), cdata) assert new_cdata is not cdata weak_cache[MyRef(new_cdata, remove)] = (cdata, destructor) return new_cdata typeof = type def getcname(self, BType, replace_with): return BType._get_c_name(replace_with) def typeoffsetof(self, BType, fieldname, num=0): if isinstance(fieldname, str): if num == 0 and issubclass(BType, CTypesGenericPtr): BType = BType._BItem if not issubclass(BType, CTypesBaseStructOrUnion): raise TypeError("expected a struct or union ctype") BField = BType._bfield_types[fieldname] if BField is Ellipsis: raise TypeError("not supported for bitfields") return (BField, BType._offsetof(fieldname)) elif isinstance(fieldname, (int, long)): if issubclass(BType, CTypesGenericArray): BType = BType._CTPtr if not issubclass(BType, CTypesGenericPtr): raise TypeError("expected an array or ptr ctype") BItem = BType._BItem offset = BItem._get_size() * fieldname if offset > sys.maxsize: raise OverflowError return (BItem, offset) else: raise TypeError(type(fieldname)) def rawaddressof(self, BTypePtr, cdata, offset=None): if isinstance(cdata, CTypesBaseStructOrUnion): ptr = ctypes.pointer(type(cdata)._to_ctypes(cdata)) elif isinstance(cdata, CTypesGenericPtr): if offset is None or not issubclass(type(cdata)._BItem, CTypesBaseStructOrUnion): raise TypeError("unexpected cdata type") ptr = type(cdata)._to_ctypes(cdata) elif isinstance(cdata, CTypesGenericArray): ptr = type(cdata)._to_ctypes(cdata) else: raise TypeError("expected a ") if offset: ptr = ctypes.cast( ctypes.c_void_p( ctypes.cast(ptr, ctypes.c_void_p).value + offset), type(ptr)) return BTypePtr._from_ctypes(ptr) class CTypesLibrary(object): def __init__(self, backend, cdll): self.backend = backend self.cdll = cdll def load_function(self, BType, name): c_func = getattr(self.cdll, name) funcobj = BType._from_ctypes(c_func) funcobj._name = name return funcobj def read_variable(self, BType, name): try: ctypes_obj = BType._ctype.in_dll(self.cdll, name) except AttributeError as e: raise NotImplementedError(e) return BType._from_ctypes(ctypes_obj) def write_variable(self, BType, name, value): new_ctypes_obj = BType._to_ctypes(value) ctypes_obj = BType._ctype.in_dll(self.cdll, name) ctypes.memmove(ctypes.addressof(ctypes_obj), ctypes.addressof(new_ctypes_obj), ctypes.sizeof(BType._ctype)) ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/cffi/cffi_opcode.py ================================================ from .error import VerificationError class CffiOp(object): def __init__(self, op, arg): self.op = op self.arg = arg def as_c_expr(self): if self.op is None: assert isinstance(self.arg, str) return '(_cffi_opcode_t)(%s)' % (self.arg,) classname = CLASS_NAME[self.op] return '_CFFI_OP(_CFFI_OP_%s, %s)' % (classname, self.arg) def as_python_bytes(self): if self.op is None and self.arg.isdigit(): value = int(self.arg) # non-negative: '-' not in self.arg if value >= 2**31: raise OverflowError("cannot emit %r: limited to 2**31-1" % (self.arg,)) return format_four_bytes(value) if isinstance(self.arg, str): raise VerificationError("cannot emit to Python: %r" % (self.arg,)) return format_four_bytes((self.arg << 8) | self.op) def __str__(self): classname = CLASS_NAME.get(self.op, self.op) return '(%s %s)' % (classname, self.arg) def format_four_bytes(num): return '\\x%02X\\x%02X\\x%02X\\x%02X' % ( (num >> 24) & 0xFF, (num >> 16) & 0xFF, (num >> 8) & 0xFF, (num ) & 0xFF) OP_PRIMITIVE = 1 OP_POINTER = 3 OP_ARRAY = 5 OP_OPEN_ARRAY = 7 OP_STRUCT_UNION = 9 OP_ENUM = 11 OP_FUNCTION = 13 OP_FUNCTION_END = 15 OP_NOOP = 17 OP_BITFIELD = 19 OP_TYPENAME = 21 OP_CPYTHON_BLTN_V = 23 # varargs OP_CPYTHON_BLTN_N = 25 # noargs OP_CPYTHON_BLTN_O = 27 # O (i.e. a single arg) OP_CONSTANT = 29 OP_CONSTANT_INT = 31 OP_GLOBAL_VAR = 33 OP_DLOPEN_FUNC = 35 OP_DLOPEN_CONST = 37 OP_GLOBAL_VAR_F = 39 OP_EXTERN_PYTHON = 41 PRIM_VOID = 0 PRIM_BOOL = 1 PRIM_CHAR = 2 PRIM_SCHAR = 3 PRIM_UCHAR = 4 PRIM_SHORT = 5 PRIM_USHORT = 6 PRIM_INT = 7 PRIM_UINT = 8 PRIM_LONG = 9 PRIM_ULONG = 10 PRIM_LONGLONG = 11 PRIM_ULONGLONG = 12 PRIM_FLOAT = 13 PRIM_DOUBLE = 14 PRIM_LONGDOUBLE = 15 PRIM_WCHAR = 16 PRIM_INT8 = 17 PRIM_UINT8 = 18 PRIM_INT16 = 19 PRIM_UINT16 = 20 PRIM_INT32 = 21 PRIM_UINT32 = 22 PRIM_INT64 = 23 PRIM_UINT64 = 24 PRIM_INTPTR = 25 PRIM_UINTPTR = 26 PRIM_PTRDIFF = 27 PRIM_SIZE = 28 PRIM_SSIZE = 29 PRIM_INT_LEAST8 = 30 PRIM_UINT_LEAST8 = 31 PRIM_INT_LEAST16 = 32 PRIM_UINT_LEAST16 = 33 PRIM_INT_LEAST32 = 34 PRIM_UINT_LEAST32 = 35 PRIM_INT_LEAST64 = 36 PRIM_UINT_LEAST64 = 37 PRIM_INT_FAST8 = 38 PRIM_UINT_FAST8 = 39 PRIM_INT_FAST16 = 40 PRIM_UINT_FAST16 = 41 PRIM_INT_FAST32 = 42 PRIM_UINT_FAST32 = 43 PRIM_INT_FAST64 = 44 PRIM_UINT_FAST64 = 45 PRIM_INTMAX = 46 PRIM_UINTMAX = 47 PRIM_FLOATCOMPLEX = 48 PRIM_DOUBLECOMPLEX = 49 PRIM_CHAR16 = 50 PRIM_CHAR32 = 51 _NUM_PRIM = 52 _UNKNOWN_PRIM = -1 _UNKNOWN_FLOAT_PRIM = -2 _UNKNOWN_LONG_DOUBLE = -3 _IO_FILE_STRUCT = -1 PRIMITIVE_TO_INDEX = { 'char': PRIM_CHAR, 'short': PRIM_SHORT, 'int': PRIM_INT, 'long': PRIM_LONG, 'long long': PRIM_LONGLONG, 'signed char': PRIM_SCHAR, 'unsigned char': PRIM_UCHAR, 'unsigned short': PRIM_USHORT, 'unsigned int': PRIM_UINT, 'unsigned long': PRIM_ULONG, 'unsigned long long': PRIM_ULONGLONG, 'float': PRIM_FLOAT, 'double': PRIM_DOUBLE, 'long double': PRIM_LONGDOUBLE, 'float _Complex': PRIM_FLOATCOMPLEX, 'double _Complex': PRIM_DOUBLECOMPLEX, '_Bool': PRIM_BOOL, 'wchar_t': PRIM_WCHAR, 'char16_t': PRIM_CHAR16, 'char32_t': PRIM_CHAR32, 'int8_t': PRIM_INT8, 'uint8_t': PRIM_UINT8, 'int16_t': PRIM_INT16, 'uint16_t': PRIM_UINT16, 'int32_t': PRIM_INT32, 'uint32_t': PRIM_UINT32, 'int64_t': PRIM_INT64, 'uint64_t': PRIM_UINT64, 'intptr_t': PRIM_INTPTR, 'uintptr_t': PRIM_UINTPTR, 'ptrdiff_t': PRIM_PTRDIFF, 'size_t': PRIM_SIZE, 'ssize_t': PRIM_SSIZE, 'int_least8_t': PRIM_INT_LEAST8, 'uint_least8_t': PRIM_UINT_LEAST8, 'int_least16_t': PRIM_INT_LEAST16, 'uint_least16_t': PRIM_UINT_LEAST16, 'int_least32_t': PRIM_INT_LEAST32, 'uint_least32_t': PRIM_UINT_LEAST32, 'int_least64_t': PRIM_INT_LEAST64, 'uint_least64_t': PRIM_UINT_LEAST64, 'int_fast8_t': PRIM_INT_FAST8, 'uint_fast8_t': PRIM_UINT_FAST8, 'int_fast16_t': PRIM_INT_FAST16, 'uint_fast16_t': PRIM_UINT_FAST16, 'int_fast32_t': PRIM_INT_FAST32, 'uint_fast32_t': PRIM_UINT_FAST32, 'int_fast64_t': PRIM_INT_FAST64, 'uint_fast64_t': PRIM_UINT_FAST64, 'intmax_t': PRIM_INTMAX, 'uintmax_t': PRIM_UINTMAX, } F_UNION = 0x01 F_CHECK_FIELDS = 0x02 F_PACKED = 0x04 F_EXTERNAL = 0x08 F_OPAQUE = 0x10 G_FLAGS = dict([('_CFFI_' + _key, globals()[_key]) for _key in ['F_UNION', 'F_CHECK_FIELDS', 'F_PACKED', 'F_EXTERNAL', 'F_OPAQUE']]) CLASS_NAME = {} for _name, _value in list(globals().items()): if _name.startswith('OP_') and isinstance(_value, int): CLASS_NAME[_value] = _name[3:] ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/cffi/commontypes.py ================================================ import sys from . import model from .error import FFIError COMMON_TYPES = {} try: # fetch "bool" and all simple Windows types from _cffi_backend import _get_common_types _get_common_types(COMMON_TYPES) except ImportError: pass COMMON_TYPES['FILE'] = model.unknown_type('FILE', '_IO_FILE') COMMON_TYPES['bool'] = '_Bool' # in case we got ImportError above for _type in model.PrimitiveType.ALL_PRIMITIVE_TYPES: if _type.endswith('_t'): COMMON_TYPES[_type] = _type del _type _CACHE = {} def resolve_common_type(parser, commontype): try: return _CACHE[commontype] except KeyError: cdecl = COMMON_TYPES.get(commontype, commontype) if not isinstance(cdecl, str): result, quals = cdecl, 0 # cdecl is already a BaseType elif cdecl in model.PrimitiveType.ALL_PRIMITIVE_TYPES: result, quals = model.PrimitiveType(cdecl), 0 elif cdecl == 'set-unicode-needed': raise FFIError("The Windows type %r is only available after " "you call ffi.set_unicode()" % (commontype,)) else: if commontype == cdecl: raise FFIError( "Unsupported type: %r. Please look at " "http://cffi.readthedocs.io/en/latest/cdef.html#ffi-cdef-limitations " "and file an issue if you think this type should really " "be supported." % (commontype,)) result, quals = parser.parse_type_and_quals(cdecl) # recursive assert isinstance(result, model.BaseTypeByIdentity) _CACHE[commontype] = result, quals return result, quals # ____________________________________________________________ # extra types for Windows (most of them are in commontypes.c) def win_common_types(): return { "UNICODE_STRING": model.StructType( "_UNICODE_STRING", ["Length", "MaximumLength", "Buffer"], [model.PrimitiveType("unsigned short"), model.PrimitiveType("unsigned short"), model.PointerType(model.PrimitiveType("wchar_t"))], [-1, -1, -1]), "PUNICODE_STRING": "UNICODE_STRING *", "PCUNICODE_STRING": "const UNICODE_STRING *", "TBYTE": "set-unicode-needed", "TCHAR": "set-unicode-needed", "LPCTSTR": "set-unicode-needed", "PCTSTR": "set-unicode-needed", "LPTSTR": "set-unicode-needed", "PTSTR": "set-unicode-needed", "PTBYTE": "set-unicode-needed", "PTCHAR": "set-unicode-needed", } if sys.platform == 'win32': COMMON_TYPES.update(win_common_types()) ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/cffi/cparser.py ================================================ from . import model from .commontypes import COMMON_TYPES, resolve_common_type from .error import FFIError, CDefError try: from . import _pycparser as pycparser except ImportError: import pycparser import weakref, re, sys try: if sys.version_info < (3,): import thread as _thread else: import _thread lock = _thread.allocate_lock() except ImportError: lock = None def _workaround_for_static_import_finders(): # Issue #392: packaging tools like cx_Freeze can not find these # because pycparser uses exec dynamic import. This is an obscure # workaround. This function is never called. import pycparser.yacctab import pycparser.lextab CDEF_SOURCE_STRING = "" _r_comment = re.compile(r"/\*.*?\*/|//([^\n\\]|\\.)*?$", re.DOTALL | re.MULTILINE) _r_define = re.compile(r"^\s*#\s*define\s+([A-Za-z_][A-Za-z_0-9]*)" r"\b((?:[^\n\\]|\\.)*?)$", re.DOTALL | re.MULTILINE) _r_partial_enum = re.compile(r"=\s*\.\.\.\s*[,}]|\.\.\.\s*\}") _r_enum_dotdotdot = re.compile(r"__dotdotdot\d+__$") _r_partial_array = re.compile(r"\[\s*\.\.\.\s*\]") _r_words = re.compile(r"\w+|\S") _parser_cache = None _r_int_literal = re.compile(r"-?0?x?[0-9a-f]+[lu]*$", re.IGNORECASE) _r_stdcall1 = re.compile(r"\b(__stdcall|WINAPI)\b") _r_stdcall2 = re.compile(r"[(]\s*(__stdcall|WINAPI)\b") _r_cdecl = re.compile(r"\b__cdecl\b") _r_extern_python = re.compile(r'\bextern\s*"' r'(Python|Python\s*\+\s*C|C\s*\+\s*Python)"\s*.') _r_star_const_space = re.compile( # matches "* const " r"[*]\s*((const|volatile|restrict)\b\s*)+") _r_int_dotdotdot = re.compile(r"(\b(int|long|short|signed|unsigned|char)\s*)+" r"\.\.\.") _r_float_dotdotdot = re.compile(r"\b(double|float)\s*\.\.\.") def _get_parser(): global _parser_cache if _parser_cache is None: _parser_cache = pycparser.CParser() return _parser_cache def _workaround_for_old_pycparser(csource): # Workaround for a pycparser issue (fixed between pycparser 2.10 and # 2.14): "char*const***" gives us a wrong syntax tree, the same as # for "char***(*const)". This means we can't tell the difference # afterwards. But "char(*const(***))" gives us the right syntax # tree. The issue only occurs if there are several stars in # sequence with no parenthesis inbetween, just possibly qualifiers. # Attempt to fix it by adding some parentheses in the source: each # time we see "* const" or "* const *", we add an opening # parenthesis before each star---the hard part is figuring out where # to close them. parts = [] while True: match = _r_star_const_space.search(csource) if not match: break #print repr(''.join(parts)+csource), '=>', parts.append(csource[:match.start()]) parts.append('('); closing = ')' parts.append(match.group()) # e.g. "* const " endpos = match.end() if csource.startswith('*', endpos): parts.append('('); closing += ')' level = 0 i = endpos while i < len(csource): c = csource[i] if c == '(': level += 1 elif c == ')': if level == 0: break level -= 1 elif c in ',;=': if level == 0: break i += 1 csource = csource[endpos:i] + closing + csource[i:] #print repr(''.join(parts)+csource) parts.append(csource) return ''.join(parts) def _preprocess_extern_python(csource): # input: `extern "Python" int foo(int);` or # `extern "Python" { int foo(int); }` # output: # void __cffi_extern_python_start; # int foo(int); # void __cffi_extern_python_stop; # # input: `extern "Python+C" int foo(int);` # output: # void __cffi_extern_python_plus_c_start; # int foo(int); # void __cffi_extern_python_stop; parts = [] while True: match = _r_extern_python.search(csource) if not match: break endpos = match.end() - 1 #print #print ''.join(parts)+csource #print '=>' parts.append(csource[:match.start()]) if 'C' in match.group(1): parts.append('void __cffi_extern_python_plus_c_start; ') else: parts.append('void __cffi_extern_python_start; ') if csource[endpos] == '{': # grouping variant closing = csource.find('}', endpos) if closing < 0: raise CDefError("'extern \"Python\" {': no '}' found") if csource.find('{', endpos + 1, closing) >= 0: raise NotImplementedError("cannot use { } inside a block " "'extern \"Python\" { ... }'") parts.append(csource[endpos+1:closing]) csource = csource[closing+1:] else: # non-grouping variant semicolon = csource.find(';', endpos) if semicolon < 0: raise CDefError("'extern \"Python\": no ';' found") parts.append(csource[endpos:semicolon+1]) csource = csource[semicolon+1:] parts.append(' void __cffi_extern_python_stop;') #print ''.join(parts)+csource #print parts.append(csource) return ''.join(parts) def _warn_for_string_literal(csource): if '"' not in csource: return for line in csource.splitlines(): if '"' in line and not line.lstrip().startswith('#'): import warnings warnings.warn("String literal found in cdef() or type source. " "String literals are ignored here, but you should " "remove them anyway because some character sequences " "confuse pre-parsing.") break def _warn_for_non_extern_non_static_global_variable(decl): if not decl.storage: import warnings warnings.warn("Declaration of global variable '%s' in cdef() should " "be marked 'extern' for consistency (or possibly " "'static' in API mode)" % (decl.name,)) def _preprocess(csource): # Remove comments. NOTE: this only work because the cdef() section # should not contain any string literal! csource = _r_comment.sub(' ', csource) # Remove the "#define FOO x" lines macros = {} for match in _r_define.finditer(csource): macroname, macrovalue = match.groups() macrovalue = macrovalue.replace('\\\n', '').strip() macros[macroname] = macrovalue csource = _r_define.sub('', csource) # if pycparser.__version__ < '2.14': csource = _workaround_for_old_pycparser(csource) # # BIG HACK: replace WINAPI or __stdcall with "volatile const". # It doesn't make sense for the return type of a function to be # "volatile volatile const", so we abuse it to detect __stdcall... # Hack number 2 is that "int(volatile *fptr)();" is not valid C # syntax, so we place the "volatile" before the opening parenthesis. csource = _r_stdcall2.sub(' volatile volatile const(', csource) csource = _r_stdcall1.sub(' volatile volatile const ', csource) csource = _r_cdecl.sub(' ', csource) # # Replace `extern "Python"` with start/end markers csource = _preprocess_extern_python(csource) # # Now there should not be any string literal left; warn if we get one _warn_for_string_literal(csource) # # Replace "[...]" with "[__dotdotdotarray__]" csource = _r_partial_array.sub('[__dotdotdotarray__]', csource) # # Replace "...}" with "__dotdotdotNUM__}". This construction should # occur only at the end of enums; at the end of structs we have "...;}" # and at the end of vararg functions "...);". Also replace "=...[,}]" # with ",__dotdotdotNUM__[,}]": this occurs in the enums too, when # giving an unknown value. matches = list(_r_partial_enum.finditer(csource)) for number, match in enumerate(reversed(matches)): p = match.start() if csource[p] == '=': p2 = csource.find('...', p, match.end()) assert p2 > p csource = '%s,__dotdotdot%d__ %s' % (csource[:p], number, csource[p2+3:]) else: assert csource[p:p+3] == '...' csource = '%s __dotdotdot%d__ %s' % (csource[:p], number, csource[p+3:]) # Replace "int ..." or "unsigned long int..." with "__dotdotdotint__" csource = _r_int_dotdotdot.sub(' __dotdotdotint__ ', csource) # Replace "float ..." or "double..." with "__dotdotdotfloat__" csource = _r_float_dotdotdot.sub(' __dotdotdotfloat__ ', csource) # Replace all remaining "..." with the same name, "__dotdotdot__", # which is declared with a typedef for the purpose of C parsing. return csource.replace('...', ' __dotdotdot__ '), macros def _common_type_names(csource): # Look in the source for what looks like usages of types from the # list of common types. A "usage" is approximated here as the # appearance of the word, minus a "definition" of the type, which # is the last word in a "typedef" statement. Approximative only # but should be fine for all the common types. look_for_words = set(COMMON_TYPES) look_for_words.add(';') look_for_words.add(',') look_for_words.add('(') look_for_words.add(')') look_for_words.add('typedef') words_used = set() is_typedef = False paren = 0 previous_word = '' for word in _r_words.findall(csource): if word in look_for_words: if word == ';': if is_typedef: words_used.discard(previous_word) look_for_words.discard(previous_word) is_typedef = False elif word == 'typedef': is_typedef = True paren = 0 elif word == '(': paren += 1 elif word == ')': paren -= 1 elif word == ',': if is_typedef and paren == 0: words_used.discard(previous_word) look_for_words.discard(previous_word) else: # word in COMMON_TYPES words_used.add(word) previous_word = word return words_used class Parser(object): def __init__(self): self._declarations = {} self._included_declarations = set() self._anonymous_counter = 0 self._structnode2type = weakref.WeakKeyDictionary() self._options = {} self._int_constants = {} self._recomplete = [] self._uses_new_feature = None def _parse(self, csource): csource, macros = _preprocess(csource) # XXX: for more efficiency we would need to poke into the # internals of CParser... the following registers the # typedefs, because their presence or absence influences the # parsing itself (but what they are typedef'ed to plays no role) ctn = _common_type_names(csource) typenames = [] for name in sorted(self._declarations): if name.startswith('typedef '): name = name[8:] typenames.append(name) ctn.discard(name) typenames += sorted(ctn) # csourcelines = [] csourcelines.append('# 1 ""') for typename in typenames: csourcelines.append('typedef int %s;' % typename) csourcelines.append('typedef int __dotdotdotint__, __dotdotdotfloat__,' ' __dotdotdot__;') # this forces pycparser to consider the following in the file # called from line 1 csourcelines.append('# 1 "%s"' % (CDEF_SOURCE_STRING,)) csourcelines.append(csource) fullcsource = '\n'.join(csourcelines) if lock is not None: lock.acquire() # pycparser is not thread-safe... try: ast = _get_parser().parse(fullcsource) except pycparser.c_parser.ParseError as e: self.convert_pycparser_error(e, csource) finally: if lock is not None: lock.release() # csource will be used to find buggy source text return ast, macros, csource def _convert_pycparser_error(self, e, csource): # xxx look for ":NUM:" at the start of str(e) # and interpret that as a line number. This will not work if # the user gives explicit ``# NUM "FILE"`` directives. line = None msg = str(e) match = re.match(r"%s:(\d+):" % (CDEF_SOURCE_STRING,), msg) if match: linenum = int(match.group(1), 10) csourcelines = csource.splitlines() if 1 <= linenum <= len(csourcelines): line = csourcelines[linenum-1] return line def convert_pycparser_error(self, e, csource): line = self._convert_pycparser_error(e, csource) msg = str(e) if line: msg = 'cannot parse "%s"\n%s' % (line.strip(), msg) else: msg = 'parse error\n%s' % (msg,) raise CDefError(msg) def parse(self, csource, override=False, packed=False, pack=None, dllexport=False): if packed: if packed != True: raise ValueError("'packed' should be False or True; use " "'pack' to give another value") if pack: raise ValueError("cannot give both 'pack' and 'packed'") pack = 1 elif pack: if pack & (pack - 1): raise ValueError("'pack' must be a power of two, not %r" % (pack,)) else: pack = 0 prev_options = self._options try: self._options = {'override': override, 'packed': pack, 'dllexport': dllexport} self._internal_parse(csource) finally: self._options = prev_options def _internal_parse(self, csource): ast, macros, csource = self._parse(csource) # add the macros self._process_macros(macros) # find the first "__dotdotdot__" and use that as a separator # between the repeated typedefs and the real csource iterator = iter(ast.ext) for decl in iterator: if decl.name == '__dotdotdot__': break else: assert 0 current_decl = None # try: self._inside_extern_python = '__cffi_extern_python_stop' for decl in iterator: current_decl = decl if isinstance(decl, pycparser.c_ast.Decl): self._parse_decl(decl) elif isinstance(decl, pycparser.c_ast.Typedef): if not decl.name: raise CDefError("typedef does not declare any name", decl) quals = 0 if (isinstance(decl.type.type, pycparser.c_ast.IdentifierType) and decl.type.type.names[-1].startswith('__dotdotdot')): realtype = self._get_unknown_type(decl) elif (isinstance(decl.type, pycparser.c_ast.PtrDecl) and isinstance(decl.type.type, pycparser.c_ast.TypeDecl) and isinstance(decl.type.type.type, pycparser.c_ast.IdentifierType) and decl.type.type.type.names[-1].startswith('__dotdotdot')): realtype = self._get_unknown_ptr_type(decl) else: realtype, quals = self._get_type_and_quals( decl.type, name=decl.name, partial_length_ok=True) self._declare('typedef ' + decl.name, realtype, quals=quals) elif decl.__class__.__name__ == 'Pragma': pass # skip pragma, only in pycparser 2.15 else: raise CDefError("unexpected <%s>: this construct is valid " "C but not valid in cdef()" % decl.__class__.__name__, decl) except CDefError as e: if len(e.args) == 1: e.args = e.args + (current_decl,) raise except FFIError as e: msg = self._convert_pycparser_error(e, csource) if msg: e.args = (e.args[0] + "\n *** Err: %s" % msg,) raise def _add_constants(self, key, val): if key in self._int_constants: if self._int_constants[key] == val: return # ignore identical double declarations raise FFIError( "multiple declarations of constant: %s" % (key,)) self._int_constants[key] = val def _add_integer_constant(self, name, int_str): int_str = int_str.lower().rstrip("ul") neg = int_str.startswith('-') if neg: int_str = int_str[1:] # "010" is not valid oct in py3 if (int_str.startswith("0") and int_str != '0' and not int_str.startswith("0x")): int_str = "0o" + int_str[1:] pyvalue = int(int_str, 0) if neg: pyvalue = -pyvalue self._add_constants(name, pyvalue) self._declare('macro ' + name, pyvalue) def _process_macros(self, macros): for key, value in macros.items(): value = value.strip() if _r_int_literal.match(value): self._add_integer_constant(key, value) elif value == '...': self._declare('macro ' + key, value) else: raise CDefError( 'only supports one of the following syntax:\n' ' #define %s ... (literally dot-dot-dot)\n' ' #define %s NUMBER (with NUMBER an integer' ' constant, decimal/hex/octal)\n' 'got:\n' ' #define %s %s' % (key, key, key, value)) def _declare_function(self, tp, quals, decl): tp = self._get_type_pointer(tp, quals) if self._options.get('dllexport'): tag = 'dllexport_python ' elif self._inside_extern_python == '__cffi_extern_python_start': tag = 'extern_python ' elif self._inside_extern_python == '__cffi_extern_python_plus_c_start': tag = 'extern_python_plus_c ' else: tag = 'function ' self._declare(tag + decl.name, tp) def _parse_decl(self, decl): node = decl.type if isinstance(node, pycparser.c_ast.FuncDecl): tp, quals = self._get_type_and_quals(node, name=decl.name) assert isinstance(tp, model.RawFunctionType) self._declare_function(tp, quals, decl) else: if isinstance(node, pycparser.c_ast.Struct): self._get_struct_union_enum_type('struct', node) elif isinstance(node, pycparser.c_ast.Union): self._get_struct_union_enum_type('union', node) elif isinstance(node, pycparser.c_ast.Enum): self._get_struct_union_enum_type('enum', node) elif not decl.name: raise CDefError("construct does not declare any variable", decl) # if decl.name: tp, quals = self._get_type_and_quals(node, partial_length_ok=True) if tp.is_raw_function: self._declare_function(tp, quals, decl) elif (tp.is_integer_type() and hasattr(decl, 'init') and hasattr(decl.init, 'value') and _r_int_literal.match(decl.init.value)): self._add_integer_constant(decl.name, decl.init.value) elif (tp.is_integer_type() and isinstance(decl.init, pycparser.c_ast.UnaryOp) and decl.init.op == '-' and hasattr(decl.init.expr, 'value') and _r_int_literal.match(decl.init.expr.value)): self._add_integer_constant(decl.name, '-' + decl.init.expr.value) elif (tp is model.void_type and decl.name.startswith('__cffi_extern_python_')): # hack: `extern "Python"` in the C source is replaced # with "void __cffi_extern_python_start;" and # "void __cffi_extern_python_stop;" self._inside_extern_python = decl.name else: if self._inside_extern_python !='__cffi_extern_python_stop': raise CDefError( "cannot declare constants or " "variables with 'extern \"Python\"'") if (quals & model.Q_CONST) and not tp.is_array_type: self._declare('constant ' + decl.name, tp, quals=quals) else: _warn_for_non_extern_non_static_global_variable(decl) self._declare('variable ' + decl.name, tp, quals=quals) def parse_type(self, cdecl): return self.parse_type_and_quals(cdecl)[0] def parse_type_and_quals(self, cdecl): ast, macros = self._parse('void __dummy(\n%s\n);' % cdecl)[:2] assert not macros exprnode = ast.ext[-1].type.args.params[0] if isinstance(exprnode, pycparser.c_ast.ID): raise CDefError("unknown identifier '%s'" % (exprnode.name,)) return self._get_type_and_quals(exprnode.type) def _declare(self, name, obj, included=False, quals=0): if name in self._declarations: prevobj, prevquals = self._declarations[name] if prevobj is obj and prevquals == quals: return if not self._options.get('override'): raise FFIError( "multiple declarations of %s (for interactive usage, " "try cdef(xx, override=True))" % (name,)) assert '__dotdotdot__' not in name.split() self._declarations[name] = (obj, quals) if included: self._included_declarations.add(obj) def _extract_quals(self, type): quals = 0 if isinstance(type, (pycparser.c_ast.TypeDecl, pycparser.c_ast.PtrDecl)): if 'const' in type.quals: quals |= model.Q_CONST if 'volatile' in type.quals: quals |= model.Q_VOLATILE if 'restrict' in type.quals: quals |= model.Q_RESTRICT return quals def _get_type_pointer(self, type, quals, declname=None): if isinstance(type, model.RawFunctionType): return type.as_function_pointer() if (isinstance(type, model.StructOrUnionOrEnum) and type.name.startswith('$') and type.name[1:].isdigit() and type.forcename is None and declname is not None): return model.NamedPointerType(type, declname, quals) return model.PointerType(type, quals) def _get_type_and_quals(self, typenode, name=None, partial_length_ok=False): # first, dereference typedefs, if we have it already parsed, we're good if (isinstance(typenode, pycparser.c_ast.TypeDecl) and isinstance(typenode.type, pycparser.c_ast.IdentifierType) and len(typenode.type.names) == 1 and ('typedef ' + typenode.type.names[0]) in self._declarations): tp, quals = self._declarations['typedef ' + typenode.type.names[0]] quals |= self._extract_quals(typenode) return tp, quals # if isinstance(typenode, pycparser.c_ast.ArrayDecl): # array type if typenode.dim is None: length = None else: length = self._parse_constant( typenode.dim, partial_length_ok=partial_length_ok) tp, quals = self._get_type_and_quals(typenode.type, partial_length_ok=partial_length_ok) return model.ArrayType(tp, length), quals # if isinstance(typenode, pycparser.c_ast.PtrDecl): # pointer type itemtype, itemquals = self._get_type_and_quals(typenode.type) tp = self._get_type_pointer(itemtype, itemquals, declname=name) quals = self._extract_quals(typenode) return tp, quals # if isinstance(typenode, pycparser.c_ast.TypeDecl): quals = self._extract_quals(typenode) type = typenode.type if isinstance(type, pycparser.c_ast.IdentifierType): # assume a primitive type. get it from .names, but reduce # synonyms to a single chosen combination names = list(type.names) if names != ['signed', 'char']: # keep this unmodified prefixes = {} while names: name = names[0] if name in ('short', 'long', 'signed', 'unsigned'): prefixes[name] = prefixes.get(name, 0) + 1 del names[0] else: break # ignore the 'signed' prefix below, and reorder the others newnames = [] for prefix in ('unsigned', 'short', 'long'): for i in range(prefixes.get(prefix, 0)): newnames.append(prefix) if not names: names = ['int'] # implicitly if names == ['int']: # but kill it if 'short' or 'long' if 'short' in prefixes or 'long' in prefixes: names = [] names = newnames + names ident = ' '.join(names) if ident == 'void': return model.void_type, quals if ident == '__dotdotdot__': raise FFIError(':%d: bad usage of "..."' % typenode.coord.line) tp0, quals0 = resolve_common_type(self, ident) return tp0, (quals | quals0) # if isinstance(type, pycparser.c_ast.Struct): # 'struct foobar' tp = self._get_struct_union_enum_type('struct', type, name) return tp, quals # if isinstance(type, pycparser.c_ast.Union): # 'union foobar' tp = self._get_struct_union_enum_type('union', type, name) return tp, quals # if isinstance(type, pycparser.c_ast.Enum): # 'enum foobar' tp = self._get_struct_union_enum_type('enum', type, name) return tp, quals # if isinstance(typenode, pycparser.c_ast.FuncDecl): # a function type return self._parse_function_type(typenode, name), 0 # # nested anonymous structs or unions end up here if isinstance(typenode, pycparser.c_ast.Struct): return self._get_struct_union_enum_type('struct', typenode, name, nested=True), 0 if isinstance(typenode, pycparser.c_ast.Union): return self._get_struct_union_enum_type('union', typenode, name, nested=True), 0 # raise FFIError(":%d: bad or unsupported type declaration" % typenode.coord.line) def _parse_function_type(self, typenode, funcname=None): params = list(getattr(typenode.args, 'params', [])) for i, arg in enumerate(params): if not hasattr(arg, 'type'): raise CDefError("%s arg %d: unknown type '%s'" " (if you meant to use the old C syntax of giving" " untyped arguments, it is not supported)" % (funcname or 'in expression', i + 1, getattr(arg, 'name', '?'))) ellipsis = ( len(params) > 0 and isinstance(params[-1].type, pycparser.c_ast.TypeDecl) and isinstance(params[-1].type.type, pycparser.c_ast.IdentifierType) and params[-1].type.type.names == ['__dotdotdot__']) if ellipsis: params.pop() if not params: raise CDefError( "%s: a function with only '(...)' as argument" " is not correct C" % (funcname or 'in expression')) args = [self._as_func_arg(*self._get_type_and_quals(argdeclnode.type)) for argdeclnode in params] if not ellipsis and args == [model.void_type]: args = [] result, quals = self._get_type_and_quals(typenode.type) # the 'quals' on the result type are ignored. HACK: we absure them # to detect __stdcall functions: we textually replace "__stdcall" # with "volatile volatile const" above. abi = None if hasattr(typenode.type, 'quals'): # else, probable syntax error anyway if typenode.type.quals[-3:] == ['volatile', 'volatile', 'const']: abi = '__stdcall' return model.RawFunctionType(tuple(args), result, ellipsis, abi) def _as_func_arg(self, type, quals): if isinstance(type, model.ArrayType): return model.PointerType(type.item, quals) elif isinstance(type, model.RawFunctionType): return type.as_function_pointer() else: return type def _get_struct_union_enum_type(self, kind, type, name=None, nested=False): # First, a level of caching on the exact 'type' node of the AST. # This is obscure, but needed because pycparser "unrolls" declarations # such as "typedef struct { } foo_t, *foo_p" and we end up with # an AST that is not a tree, but a DAG, with the "type" node of the # two branches foo_t and foo_p of the trees being the same node. # It's a bit silly but detecting "DAG-ness" in the AST tree seems # to be the only way to distinguish this case from two independent # structs. See test_struct_with_two_usages. try: return self._structnode2type[type] except KeyError: pass # # Note that this must handle parsing "struct foo" any number of # times and always return the same StructType object. Additionally, # one of these times (not necessarily the first), the fields of # the struct can be specified with "struct foo { ...fields... }". # If no name is given, then we have to create a new anonymous struct # with no caching; in this case, the fields are either specified # right now or never. # force_name = name name = type.name # # get the type or create it if needed if name is None: # 'force_name' is used to guess a more readable name for # anonymous structs, for the common case "typedef struct { } foo". if force_name is not None: explicit_name = '$%s' % force_name else: self._anonymous_counter += 1 explicit_name = '$%d' % self._anonymous_counter tp = None else: explicit_name = name key = '%s %s' % (kind, name) tp, _ = self._declarations.get(key, (None, None)) # if tp is None: if kind == 'struct': tp = model.StructType(explicit_name, None, None, None) elif kind == 'union': tp = model.UnionType(explicit_name, None, None, None) elif kind == 'enum': if explicit_name == '__dotdotdot__': raise CDefError("Enums cannot be declared with ...") tp = self._build_enum_type(explicit_name, type.values) else: raise AssertionError("kind = %r" % (kind,)) if name is not None: self._declare(key, tp) else: if kind == 'enum' and type.values is not None: raise NotImplementedError( "enum %s: the '{}' declaration should appear on the first " "time the enum is mentioned, not later" % explicit_name) if not tp.forcename: tp.force_the_name(force_name) if tp.forcename and '$' in tp.name: self._declare('anonymous %s' % tp.forcename, tp) # self._structnode2type[type] = tp # # enums: done here if kind == 'enum': return tp # # is there a 'type.decls'? If yes, then this is the place in the # C sources that declare the fields. If no, then just return the # existing type, possibly still incomplete. if type.decls is None: return tp # if tp.fldnames is not None: raise CDefError("duplicate declaration of struct %s" % name) fldnames = [] fldtypes = [] fldbitsize = [] fldquals = [] for decl in type.decls: if (isinstance(decl.type, pycparser.c_ast.IdentifierType) and ''.join(decl.type.names) == '__dotdotdot__'): # XXX pycparser is inconsistent: 'names' should be a list # of strings, but is sometimes just one string. Use # str.join() as a way to cope with both. self._make_partial(tp, nested) continue if decl.bitsize is None: bitsize = -1 else: bitsize = self._parse_constant(decl.bitsize) self._partial_length = False type, fqual = self._get_type_and_quals(decl.type, partial_length_ok=True) if self._partial_length: self._make_partial(tp, nested) if isinstance(type, model.StructType) and type.partial: self._make_partial(tp, nested) fldnames.append(decl.name or '') fldtypes.append(type) fldbitsize.append(bitsize) fldquals.append(fqual) tp.fldnames = tuple(fldnames) tp.fldtypes = tuple(fldtypes) tp.fldbitsize = tuple(fldbitsize) tp.fldquals = tuple(fldquals) if fldbitsize != [-1] * len(fldbitsize): if isinstance(tp, model.StructType) and tp.partial: raise NotImplementedError("%s: using both bitfields and '...;'" % (tp,)) tp.packed = self._options.get('packed') if tp.completed: # must be re-completed: it is not opaque any more tp.completed = 0 self._recomplete.append(tp) return tp def _make_partial(self, tp, nested): if not isinstance(tp, model.StructOrUnion): raise CDefError("%s cannot be partial" % (tp,)) if not tp.has_c_name() and not nested: raise NotImplementedError("%s is partial but has no C name" %(tp,)) tp.partial = True def _parse_constant(self, exprnode, partial_length_ok=False): # for now, limited to expressions that are an immediate number # or positive/negative number if isinstance(exprnode, pycparser.c_ast.Constant): s = exprnode.value if '0' <= s[0] <= '9': s = s.rstrip('uUlL') try: if s.startswith('0'): return int(s, 8) else: return int(s, 10) except ValueError: if len(s) > 1: if s.lower()[0:2] == '0x': return int(s, 16) elif s.lower()[0:2] == '0b': return int(s, 2) raise CDefError("invalid constant %r" % (s,)) elif s[0] == "'" and s[-1] == "'" and ( len(s) == 3 or (len(s) == 4 and s[1] == "\\")): return ord(s[-2]) else: raise CDefError("invalid constant %r" % (s,)) # if (isinstance(exprnode, pycparser.c_ast.UnaryOp) and exprnode.op == '+'): return self._parse_constant(exprnode.expr) # if (isinstance(exprnode, pycparser.c_ast.UnaryOp) and exprnode.op == '-'): return -self._parse_constant(exprnode.expr) # load previously defined int constant if (isinstance(exprnode, pycparser.c_ast.ID) and exprnode.name in self._int_constants): return self._int_constants[exprnode.name] # if (isinstance(exprnode, pycparser.c_ast.ID) and exprnode.name == '__dotdotdotarray__'): if partial_length_ok: self._partial_length = True return '...' raise FFIError(":%d: unsupported '[...]' here, cannot derive " "the actual array length in this context" % exprnode.coord.line) # if isinstance(exprnode, pycparser.c_ast.BinaryOp): left = self._parse_constant(exprnode.left) right = self._parse_constant(exprnode.right) if exprnode.op == '+': return left + right elif exprnode.op == '-': return left - right elif exprnode.op == '*': return left * right elif exprnode.op == '/': return self._c_div(left, right) elif exprnode.op == '%': return left - self._c_div(left, right) * right elif exprnode.op == '<<': return left << right elif exprnode.op == '>>': return left >> right elif exprnode.op == '&': return left & right elif exprnode.op == '|': return left | right elif exprnode.op == '^': return left ^ right # raise FFIError(":%d: unsupported expression: expected a " "simple numeric constant" % exprnode.coord.line) def _c_div(self, a, b): result = a // b if ((a < 0) ^ (b < 0)) and (a % b) != 0: result += 1 return result def _build_enum_type(self, explicit_name, decls): if decls is not None: partial = False enumerators = [] enumvalues = [] nextenumvalue = 0 for enum in decls.enumerators: if _r_enum_dotdotdot.match(enum.name): partial = True continue if enum.value is not None: nextenumvalue = self._parse_constant(enum.value) enumerators.append(enum.name) enumvalues.append(nextenumvalue) self._add_constants(enum.name, nextenumvalue) nextenumvalue += 1 enumerators = tuple(enumerators) enumvalues = tuple(enumvalues) tp = model.EnumType(explicit_name, enumerators, enumvalues) tp.partial = partial else: # opaque enum tp = model.EnumType(explicit_name, (), ()) return tp def include(self, other): for name, (tp, quals) in other._declarations.items(): if name.startswith('anonymous $enum_$'): continue # fix for test_anonymous_enum_include kind = name.split(' ', 1)[0] if kind in ('struct', 'union', 'enum', 'anonymous', 'typedef'): self._declare(name, tp, included=True, quals=quals) for k, v in other._int_constants.items(): self._add_constants(k, v) def _get_unknown_type(self, decl): typenames = decl.type.type.names if typenames == ['__dotdotdot__']: return model.unknown_type(decl.name) if typenames == ['__dotdotdotint__']: if self._uses_new_feature is None: self._uses_new_feature = "'typedef int... %s'" % decl.name return model.UnknownIntegerType(decl.name) if typenames == ['__dotdotdotfloat__']: # note: not for 'long double' so far if self._uses_new_feature is None: self._uses_new_feature = "'typedef float... %s'" % decl.name return model.UnknownFloatType(decl.name) raise FFIError(':%d: unsupported usage of "..." in typedef' % decl.coord.line) def _get_unknown_ptr_type(self, decl): if decl.type.type.type.names == ['__dotdotdot__']: return model.unknown_ptr_type(decl.name) raise FFIError(':%d: unsupported usage of "..." in typedef' % decl.coord.line) ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/cffi/error.py ================================================ class FFIError(Exception): __module__ = 'cffi' class CDefError(Exception): __module__ = 'cffi' def __str__(self): try: current_decl = self.args[1] filename = current_decl.coord.file linenum = current_decl.coord.line prefix = '%s:%d: ' % (filename, linenum) except (AttributeError, TypeError, IndexError): prefix = '' return '%s%s' % (prefix, self.args[0]) class VerificationError(Exception): """ An error raised when verification fails """ __module__ = 'cffi' class VerificationMissing(Exception): """ An error raised when incomplete structures are passed into cdef, but no verification has been done """ __module__ = 'cffi' class PkgConfigError(Exception): """ An error raised for missing modules in pkg-config """ __module__ = 'cffi' ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/cffi/ffiplatform.py ================================================ import sys, os from .error import VerificationError LIST_OF_FILE_NAMES = ['sources', 'include_dirs', 'library_dirs', 'extra_objects', 'depends'] def get_extension(srcfilename, modname, sources=(), **kwds): _hack_at_distutils() from distutils.core import Extension allsources = [srcfilename] for src in sources: allsources.append(os.path.normpath(src)) return Extension(name=modname, sources=allsources, **kwds) def compile(tmpdir, ext, compiler_verbose=0, debug=None): """Compile a C extension module using distutils.""" _hack_at_distutils() saved_environ = os.environ.copy() try: outputfilename = _build(tmpdir, ext, compiler_verbose, debug) outputfilename = os.path.abspath(outputfilename) finally: # workaround for a distutils bugs where some env vars can # become longer and longer every time it is used for key, value in saved_environ.items(): if os.environ.get(key) != value: os.environ[key] = value return outputfilename def _build(tmpdir, ext, compiler_verbose=0, debug=None): # XXX compact but horrible :-( from distutils.core import Distribution import distutils.errors, distutils.log # dist = Distribution({'ext_modules': [ext]}) dist.parse_config_files() options = dist.get_option_dict('build_ext') if debug is None: debug = sys.flags.debug options['debug'] = ('ffiplatform', debug) options['force'] = ('ffiplatform', True) options['build_lib'] = ('ffiplatform', tmpdir) options['build_temp'] = ('ffiplatform', tmpdir) # try: old_level = distutils.log.set_threshold(0) or 0 try: distutils.log.set_verbosity(compiler_verbose) dist.run_command('build_ext') cmd_obj = dist.get_command_obj('build_ext') [soname] = cmd_obj.get_outputs() finally: distutils.log.set_threshold(old_level) except (distutils.errors.CompileError, distutils.errors.LinkError) as e: raise VerificationError('%s: %s' % (e.__class__.__name__, e)) # return soname try: from os.path import samefile except ImportError: def samefile(f1, f2): return os.path.abspath(f1) == os.path.abspath(f2) def maybe_relative_path(path): if not os.path.isabs(path): return path # already relative dir = path names = [] while True: prevdir = dir dir, name = os.path.split(prevdir) if dir == prevdir or not dir: return path # failed to make it relative names.append(name) try: if samefile(dir, os.curdir): names.reverse() return os.path.join(*names) except OSError: pass # ____________________________________________________________ try: int_or_long = (int, long) import cStringIO except NameError: int_or_long = int # Python 3 import io as cStringIO def _flatten(x, f): if isinstance(x, str): f.write('%ds%s' % (len(x), x)) elif isinstance(x, dict): keys = sorted(x.keys()) f.write('%dd' % len(keys)) for key in keys: _flatten(key, f) _flatten(x[key], f) elif isinstance(x, (list, tuple)): f.write('%dl' % len(x)) for value in x: _flatten(value, f) elif isinstance(x, int_or_long): f.write('%di' % (x,)) else: raise TypeError( "the keywords to verify() contains unsupported object %r" % (x,)) def flatten(x): f = cStringIO.StringIO() _flatten(x, f) return f.getvalue() def _hack_at_distutils(): # Windows-only workaround for some configurations: see # https://bugs.python.org/issue23246 (Python 2.7 with # a specific MS compiler suite download) if sys.platform == "win32": try: import setuptools # for side-effects, patches distutils except ImportError: pass ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/cffi/lock.py ================================================ import sys if sys.version_info < (3,): try: from thread import allocate_lock except ImportError: from dummy_thread import allocate_lock else: try: from _thread import allocate_lock except ImportError: from _dummy_thread import allocate_lock ##import sys ##l1 = allocate_lock ##class allocate_lock(object): ## def __init__(self): ## self._real = l1() ## def __enter__(self): ## for i in range(4, 0, -1): ## print sys._getframe(i).f_code ## print ## return self._real.__enter__() ## def __exit__(self, *args): ## return self._real.__exit__(*args) ## def acquire(self, f): ## assert f is False ## return self._real.acquire(f) ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/cffi/model.py ================================================ import types import weakref from .lock import allocate_lock from .error import CDefError, VerificationError, VerificationMissing # type qualifiers Q_CONST = 0x01 Q_RESTRICT = 0x02 Q_VOLATILE = 0x04 def qualify(quals, replace_with): if quals & Q_CONST: replace_with = ' const ' + replace_with.lstrip() if quals & Q_VOLATILE: replace_with = ' volatile ' + replace_with.lstrip() if quals & Q_RESTRICT: # It seems that __restrict is supported by gcc and msvc. # If you hit some different compiler, add a #define in # _cffi_include.h for it (and in its copies, documented there) replace_with = ' __restrict ' + replace_with.lstrip() return replace_with class BaseTypeByIdentity(object): is_array_type = False is_raw_function = False def get_c_name(self, replace_with='', context='a C file', quals=0): result = self.c_name_with_marker assert result.count('&') == 1 # some logic duplication with ffi.getctype()... :-( replace_with = replace_with.strip() if replace_with: if replace_with.startswith('*') and '&[' in result: replace_with = '(%s)' % replace_with elif not replace_with[0] in '[(': replace_with = ' ' + replace_with replace_with = qualify(quals, replace_with) result = result.replace('&', replace_with) if '$' in result: raise VerificationError( "cannot generate '%s' in %s: unknown type name" % (self._get_c_name(), context)) return result def _get_c_name(self): return self.c_name_with_marker.replace('&', '') def has_c_name(self): return '$' not in self._get_c_name() def is_integer_type(self): return False def get_cached_btype(self, ffi, finishlist, can_delay=False): try: BType = ffi._cached_btypes[self] except KeyError: BType = self.build_backend_type(ffi, finishlist) BType2 = ffi._cached_btypes.setdefault(self, BType) assert BType2 is BType return BType def __repr__(self): return '<%s>' % (self._get_c_name(),) def _get_items(self): return [(name, getattr(self, name)) for name in self._attrs_] class BaseType(BaseTypeByIdentity): def __eq__(self, other): return (self.__class__ == other.__class__ and self._get_items() == other._get_items()) def __ne__(self, other): return not self == other def __hash__(self): return hash((self.__class__, tuple(self._get_items()))) class VoidType(BaseType): _attrs_ = () def __init__(self): self.c_name_with_marker = 'void&' def build_backend_type(self, ffi, finishlist): return global_cache(self, ffi, 'new_void_type') void_type = VoidType() class BasePrimitiveType(BaseType): def is_complex_type(self): return False class PrimitiveType(BasePrimitiveType): _attrs_ = ('name',) ALL_PRIMITIVE_TYPES = { 'char': 'c', 'short': 'i', 'int': 'i', 'long': 'i', 'long long': 'i', 'signed char': 'i', 'unsigned char': 'i', 'unsigned short': 'i', 'unsigned int': 'i', 'unsigned long': 'i', 'unsigned long long': 'i', 'float': 'f', 'double': 'f', 'long double': 'f', 'float _Complex': 'j', 'double _Complex': 'j', '_Bool': 'i', # the following types are not primitive in the C sense 'wchar_t': 'c', 'char16_t': 'c', 'char32_t': 'c', 'int8_t': 'i', 'uint8_t': 'i', 'int16_t': 'i', 'uint16_t': 'i', 'int32_t': 'i', 'uint32_t': 'i', 'int64_t': 'i', 'uint64_t': 'i', 'int_least8_t': 'i', 'uint_least8_t': 'i', 'int_least16_t': 'i', 'uint_least16_t': 'i', 'int_least32_t': 'i', 'uint_least32_t': 'i', 'int_least64_t': 'i', 'uint_least64_t': 'i', 'int_fast8_t': 'i', 'uint_fast8_t': 'i', 'int_fast16_t': 'i', 'uint_fast16_t': 'i', 'int_fast32_t': 'i', 'uint_fast32_t': 'i', 'int_fast64_t': 'i', 'uint_fast64_t': 'i', 'intptr_t': 'i', 'uintptr_t': 'i', 'intmax_t': 'i', 'uintmax_t': 'i', 'ptrdiff_t': 'i', 'size_t': 'i', 'ssize_t': 'i', } def __init__(self, name): assert name in self.ALL_PRIMITIVE_TYPES self.name = name self.c_name_with_marker = name + '&' def is_char_type(self): return self.ALL_PRIMITIVE_TYPES[self.name] == 'c' def is_integer_type(self): return self.ALL_PRIMITIVE_TYPES[self.name] == 'i' def is_float_type(self): return self.ALL_PRIMITIVE_TYPES[self.name] == 'f' def is_complex_type(self): return self.ALL_PRIMITIVE_TYPES[self.name] == 'j' def build_backend_type(self, ffi, finishlist): return global_cache(self, ffi, 'new_primitive_type', self.name) class UnknownIntegerType(BasePrimitiveType): _attrs_ = ('name',) def __init__(self, name): self.name = name self.c_name_with_marker = name + '&' def is_integer_type(self): return True def build_backend_type(self, ffi, finishlist): raise NotImplementedError("integer type '%s' can only be used after " "compilation" % self.name) class UnknownFloatType(BasePrimitiveType): _attrs_ = ('name', ) def __init__(self, name): self.name = name self.c_name_with_marker = name + '&' def build_backend_type(self, ffi, finishlist): raise NotImplementedError("float type '%s' can only be used after " "compilation" % self.name) class BaseFunctionType(BaseType): _attrs_ = ('args', 'result', 'ellipsis', 'abi') def __init__(self, args, result, ellipsis, abi=None): self.args = args self.result = result self.ellipsis = ellipsis self.abi = abi # reprargs = [arg._get_c_name() for arg in self.args] if self.ellipsis: reprargs.append('...') reprargs = reprargs or ['void'] replace_with = self._base_pattern % (', '.join(reprargs),) if abi is not None: replace_with = replace_with[:1] + abi + ' ' + replace_with[1:] self.c_name_with_marker = ( self.result.c_name_with_marker.replace('&', replace_with)) class RawFunctionType(BaseFunctionType): # Corresponds to a C type like 'int(int)', which is the C type of # a function, but not a pointer-to-function. The backend has no # notion of such a type; it's used temporarily by parsing. _base_pattern = '(&)(%s)' is_raw_function = True def build_backend_type(self, ffi, finishlist): raise CDefError("cannot render the type %r: it is a function " "type, not a pointer-to-function type" % (self,)) def as_function_pointer(self): return FunctionPtrType(self.args, self.result, self.ellipsis, self.abi) class FunctionPtrType(BaseFunctionType): _base_pattern = '(*&)(%s)' def build_backend_type(self, ffi, finishlist): result = self.result.get_cached_btype(ffi, finishlist) args = [] for tp in self.args: args.append(tp.get_cached_btype(ffi, finishlist)) abi_args = () if self.abi == "__stdcall": if not self.ellipsis: # __stdcall ignored for variadic funcs try: abi_args = (ffi._backend.FFI_STDCALL,) except AttributeError: pass return global_cache(self, ffi, 'new_function_type', tuple(args), result, self.ellipsis, *abi_args) def as_raw_function(self): return RawFunctionType(self.args, self.result, self.ellipsis, self.abi) class PointerType(BaseType): _attrs_ = ('totype', 'quals') def __init__(self, totype, quals=0): self.totype = totype self.quals = quals extra = qualify(quals, " *&") if totype.is_array_type: extra = "(%s)" % (extra.lstrip(),) self.c_name_with_marker = totype.c_name_with_marker.replace('&', extra) def build_backend_type(self, ffi, finishlist): BItem = self.totype.get_cached_btype(ffi, finishlist, can_delay=True) return global_cache(self, ffi, 'new_pointer_type', BItem) voidp_type = PointerType(void_type) def ConstPointerType(totype): return PointerType(totype, Q_CONST) const_voidp_type = ConstPointerType(void_type) class NamedPointerType(PointerType): _attrs_ = ('totype', 'name') def __init__(self, totype, name, quals=0): PointerType.__init__(self, totype, quals) self.name = name self.c_name_with_marker = name + '&' class ArrayType(BaseType): _attrs_ = ('item', 'length') is_array_type = True def __init__(self, item, length): self.item = item self.length = length # if length is None: brackets = '&[]' elif length == '...': brackets = '&[/*...*/]' else: brackets = '&[%s]' % length self.c_name_with_marker = ( self.item.c_name_with_marker.replace('&', brackets)) def resolve_length(self, newlength): return ArrayType(self.item, newlength) def build_backend_type(self, ffi, finishlist): if self.length == '...': raise CDefError("cannot render the type %r: unknown length" % (self,)) self.item.get_cached_btype(ffi, finishlist) # force the item BType BPtrItem = PointerType(self.item).get_cached_btype(ffi, finishlist) return global_cache(self, ffi, 'new_array_type', BPtrItem, self.length) char_array_type = ArrayType(PrimitiveType('char'), None) class StructOrUnionOrEnum(BaseTypeByIdentity): _attrs_ = ('name',) forcename = None def build_c_name_with_marker(self): name = self.forcename or '%s %s' % (self.kind, self.name) self.c_name_with_marker = name + '&' def force_the_name(self, forcename): self.forcename = forcename self.build_c_name_with_marker() def get_official_name(self): assert self.c_name_with_marker.endswith('&') return self.c_name_with_marker[:-1] class StructOrUnion(StructOrUnionOrEnum): fixedlayout = None completed = 0 partial = False packed = 0 def __init__(self, name, fldnames, fldtypes, fldbitsize, fldquals=None): self.name = name self.fldnames = fldnames self.fldtypes = fldtypes self.fldbitsize = fldbitsize self.fldquals = fldquals self.build_c_name_with_marker() def anonymous_struct_fields(self): if self.fldtypes is not None: for name, type in zip(self.fldnames, self.fldtypes): if name == '' and isinstance(type, StructOrUnion): yield type def enumfields(self, expand_anonymous_struct_union=True): fldquals = self.fldquals if fldquals is None: fldquals = (0,) * len(self.fldnames) for name, type, bitsize, quals in zip(self.fldnames, self.fldtypes, self.fldbitsize, fldquals): if (name == '' and isinstance(type, StructOrUnion) and expand_anonymous_struct_union): # nested anonymous struct/union for result in type.enumfields(): yield result else: yield (name, type, bitsize, quals) def force_flatten(self): # force the struct or union to have a declaration that lists # directly all fields returned by enumfields(), flattening # nested anonymous structs/unions. names = [] types = [] bitsizes = [] fldquals = [] for name, type, bitsize, quals in self.enumfields(): names.append(name) types.append(type) bitsizes.append(bitsize) fldquals.append(quals) self.fldnames = tuple(names) self.fldtypes = tuple(types) self.fldbitsize = tuple(bitsizes) self.fldquals = tuple(fldquals) def get_cached_btype(self, ffi, finishlist, can_delay=False): BType = StructOrUnionOrEnum.get_cached_btype(self, ffi, finishlist, can_delay) if not can_delay: self.finish_backend_type(ffi, finishlist) return BType def finish_backend_type(self, ffi, finishlist): if self.completed: if self.completed != 2: raise NotImplementedError("recursive structure declaration " "for '%s'" % (self.name,)) return BType = ffi._cached_btypes[self] # self.completed = 1 # if self.fldtypes is None: pass # not completing it: it's an opaque struct # elif self.fixedlayout is None: fldtypes = [tp.get_cached_btype(ffi, finishlist) for tp in self.fldtypes] lst = list(zip(self.fldnames, fldtypes, self.fldbitsize)) extra_flags = () if self.packed: if self.packed == 1: extra_flags = (8,) # SF_PACKED else: extra_flags = (0, self.packed) ffi._backend.complete_struct_or_union(BType, lst, self, -1, -1, *extra_flags) # else: fldtypes = [] fieldofs, fieldsize, totalsize, totalalignment = self.fixedlayout for i in range(len(self.fldnames)): fsize = fieldsize[i] ftype = self.fldtypes[i] # if isinstance(ftype, ArrayType) and ftype.length == '...': # fix the length to match the total size BItemType = ftype.item.get_cached_btype(ffi, finishlist) nlen, nrest = divmod(fsize, ffi.sizeof(BItemType)) if nrest != 0: self._verification_error( "field '%s.%s' has a bogus size?" % ( self.name, self.fldnames[i] or '{}')) ftype = ftype.resolve_length(nlen) self.fldtypes = (self.fldtypes[:i] + (ftype,) + self.fldtypes[i+1:]) # BFieldType = ftype.get_cached_btype(ffi, finishlist) if isinstance(ftype, ArrayType) and ftype.length is None: assert fsize == 0 else: bitemsize = ffi.sizeof(BFieldType) if bitemsize != fsize: self._verification_error( "field '%s.%s' is declared as %d bytes, but is " "really %d bytes" % (self.name, self.fldnames[i] or '{}', bitemsize, fsize)) fldtypes.append(BFieldType) # lst = list(zip(self.fldnames, fldtypes, self.fldbitsize, fieldofs)) ffi._backend.complete_struct_or_union(BType, lst, self, totalsize, totalalignment) self.completed = 2 def _verification_error(self, msg): raise VerificationError(msg) def check_not_partial(self): if self.partial and self.fixedlayout is None: raise VerificationMissing(self._get_c_name()) def build_backend_type(self, ffi, finishlist): self.check_not_partial() finishlist.append(self) # return global_cache(self, ffi, 'new_%s_type' % self.kind, self.get_official_name(), key=self) class StructType(StructOrUnion): kind = 'struct' class UnionType(StructOrUnion): kind = 'union' class EnumType(StructOrUnionOrEnum): kind = 'enum' partial = False partial_resolved = False def __init__(self, name, enumerators, enumvalues, baseinttype=None): self.name = name self.enumerators = enumerators self.enumvalues = enumvalues self.baseinttype = baseinttype self.build_c_name_with_marker() def force_the_name(self, forcename): StructOrUnionOrEnum.force_the_name(self, forcename) if self.forcename is None: name = self.get_official_name() self.forcename = '$' + name.replace(' ', '_') def check_not_partial(self): if self.partial and not self.partial_resolved: raise VerificationMissing(self._get_c_name()) def build_backend_type(self, ffi, finishlist): self.check_not_partial() base_btype = self.build_baseinttype(ffi, finishlist) return global_cache(self, ffi, 'new_enum_type', self.get_official_name(), self.enumerators, self.enumvalues, base_btype, key=self) def build_baseinttype(self, ffi, finishlist): if self.baseinttype is not None: return self.baseinttype.get_cached_btype(ffi, finishlist) # if self.enumvalues: smallest_value = min(self.enumvalues) largest_value = max(self.enumvalues) else: import warnings try: # XXX! The goal is to ensure that the warnings.warn() # will not suppress the warning. We want to get it # several times if we reach this point several times. __warningregistry__.clear() except NameError: pass warnings.warn("%r has no values explicitly defined; " "guessing that it is equivalent to 'unsigned int'" % self._get_c_name()) smallest_value = largest_value = 0 if smallest_value < 0: # needs a signed type sign = 1 candidate1 = PrimitiveType("int") candidate2 = PrimitiveType("long") else: sign = 0 candidate1 = PrimitiveType("unsigned int") candidate2 = PrimitiveType("unsigned long") btype1 = candidate1.get_cached_btype(ffi, finishlist) btype2 = candidate2.get_cached_btype(ffi, finishlist) size1 = ffi.sizeof(btype1) size2 = ffi.sizeof(btype2) if (smallest_value >= ((-1) << (8*size1-1)) and largest_value < (1 << (8*size1-sign))): return btype1 if (smallest_value >= ((-1) << (8*size2-1)) and largest_value < (1 << (8*size2-sign))): return btype2 raise CDefError("%s values don't all fit into either 'long' " "or 'unsigned long'" % self._get_c_name()) def unknown_type(name, structname=None): if structname is None: structname = '$%s' % name tp = StructType(structname, None, None, None) tp.force_the_name(name) tp.origin = "unknown_type" return tp def unknown_ptr_type(name, structname=None): if structname is None: structname = '$$%s' % name tp = StructType(structname, None, None, None) return NamedPointerType(tp, name) global_lock = allocate_lock() _typecache_cffi_backend = weakref.WeakValueDictionary() def get_typecache(backend): # returns _typecache_cffi_backend if backend is the _cffi_backend # module, or type(backend).__typecache if backend is an instance of # CTypesBackend (or some FakeBackend class during tests) if isinstance(backend, types.ModuleType): return _typecache_cffi_backend with global_lock: if not hasattr(type(backend), '__typecache'): type(backend).__typecache = weakref.WeakValueDictionary() return type(backend).__typecache def global_cache(srctype, ffi, funcname, *args, **kwds): key = kwds.pop('key', (funcname, args)) assert not kwds try: return ffi._typecache[key] except KeyError: pass try: res = getattr(ffi._backend, funcname)(*args) except NotImplementedError as e: raise NotImplementedError("%s: %r: %s" % (funcname, srctype, e)) # note that setdefault() on WeakValueDictionary is not atomic # and contains a rare bug (http://bugs.python.org/issue19542); # we have to use a lock and do it ourselves cache = ffi._typecache with global_lock: res1 = cache.get(key) if res1 is None: cache[key] = res return res else: return res1 def pointer_cache(ffi, BType): return global_cache('?', ffi, 'new_pointer_type', BType) def attach_exception_info(e, name): if e.args and type(e.args[0]) is str: e.args = ('%s: %s' % (name, e.args[0]),) + e.args[1:] ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/cffi/parse_c_type.h ================================================ /* This part is from file 'cffi/parse_c_type.h'. It is copied at the beginning of C sources generated by CFFI's ffi.set_source(). */ typedef void *_cffi_opcode_t; #define _CFFI_OP(opcode, arg) (_cffi_opcode_t)(opcode | (((uintptr_t)(arg)) << 8)) #define _CFFI_GETOP(cffi_opcode) ((unsigned char)(uintptr_t)cffi_opcode) #define _CFFI_GETARG(cffi_opcode) (((intptr_t)cffi_opcode) >> 8) #define _CFFI_OP_PRIMITIVE 1 #define _CFFI_OP_POINTER 3 #define _CFFI_OP_ARRAY 5 #define _CFFI_OP_OPEN_ARRAY 7 #define _CFFI_OP_STRUCT_UNION 9 #define _CFFI_OP_ENUM 11 #define _CFFI_OP_FUNCTION 13 #define _CFFI_OP_FUNCTION_END 15 #define _CFFI_OP_NOOP 17 #define _CFFI_OP_BITFIELD 19 #define _CFFI_OP_TYPENAME 21 #define _CFFI_OP_CPYTHON_BLTN_V 23 // varargs #define _CFFI_OP_CPYTHON_BLTN_N 25 // noargs #define _CFFI_OP_CPYTHON_BLTN_O 27 // O (i.e. a single arg) #define _CFFI_OP_CONSTANT 29 #define _CFFI_OP_CONSTANT_INT 31 #define _CFFI_OP_GLOBAL_VAR 33 #define _CFFI_OP_DLOPEN_FUNC 35 #define _CFFI_OP_DLOPEN_CONST 37 #define _CFFI_OP_GLOBAL_VAR_F 39 #define _CFFI_OP_EXTERN_PYTHON 41 #define _CFFI_PRIM_VOID 0 #define _CFFI_PRIM_BOOL 1 #define _CFFI_PRIM_CHAR 2 #define _CFFI_PRIM_SCHAR 3 #define _CFFI_PRIM_UCHAR 4 #define _CFFI_PRIM_SHORT 5 #define _CFFI_PRIM_USHORT 6 #define _CFFI_PRIM_INT 7 #define _CFFI_PRIM_UINT 8 #define _CFFI_PRIM_LONG 9 #define _CFFI_PRIM_ULONG 10 #define _CFFI_PRIM_LONGLONG 11 #define _CFFI_PRIM_ULONGLONG 12 #define _CFFI_PRIM_FLOAT 13 #define _CFFI_PRIM_DOUBLE 14 #define _CFFI_PRIM_LONGDOUBLE 15 #define _CFFI_PRIM_WCHAR 16 #define _CFFI_PRIM_INT8 17 #define _CFFI_PRIM_UINT8 18 #define _CFFI_PRIM_INT16 19 #define _CFFI_PRIM_UINT16 20 #define _CFFI_PRIM_INT32 21 #define _CFFI_PRIM_UINT32 22 #define _CFFI_PRIM_INT64 23 #define _CFFI_PRIM_UINT64 24 #define _CFFI_PRIM_INTPTR 25 #define _CFFI_PRIM_UINTPTR 26 #define _CFFI_PRIM_PTRDIFF 27 #define _CFFI_PRIM_SIZE 28 #define _CFFI_PRIM_SSIZE 29 #define _CFFI_PRIM_INT_LEAST8 30 #define _CFFI_PRIM_UINT_LEAST8 31 #define _CFFI_PRIM_INT_LEAST16 32 #define _CFFI_PRIM_UINT_LEAST16 33 #define _CFFI_PRIM_INT_LEAST32 34 #define _CFFI_PRIM_UINT_LEAST32 35 #define _CFFI_PRIM_INT_LEAST64 36 #define _CFFI_PRIM_UINT_LEAST64 37 #define _CFFI_PRIM_INT_FAST8 38 #define _CFFI_PRIM_UINT_FAST8 39 #define _CFFI_PRIM_INT_FAST16 40 #define _CFFI_PRIM_UINT_FAST16 41 #define _CFFI_PRIM_INT_FAST32 42 #define _CFFI_PRIM_UINT_FAST32 43 #define _CFFI_PRIM_INT_FAST64 44 #define _CFFI_PRIM_UINT_FAST64 45 #define _CFFI_PRIM_INTMAX 46 #define _CFFI_PRIM_UINTMAX 47 #define _CFFI_PRIM_FLOATCOMPLEX 48 #define _CFFI_PRIM_DOUBLECOMPLEX 49 #define _CFFI_PRIM_CHAR16 50 #define _CFFI_PRIM_CHAR32 51 #define _CFFI__NUM_PRIM 52 #define _CFFI__UNKNOWN_PRIM (-1) #define _CFFI__UNKNOWN_FLOAT_PRIM (-2) #define _CFFI__UNKNOWN_LONG_DOUBLE (-3) #define _CFFI__IO_FILE_STRUCT (-1) struct _cffi_global_s { const char *name; void *address; _cffi_opcode_t type_op; void *size_or_direct_fn; // OP_GLOBAL_VAR: size, or 0 if unknown // OP_CPYTHON_BLTN_*: addr of direct function }; struct _cffi_getconst_s { unsigned long long value; const struct _cffi_type_context_s *ctx; int gindex; }; struct _cffi_struct_union_s { const char *name; int type_index; // -> _cffi_types, on a OP_STRUCT_UNION int flags; // _CFFI_F_* flags below size_t size; int alignment; int first_field_index; // -> _cffi_fields array int num_fields; }; #define _CFFI_F_UNION 0x01 // is a union, not a struct #define _CFFI_F_CHECK_FIELDS 0x02 // complain if fields are not in the // "standard layout" or if some are missing #define _CFFI_F_PACKED 0x04 // for CHECK_FIELDS, assume a packed struct #define _CFFI_F_EXTERNAL 0x08 // in some other ffi.include() #define _CFFI_F_OPAQUE 0x10 // opaque struct _cffi_field_s { const char *name; size_t field_offset; size_t field_size; _cffi_opcode_t field_type_op; }; struct _cffi_enum_s { const char *name; int type_index; // -> _cffi_types, on a OP_ENUM int type_prim; // _CFFI_PRIM_xxx const char *enumerators; // comma-delimited string }; struct _cffi_typename_s { const char *name; int type_index; /* if opaque, points to a possibly artificial OP_STRUCT which is itself opaque */ }; struct _cffi_type_context_s { _cffi_opcode_t *types; const struct _cffi_global_s *globals; const struct _cffi_field_s *fields; const struct _cffi_struct_union_s *struct_unions; const struct _cffi_enum_s *enums; const struct _cffi_typename_s *typenames; int num_globals; int num_struct_unions; int num_enums; int num_typenames; const char *const *includes; int num_types; int flags; /* future extension */ }; struct _cffi_parse_info_s { const struct _cffi_type_context_s *ctx; _cffi_opcode_t *output; unsigned int output_size; size_t error_location; const char *error_message; }; struct _cffi_externpy_s { const char *name; size_t size_of_result; void *reserved1, *reserved2; }; #ifdef _CFFI_INTERNAL static int parse_c_type(struct _cffi_parse_info_s *info, const char *input); static int search_in_globals(const struct _cffi_type_context_s *ctx, const char *search, size_t search_len); static int search_in_struct_unions(const struct _cffi_type_context_s *ctx, const char *search, size_t search_len); #endif ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/cffi/pkgconfig.py ================================================ # pkg-config, https://www.freedesktop.org/wiki/Software/pkg-config/ integration for cffi import sys, os, subprocess from .error import PkgConfigError def merge_flags(cfg1, cfg2): """Merge values from cffi config flags cfg2 to cf1 Example: merge_flags({"libraries": ["one"]}, {"libraries": ["two"]}) {"libraries": ["one", "two"]} """ for key, value in cfg2.items(): if key not in cfg1: cfg1[key] = value else: if not isinstance(cfg1[key], list): raise TypeError("cfg1[%r] should be a list of strings" % (key,)) if not isinstance(value, list): raise TypeError("cfg2[%r] should be a list of strings" % (key,)) cfg1[key].extend(value) return cfg1 def call(libname, flag, encoding=sys.getfilesystemencoding()): """Calls pkg-config and returns the output if found """ a = ["pkg-config", "--print-errors"] a.append(flag) a.append(libname) try: pc = subprocess.Popen(a, stdout=subprocess.PIPE, stderr=subprocess.PIPE) except EnvironmentError as e: raise PkgConfigError("cannot run pkg-config: %s" % (str(e).strip(),)) bout, berr = pc.communicate() if pc.returncode != 0: try: berr = berr.decode(encoding) except Exception: pass raise PkgConfigError(berr.strip()) if sys.version_info >= (3,) and not isinstance(bout, str): # Python 3.x try: bout = bout.decode(encoding) except UnicodeDecodeError: raise PkgConfigError("pkg-config %s %s returned bytes that cannot " "be decoded with encoding %r:\n%r" % (flag, libname, encoding, bout)) if os.altsep != '\\' and '\\' in bout: raise PkgConfigError("pkg-config %s %s returned an unsupported " "backslash-escaped output:\n%r" % (flag, libname, bout)) return bout def flags_from_pkgconfig(libs): r"""Return compiler line flags for FFI.set_source based on pkg-config output Usage ... ffibuilder.set_source("_foo", pkgconfig = ["libfoo", "libbar >= 1.8.3"]) If pkg-config is installed on build machine, then arguments include_dirs, library_dirs, libraries, define_macros, extra_compile_args and extra_link_args are extended with an output of pkg-config for libfoo and libbar. Raises PkgConfigError in case the pkg-config call fails. """ def get_include_dirs(string): return [x[2:] for x in string.split() if x.startswith("-I")] def get_library_dirs(string): return [x[2:] for x in string.split() if x.startswith("-L")] def get_libraries(string): return [x[2:] for x in string.split() if x.startswith("-l")] # convert -Dfoo=bar to list of tuples [("foo", "bar")] expected by distutils def get_macros(string): def _macro(x): x = x[2:] # drop "-D" if '=' in x: return tuple(x.split("=", 1)) # "-Dfoo=bar" => ("foo", "bar") else: return (x, None) # "-Dfoo" => ("foo", None) return [_macro(x) for x in string.split() if x.startswith("-D")] def get_other_cflags(string): return [x for x in string.split() if not x.startswith("-I") and not x.startswith("-D")] def get_other_libs(string): return [x for x in string.split() if not x.startswith("-L") and not x.startswith("-l")] # return kwargs for given libname def kwargs(libname): fse = sys.getfilesystemencoding() all_cflags = call(libname, "--cflags") all_libs = call(libname, "--libs") return { "include_dirs": get_include_dirs(all_cflags), "library_dirs": get_library_dirs(all_libs), "libraries": get_libraries(all_libs), "define_macros": get_macros(all_cflags), "extra_compile_args": get_other_cflags(all_cflags), "extra_link_args": get_other_libs(all_libs), } # merge all arguments together ret = {} for libname in libs: lib_flags = kwargs(libname) merge_flags(ret, lib_flags) return ret ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/cffi/recompiler.py ================================================ import os, sys, io from . import ffiplatform, model from .error import VerificationError from .cffi_opcode import * VERSION_BASE = 0x2601 VERSION_EMBEDDED = 0x2701 VERSION_CHAR16CHAR32 = 0x2801 class GlobalExpr: def __init__(self, name, address, type_op, size=0, check_value=0): self.name = name self.address = address self.type_op = type_op self.size = size self.check_value = check_value def as_c_expr(self): return ' { "%s", (void *)%s, %s, (void *)%s },' % ( self.name, self.address, self.type_op.as_c_expr(), self.size) def as_python_expr(self): return "b'%s%s',%d" % (self.type_op.as_python_bytes(), self.name, self.check_value) class FieldExpr: def __init__(self, name, field_offset, field_size, fbitsize, field_type_op): self.name = name self.field_offset = field_offset self.field_size = field_size self.fbitsize = fbitsize self.field_type_op = field_type_op def as_c_expr(self): spaces = " " * len(self.name) return (' { "%s", %s,\n' % (self.name, self.field_offset) + ' %s %s,\n' % (spaces, self.field_size) + ' %s %s },' % (spaces, self.field_type_op.as_c_expr())) def as_python_expr(self): raise NotImplementedError def as_field_python_expr(self): if self.field_type_op.op == OP_NOOP: size_expr = '' elif self.field_type_op.op == OP_BITFIELD: size_expr = format_four_bytes(self.fbitsize) else: raise NotImplementedError return "b'%s%s%s'" % (self.field_type_op.as_python_bytes(), size_expr, self.name) class StructUnionExpr: def __init__(self, name, type_index, flags, size, alignment, comment, first_field_index, c_fields): self.name = name self.type_index = type_index self.flags = flags self.size = size self.alignment = alignment self.comment = comment self.first_field_index = first_field_index self.c_fields = c_fields def as_c_expr(self): return (' { "%s", %d, %s,' % (self.name, self.type_index, self.flags) + '\n %s, %s, ' % (self.size, self.alignment) + '%d, %d ' % (self.first_field_index, len(self.c_fields)) + ('/* %s */ ' % self.comment if self.comment else '') + '},') def as_python_expr(self): flags = eval(self.flags, G_FLAGS) fields_expr = [c_field.as_field_python_expr() for c_field in self.c_fields] return "(b'%s%s%s',%s)" % ( format_four_bytes(self.type_index), format_four_bytes(flags), self.name, ','.join(fields_expr)) class EnumExpr: def __init__(self, name, type_index, size, signed, allenums): self.name = name self.type_index = type_index self.size = size self.signed = signed self.allenums = allenums def as_c_expr(self): return (' { "%s", %d, _cffi_prim_int(%s, %s),\n' ' "%s" },' % (self.name, self.type_index, self.size, self.signed, self.allenums)) def as_python_expr(self): prim_index = { (1, 0): PRIM_UINT8, (1, 1): PRIM_INT8, (2, 0): PRIM_UINT16, (2, 1): PRIM_INT16, (4, 0): PRIM_UINT32, (4, 1): PRIM_INT32, (8, 0): PRIM_UINT64, (8, 1): PRIM_INT64, }[self.size, self.signed] return "b'%s%s%s\\x00%s'" % (format_four_bytes(self.type_index), format_four_bytes(prim_index), self.name, self.allenums) class TypenameExpr: def __init__(self, name, type_index): self.name = name self.type_index = type_index def as_c_expr(self): return ' { "%s", %d },' % (self.name, self.type_index) def as_python_expr(self): return "b'%s%s'" % (format_four_bytes(self.type_index), self.name) # ____________________________________________________________ class Recompiler: _num_externpy = 0 def __init__(self, ffi, module_name, target_is_python=False): self.ffi = ffi self.module_name = module_name self.target_is_python = target_is_python self._version = VERSION_BASE def needs_version(self, ver): self._version = max(self._version, ver) def collect_type_table(self): self._typesdict = {} self._generate("collecttype") # all_decls = sorted(self._typesdict, key=str) # # prepare all FUNCTION bytecode sequences first self.cffi_types = [] for tp in all_decls: if tp.is_raw_function: assert self._typesdict[tp] is None self._typesdict[tp] = len(self.cffi_types) self.cffi_types.append(tp) # placeholder for tp1 in tp.args: assert isinstance(tp1, (model.VoidType, model.BasePrimitiveType, model.PointerType, model.StructOrUnionOrEnum, model.FunctionPtrType)) if self._typesdict[tp1] is None: self._typesdict[tp1] = len(self.cffi_types) self.cffi_types.append(tp1) # placeholder self.cffi_types.append('END') # placeholder # # prepare all OTHER bytecode sequences for tp in all_decls: if not tp.is_raw_function and self._typesdict[tp] is None: self._typesdict[tp] = len(self.cffi_types) self.cffi_types.append(tp) # placeholder if tp.is_array_type and tp.length is not None: self.cffi_types.append('LEN') # placeholder assert None not in self._typesdict.values() # # collect all structs and unions and enums self._struct_unions = {} self._enums = {} for tp in all_decls: if isinstance(tp, model.StructOrUnion): self._struct_unions[tp] = None elif isinstance(tp, model.EnumType): self._enums[tp] = None for i, tp in enumerate(sorted(self._struct_unions, key=lambda tp: tp.name)): self._struct_unions[tp] = i for i, tp in enumerate(sorted(self._enums, key=lambda tp: tp.name)): self._enums[tp] = i # # emit all bytecode sequences now for tp in all_decls: method = getattr(self, '_emit_bytecode_' + tp.__class__.__name__) method(tp, self._typesdict[tp]) # # consistency check for op in self.cffi_types: assert isinstance(op, CffiOp) self.cffi_types = tuple(self.cffi_types) # don't change any more def _do_collect_type(self, tp): if not isinstance(tp, model.BaseTypeByIdentity): if isinstance(tp, tuple): for x in tp: self._do_collect_type(x) return if tp not in self._typesdict: self._typesdict[tp] = None if isinstance(tp, model.FunctionPtrType): self._do_collect_type(tp.as_raw_function()) elif isinstance(tp, model.StructOrUnion): if tp.fldtypes is not None and ( tp not in self.ffi._parser._included_declarations): for name1, tp1, _, _ in tp.enumfields(): self._do_collect_type(self._field_type(tp, name1, tp1)) else: for _, x in tp._get_items(): self._do_collect_type(x) def _generate(self, step_name): lst = self.ffi._parser._declarations.items() for name, (tp, quals) in sorted(lst): kind, realname = name.split(' ', 1) try: method = getattr(self, '_generate_cpy_%s_%s' % (kind, step_name)) except AttributeError: raise VerificationError( "not implemented in recompile(): %r" % name) try: self._current_quals = quals method(tp, realname) except Exception as e: model.attach_exception_info(e, name) raise # ---------- ALL_STEPS = ["global", "field", "struct_union", "enum", "typename"] def collect_step_tables(self): # collect the declarations for '_cffi_globals', '_cffi_typenames', etc. self._lsts = {} for step_name in self.ALL_STEPS: self._lsts[step_name] = [] self._seen_struct_unions = set() self._generate("ctx") self._add_missing_struct_unions() # for step_name in self.ALL_STEPS: lst = self._lsts[step_name] if step_name != "field": lst.sort(key=lambda entry: entry.name) self._lsts[step_name] = tuple(lst) # don't change any more # # check for a possible internal inconsistency: _cffi_struct_unions # should have been generated with exactly self._struct_unions lst = self._lsts["struct_union"] for tp, i in self._struct_unions.items(): assert i < len(lst) assert lst[i].name == tp.name assert len(lst) == len(self._struct_unions) # same with enums lst = self._lsts["enum"] for tp, i in self._enums.items(): assert i < len(lst) assert lst[i].name == tp.name assert len(lst) == len(self._enums) # ---------- def _prnt(self, what=''): self._f.write(what + '\n') def write_source_to_f(self, f, preamble): if self.target_is_python: assert preamble is None self.write_py_source_to_f(f) else: assert preamble is not None self.write_c_source_to_f(f, preamble) def _rel_readlines(self, filename): g = open(os.path.join(os.path.dirname(__file__), filename), 'r') lines = g.readlines() g.close() return lines def write_c_source_to_f(self, f, preamble): self._f = f prnt = self._prnt if self.ffi._embedding is not None: prnt('#define _CFFI_USE_EMBEDDING') # # first the '#include' (actually done by inlining the file's content) lines = self._rel_readlines('_cffi_include.h') i = lines.index('#include "parse_c_type.h"\n') lines[i:i+1] = self._rel_readlines('parse_c_type.h') prnt(''.join(lines)) # # if we have ffi._embedding != None, we give it here as a macro # and include an extra file base_module_name = self.module_name.split('.')[-1] if self.ffi._embedding is not None: prnt('#define _CFFI_MODULE_NAME "%s"' % (self.module_name,)) prnt('static const char _CFFI_PYTHON_STARTUP_CODE[] = {') self._print_string_literal_in_array(self.ffi._embedding) prnt('0 };') prnt('#ifdef PYPY_VERSION') prnt('# define _CFFI_PYTHON_STARTUP_FUNC _cffi_pypyinit_%s' % ( base_module_name,)) prnt('#elif PY_MAJOR_VERSION >= 3') prnt('# define _CFFI_PYTHON_STARTUP_FUNC PyInit_%s' % ( base_module_name,)) prnt('#else') prnt('# define _CFFI_PYTHON_STARTUP_FUNC init%s' % ( base_module_name,)) prnt('#endif') lines = self._rel_readlines('_embedding.h') i = lines.index('#include "_cffi_errors.h"\n') lines[i:i+1] = self._rel_readlines('_cffi_errors.h') prnt(''.join(lines)) self.needs_version(VERSION_EMBEDDED) # # then paste the C source given by the user, verbatim. prnt('/************************************************************/') prnt() prnt(preamble) prnt() prnt('/************************************************************/') prnt() # # the declaration of '_cffi_types' prnt('static void *_cffi_types[] = {') typeindex2type = dict([(i, tp) for (tp, i) in self._typesdict.items()]) for i, op in enumerate(self.cffi_types): comment = '' if i in typeindex2type: comment = ' // ' + typeindex2type[i]._get_c_name() prnt('/* %2d */ %s,%s' % (i, op.as_c_expr(), comment)) if not self.cffi_types: prnt(' 0') prnt('};') prnt() # # call generate_cpy_xxx_decl(), for every xxx found from # ffi._parser._declarations. This generates all the functions. self._seen_constants = set() self._generate("decl") # # the declaration of '_cffi_globals' and '_cffi_typenames' nums = {} for step_name in self.ALL_STEPS: lst = self._lsts[step_name] nums[step_name] = len(lst) if nums[step_name] > 0: prnt('static const struct _cffi_%s_s _cffi_%ss[] = {' % ( step_name, step_name)) for entry in lst: prnt(entry.as_c_expr()) prnt('};') prnt() # # the declaration of '_cffi_includes' if self.ffi._included_ffis: prnt('static const char * const _cffi_includes[] = {') for ffi_to_include in self.ffi._included_ffis: try: included_module_name, included_source = ( ffi_to_include._assigned_source[:2]) except AttributeError: raise VerificationError( "ffi object %r includes %r, but the latter has not " "been prepared with set_source()" % ( self.ffi, ffi_to_include,)) if included_source is None: raise VerificationError( "not implemented yet: ffi.include() of a Python-based " "ffi inside a C-based ffi") prnt(' "%s",' % (included_module_name,)) prnt(' NULL') prnt('};') prnt() # # the declaration of '_cffi_type_context' prnt('static const struct _cffi_type_context_s _cffi_type_context = {') prnt(' _cffi_types,') for step_name in self.ALL_STEPS: if nums[step_name] > 0: prnt(' _cffi_%ss,' % step_name) else: prnt(' NULL, /* no %ss */' % step_name) for step_name in self.ALL_STEPS: if step_name != "field": prnt(' %d, /* num_%ss */' % (nums[step_name], step_name)) if self.ffi._included_ffis: prnt(' _cffi_includes,') else: prnt(' NULL, /* no includes */') prnt(' %d, /* num_types */' % (len(self.cffi_types),)) flags = 0 if self._num_externpy: flags |= 1 # set to mean that we use extern "Python" prnt(' %d, /* flags */' % flags) prnt('};') prnt() # # the init function prnt('#ifdef __GNUC__') prnt('# pragma GCC visibility push(default) /* for -fvisibility= */') prnt('#endif') prnt() prnt('#ifdef PYPY_VERSION') prnt('PyMODINIT_FUNC') prnt('_cffi_pypyinit_%s(const void *p[])' % (base_module_name,)) prnt('{') if self._num_externpy: prnt(' if (((intptr_t)p[0]) >= 0x0A03) {') prnt(' _cffi_call_python_org = ' '(void(*)(struct _cffi_externpy_s *, char *))p[1];') prnt(' }') prnt(' p[0] = (const void *)0x%x;' % self._version) prnt(' p[1] = &_cffi_type_context;') prnt('#if PY_MAJOR_VERSION >= 3') prnt(' return NULL;') prnt('#endif') prnt('}') # on Windows, distutils insists on putting init_cffi_xyz in # 'export_symbols', so instead of fighting it, just give up and # give it one prnt('# ifdef _MSC_VER') prnt(' PyMODINIT_FUNC') prnt('# if PY_MAJOR_VERSION >= 3') prnt(' PyInit_%s(void) { return NULL; }' % (base_module_name,)) prnt('# else') prnt(' init%s(void) { }' % (base_module_name,)) prnt('# endif') prnt('# endif') prnt('#elif PY_MAJOR_VERSION >= 3') prnt('PyMODINIT_FUNC') prnt('PyInit_%s(void)' % (base_module_name,)) prnt('{') prnt(' return _cffi_init("%s", 0x%x, &_cffi_type_context);' % ( self.module_name, self._version)) prnt('}') prnt('#else') prnt('PyMODINIT_FUNC') prnt('init%s(void)' % (base_module_name,)) prnt('{') prnt(' _cffi_init("%s", 0x%x, &_cffi_type_context);' % ( self.module_name, self._version)) prnt('}') prnt('#endif') prnt() prnt('#ifdef __GNUC__') prnt('# pragma GCC visibility pop') prnt('#endif') self._version = None def _to_py(self, x): if isinstance(x, str): return "b'%s'" % (x,) if isinstance(x, (list, tuple)): rep = [self._to_py(item) for item in x] if len(rep) == 1: rep.append('') return "(%s)" % (','.join(rep),) return x.as_python_expr() # Py2: unicode unexpected; Py3: bytes unexp. def write_py_source_to_f(self, f): self._f = f prnt = self._prnt # # header prnt("# auto-generated file") prnt("import _cffi_backend") # # the 'import' of the included ffis num_includes = len(self.ffi._included_ffis or ()) for i in range(num_includes): ffi_to_include = self.ffi._included_ffis[i] try: included_module_name, included_source = ( ffi_to_include._assigned_source[:2]) except AttributeError: raise VerificationError( "ffi object %r includes %r, but the latter has not " "been prepared with set_source()" % ( self.ffi, ffi_to_include,)) if included_source is not None: raise VerificationError( "not implemented yet: ffi.include() of a C-based " "ffi inside a Python-based ffi") prnt('from %s import ffi as _ffi%d' % (included_module_name, i)) prnt() prnt("ffi = _cffi_backend.FFI('%s'," % (self.module_name,)) prnt(" _version = 0x%x," % (self._version,)) self._version = None # # the '_types' keyword argument self.cffi_types = tuple(self.cffi_types) # don't change any more types_lst = [op.as_python_bytes() for op in self.cffi_types] prnt(' _types = %s,' % (self._to_py(''.join(types_lst)),)) typeindex2type = dict([(i, tp) for (tp, i) in self._typesdict.items()]) # # the keyword arguments from ALL_STEPS for step_name in self.ALL_STEPS: lst = self._lsts[step_name] if len(lst) > 0 and step_name != "field": prnt(' _%ss = %s,' % (step_name, self._to_py(lst))) # # the '_includes' keyword argument if num_includes > 0: prnt(' _includes = (%s,),' % ( ', '.join(['_ffi%d' % i for i in range(num_includes)]),)) # # the footer prnt(')') # ---------- def _gettypenum(self, type): # a KeyError here is a bug. please report it! :-) return self._typesdict[type] def _convert_funcarg_to_c(self, tp, fromvar, tovar, errcode): extraarg = '' if isinstance(tp, model.BasePrimitiveType) and not tp.is_complex_type(): if tp.is_integer_type() and tp.name != '_Bool': converter = '_cffi_to_c_int' extraarg = ', %s' % tp.name elif isinstance(tp, model.UnknownFloatType): # don't check with is_float_type(): it may be a 'long # double' here, and _cffi_to_c_double would loose precision converter = '(%s)_cffi_to_c_double' % (tp.get_c_name(''),) else: cname = tp.get_c_name('') converter = '(%s)_cffi_to_c_%s' % (cname, tp.name.replace(' ', '_')) if cname in ('char16_t', 'char32_t'): self.needs_version(VERSION_CHAR16CHAR32) errvalue = '-1' # elif isinstance(tp, model.PointerType): self._convert_funcarg_to_c_ptr_or_array(tp, fromvar, tovar, errcode) return # elif (isinstance(tp, model.StructOrUnionOrEnum) or isinstance(tp, model.BasePrimitiveType)): # a struct (not a struct pointer) as a function argument; # or, a complex (the same code works) self._prnt(' if (_cffi_to_c((char *)&%s, _cffi_type(%d), %s) < 0)' % (tovar, self._gettypenum(tp), fromvar)) self._prnt(' %s;' % errcode) return # elif isinstance(tp, model.FunctionPtrType): converter = '(%s)_cffi_to_c_pointer' % tp.get_c_name('') extraarg = ', _cffi_type(%d)' % self._gettypenum(tp) errvalue = 'NULL' # else: raise NotImplementedError(tp) # self._prnt(' %s = %s(%s%s);' % (tovar, converter, fromvar, extraarg)) self._prnt(' if (%s == (%s)%s && PyErr_Occurred())' % ( tovar, tp.get_c_name(''), errvalue)) self._prnt(' %s;' % errcode) def _extra_local_variables(self, tp, localvars): if isinstance(tp, model.PointerType): localvars.add('Py_ssize_t datasize') def _convert_funcarg_to_c_ptr_or_array(self, tp, fromvar, tovar, errcode): self._prnt(' datasize = _cffi_prepare_pointer_call_argument(') self._prnt(' _cffi_type(%d), %s, (char **)&%s);' % ( self._gettypenum(tp), fromvar, tovar)) self._prnt(' if (datasize != 0) {') self._prnt(' if (datasize < 0)') self._prnt(' %s;' % errcode) self._prnt(' %s = (%s)alloca((size_t)datasize);' % ( tovar, tp.get_c_name(''))) self._prnt(' memset((void *)%s, 0, (size_t)datasize);' % (tovar,)) self._prnt(' if (_cffi_convert_array_from_object(' '(char *)%s, _cffi_type(%d), %s) < 0)' % ( tovar, self._gettypenum(tp), fromvar)) self._prnt(' %s;' % errcode) self._prnt(' }') def _convert_expr_from_c(self, tp, var, context): if isinstance(tp, model.BasePrimitiveType): if tp.is_integer_type() and tp.name != '_Bool': return '_cffi_from_c_int(%s, %s)' % (var, tp.name) elif isinstance(tp, model.UnknownFloatType): return '_cffi_from_c_double(%s)' % (var,) elif tp.name != 'long double' and not tp.is_complex_type(): cname = tp.name.replace(' ', '_') if cname in ('char16_t', 'char32_t'): self.needs_version(VERSION_CHAR16CHAR32) return '_cffi_from_c_%s(%s)' % (cname, var) else: return '_cffi_from_c_deref((char *)&%s, _cffi_type(%d))' % ( var, self._gettypenum(tp)) elif isinstance(tp, (model.PointerType, model.FunctionPtrType)): return '_cffi_from_c_pointer((char *)%s, _cffi_type(%d))' % ( var, self._gettypenum(tp)) elif isinstance(tp, model.ArrayType): return '_cffi_from_c_pointer((char *)%s, _cffi_type(%d))' % ( var, self._gettypenum(model.PointerType(tp.item))) elif isinstance(tp, model.StructOrUnion): if tp.fldnames is None: raise TypeError("'%s' is used as %s, but is opaque" % ( tp._get_c_name(), context)) return '_cffi_from_c_struct((char *)&%s, _cffi_type(%d))' % ( var, self._gettypenum(tp)) elif isinstance(tp, model.EnumType): return '_cffi_from_c_deref((char *)&%s, _cffi_type(%d))' % ( var, self._gettypenum(tp)) else: raise NotImplementedError(tp) # ---------- # typedefs def _typedef_type(self, tp, name): return self._global_type(tp, "(*(%s *)0)" % (name,)) def _generate_cpy_typedef_collecttype(self, tp, name): self._do_collect_type(self._typedef_type(tp, name)) def _generate_cpy_typedef_decl(self, tp, name): pass def _typedef_ctx(self, tp, name): type_index = self._typesdict[tp] self._lsts["typename"].append(TypenameExpr(name, type_index)) def _generate_cpy_typedef_ctx(self, tp, name): tp = self._typedef_type(tp, name) self._typedef_ctx(tp, name) if getattr(tp, "origin", None) == "unknown_type": self._struct_ctx(tp, tp.name, approxname=None) elif isinstance(tp, model.NamedPointerType): self._struct_ctx(tp.totype, tp.totype.name, approxname=tp.name, named_ptr=tp) # ---------- # function declarations def _generate_cpy_function_collecttype(self, tp, name): self._do_collect_type(tp.as_raw_function()) if tp.ellipsis and not self.target_is_python: self._do_collect_type(tp) def _generate_cpy_function_decl(self, tp, name): assert not self.target_is_python assert isinstance(tp, model.FunctionPtrType) if tp.ellipsis: # cannot support vararg functions better than this: check for its # exact type (including the fixed arguments), and build it as a # constant function pointer (no CPython wrapper) self._generate_cpy_constant_decl(tp, name) return prnt = self._prnt numargs = len(tp.args) if numargs == 0: argname = 'noarg' elif numargs == 1: argname = 'arg0' else: argname = 'args' # # ------------------------------ # the 'd' version of the function, only for addressof(lib, 'func') arguments = [] call_arguments = [] context = 'argument of %s' % name for i, type in enumerate(tp.args): arguments.append(type.get_c_name(' x%d' % i, context)) call_arguments.append('x%d' % i) repr_arguments = ', '.join(arguments) repr_arguments = repr_arguments or 'void' if tp.abi: abi = tp.abi + ' ' else: abi = '' name_and_arguments = '%s_cffi_d_%s(%s)' % (abi, name, repr_arguments) prnt('static %s' % (tp.result.get_c_name(name_and_arguments),)) prnt('{') call_arguments = ', '.join(call_arguments) result_code = 'return ' if isinstance(tp.result, model.VoidType): result_code = '' prnt(' %s%s(%s);' % (result_code, name, call_arguments)) prnt('}') # prnt('#ifndef PYPY_VERSION') # ------------------------------ # prnt('static PyObject *') prnt('_cffi_f_%s(PyObject *self, PyObject *%s)' % (name, argname)) prnt('{') # context = 'argument of %s' % name for i, type in enumerate(tp.args): arg = type.get_c_name(' x%d' % i, context) prnt(' %s;' % arg) # localvars = set() for type in tp.args: self._extra_local_variables(type, localvars) for decl in localvars: prnt(' %s;' % (decl,)) # if not isinstance(tp.result, model.VoidType): result_code = 'result = ' context = 'result of %s' % name result_decl = ' %s;' % tp.result.get_c_name(' result', context) prnt(result_decl) else: result_decl = None result_code = '' # if len(tp.args) > 1: rng = range(len(tp.args)) for i in rng: prnt(' PyObject *arg%d;' % i) prnt() prnt(' if (!PyArg_UnpackTuple(args, "%s", %d, %d, %s))' % ( name, len(rng), len(rng), ', '.join(['&arg%d' % i for i in rng]))) prnt(' return NULL;') prnt() # for i, type in enumerate(tp.args): self._convert_funcarg_to_c(type, 'arg%d' % i, 'x%d' % i, 'return NULL') prnt() # prnt(' Py_BEGIN_ALLOW_THREADS') prnt(' _cffi_restore_errno();') call_arguments = ['x%d' % i for i in range(len(tp.args))] call_arguments = ', '.join(call_arguments) prnt(' { %s%s(%s); }' % (result_code, name, call_arguments)) prnt(' _cffi_save_errno();') prnt(' Py_END_ALLOW_THREADS') prnt() # prnt(' (void)self; /* unused */') if numargs == 0: prnt(' (void)noarg; /* unused */') if result_code: prnt(' return %s;' % self._convert_expr_from_c(tp.result, 'result', 'result type')) else: prnt(' Py_INCREF(Py_None);') prnt(' return Py_None;') prnt('}') # prnt('#else') # ------------------------------ # # the PyPy version: need to replace struct/union arguments with # pointers, and if the result is a struct/union, insert a first # arg that is a pointer to the result. We also do that for # complex args and return type. def need_indirection(type): return (isinstance(type, model.StructOrUnion) or (isinstance(type, model.PrimitiveType) and type.is_complex_type())) difference = False arguments = [] call_arguments = [] context = 'argument of %s' % name for i, type in enumerate(tp.args): indirection = '' if need_indirection(type): indirection = '*' difference = True arg = type.get_c_name(' %sx%d' % (indirection, i), context) arguments.append(arg) call_arguments.append('%sx%d' % (indirection, i)) tp_result = tp.result if need_indirection(tp_result): context = 'result of %s' % name arg = tp_result.get_c_name(' *result', context) arguments.insert(0, arg) tp_result = model.void_type result_decl = None result_code = '*result = ' difference = True if difference: repr_arguments = ', '.join(arguments) repr_arguments = repr_arguments or 'void' name_and_arguments = '%s_cffi_f_%s(%s)' % (abi, name, repr_arguments) prnt('static %s' % (tp_result.get_c_name(name_and_arguments),)) prnt('{') if result_decl: prnt(result_decl) call_arguments = ', '.join(call_arguments) prnt(' { %s%s(%s); }' % (result_code, name, call_arguments)) if result_decl: prnt(' return result;') prnt('}') else: prnt('# define _cffi_f_%s _cffi_d_%s' % (name, name)) # prnt('#endif') # ------------------------------ prnt() def _generate_cpy_function_ctx(self, tp, name): if tp.ellipsis and not self.target_is_python: self._generate_cpy_constant_ctx(tp, name) return type_index = self._typesdict[tp.as_raw_function()] numargs = len(tp.args) if self.target_is_python: meth_kind = OP_DLOPEN_FUNC elif numargs == 0: meth_kind = OP_CPYTHON_BLTN_N # 'METH_NOARGS' elif numargs == 1: meth_kind = OP_CPYTHON_BLTN_O # 'METH_O' else: meth_kind = OP_CPYTHON_BLTN_V # 'METH_VARARGS' self._lsts["global"].append( GlobalExpr(name, '_cffi_f_%s' % name, CffiOp(meth_kind, type_index), size='_cffi_d_%s' % name)) # ---------- # named structs or unions def _field_type(self, tp_struct, field_name, tp_field): if isinstance(tp_field, model.ArrayType): actual_length = tp_field.length if actual_length == '...': ptr_struct_name = tp_struct.get_c_name('*') actual_length = '_cffi_array_len(((%s)0)->%s)' % ( ptr_struct_name, field_name) tp_item = self._field_type(tp_struct, '%s[0]' % field_name, tp_field.item) tp_field = model.ArrayType(tp_item, actual_length) return tp_field def _struct_collecttype(self, tp): self._do_collect_type(tp) if self.target_is_python: # also requires nested anon struct/unions in ABI mode, recursively for fldtype in tp.anonymous_struct_fields(): self._struct_collecttype(fldtype) def _struct_decl(self, tp, cname, approxname): if tp.fldtypes is None: return prnt = self._prnt checkfuncname = '_cffi_checkfld_%s' % (approxname,) prnt('_CFFI_UNUSED_FN') prnt('static void %s(%s *p)' % (checkfuncname, cname)) prnt('{') prnt(' /* only to generate compile-time warnings or errors */') prnt(' (void)p;') for fname, ftype, fbitsize, fqual in tp.enumfields(): try: if ftype.is_integer_type() or fbitsize >= 0: # accept all integers, but complain on float or double if fname != '': prnt(" (void)((p->%s) | 0); /* check that '%s.%s' is " "an integer */" % (fname, cname, fname)) continue # only accept exactly the type declared, except that '[]' # is interpreted as a '*' and so will match any array length. # (It would also match '*', but that's harder to detect...) while (isinstance(ftype, model.ArrayType) and (ftype.length is None or ftype.length == '...')): ftype = ftype.item fname = fname + '[0]' prnt(' { %s = &p->%s; (void)tmp; }' % ( ftype.get_c_name('*tmp', 'field %r'%fname, quals=fqual), fname)) except VerificationError as e: prnt(' /* %s */' % str(e)) # cannot verify it, ignore prnt('}') prnt('struct _cffi_align_%s { char x; %s y; };' % (approxname, cname)) prnt() def _struct_ctx(self, tp, cname, approxname, named_ptr=None): type_index = self._typesdict[tp] reason_for_not_expanding = None flags = [] if isinstance(tp, model.UnionType): flags.append("_CFFI_F_UNION") if tp.fldtypes is None: flags.append("_CFFI_F_OPAQUE") reason_for_not_expanding = "opaque" if (tp not in self.ffi._parser._included_declarations and (named_ptr is None or named_ptr not in self.ffi._parser._included_declarations)): if tp.fldtypes is None: pass # opaque elif tp.partial or any(tp.anonymous_struct_fields()): pass # field layout obtained silently from the C compiler else: flags.append("_CFFI_F_CHECK_FIELDS") if tp.packed: if tp.packed > 1: raise NotImplementedError( "%r is declared with 'pack=%r'; only 0 or 1 are " "supported in API mode (try to use \"...;\", which " "does not require a 'pack' declaration)" % (tp, tp.packed)) flags.append("_CFFI_F_PACKED") else: flags.append("_CFFI_F_EXTERNAL") reason_for_not_expanding = "external" flags = '|'.join(flags) or '0' c_fields = [] if reason_for_not_expanding is None: expand_anonymous_struct_union = not self.target_is_python enumfields = list(tp.enumfields(expand_anonymous_struct_union)) for fldname, fldtype, fbitsize, fqual in enumfields: fldtype = self._field_type(tp, fldname, fldtype) self._check_not_opaque(fldtype, "field '%s.%s'" % (tp.name, fldname)) # cname is None for _add_missing_struct_unions() only op = OP_NOOP if fbitsize >= 0: op = OP_BITFIELD size = '%d /* bits */' % fbitsize elif cname is None or ( isinstance(fldtype, model.ArrayType) and fldtype.length is None): size = '(size_t)-1' else: size = 'sizeof(((%s)0)->%s)' % ( tp.get_c_name('*') if named_ptr is None else named_ptr.name, fldname) if cname is None or fbitsize >= 0: offset = '(size_t)-1' elif named_ptr is not None: offset = '((char *)&((%s)0)->%s) - (char *)0' % ( named_ptr.name, fldname) else: offset = 'offsetof(%s, %s)' % (tp.get_c_name(''), fldname) c_fields.append( FieldExpr(fldname, offset, size, fbitsize, CffiOp(op, self._typesdict[fldtype]))) first_field_index = len(self._lsts["field"]) self._lsts["field"].extend(c_fields) # if cname is None: # unknown name, for _add_missing_struct_unions size = '(size_t)-2' align = -2 comment = "unnamed" else: if named_ptr is not None: size = 'sizeof(*(%s)0)' % (named_ptr.name,) align = '-1 /* unknown alignment */' else: size = 'sizeof(%s)' % (cname,) align = 'offsetof(struct _cffi_align_%s, y)' % (approxname,) comment = None else: size = '(size_t)-1' align = -1 first_field_index = -1 comment = reason_for_not_expanding self._lsts["struct_union"].append( StructUnionExpr(tp.name, type_index, flags, size, align, comment, first_field_index, c_fields)) self._seen_struct_unions.add(tp) def _check_not_opaque(self, tp, location): while isinstance(tp, model.ArrayType): tp = tp.item if isinstance(tp, model.StructOrUnion) and tp.fldtypes is None: raise TypeError( "%s is of an opaque type (not declared in cdef())" % location) def _add_missing_struct_unions(self): # not very nice, but some struct declarations might be missing # because they don't have any known C name. Check that they are # not partial (we can't complete or verify them!) and emit them # anonymously. lst = list(self._struct_unions.items()) lst.sort(key=lambda tp_order: tp_order[1]) for tp, order in lst: if tp not in self._seen_struct_unions: if tp.partial: raise NotImplementedError("internal inconsistency: %r is " "partial but was not seen at " "this point" % (tp,)) if tp.name.startswith('$') and tp.name[1:].isdigit(): approxname = tp.name[1:] elif tp.name == '_IO_FILE' and tp.forcename == 'FILE': approxname = 'FILE' self._typedef_ctx(tp, 'FILE') else: raise NotImplementedError("internal inconsistency: %r" % (tp,)) self._struct_ctx(tp, None, approxname) def _generate_cpy_struct_collecttype(self, tp, name): self._struct_collecttype(tp) _generate_cpy_union_collecttype = _generate_cpy_struct_collecttype def _struct_names(self, tp): cname = tp.get_c_name('') if ' ' in cname: return cname, cname.replace(' ', '_') else: return cname, '_' + cname def _generate_cpy_struct_decl(self, tp, name): self._struct_decl(tp, *self._struct_names(tp)) _generate_cpy_union_decl = _generate_cpy_struct_decl def _generate_cpy_struct_ctx(self, tp, name): self._struct_ctx(tp, *self._struct_names(tp)) _generate_cpy_union_ctx = _generate_cpy_struct_ctx # ---------- # 'anonymous' declarations. These are produced for anonymous structs # or unions; the 'name' is obtained by a typedef. def _generate_cpy_anonymous_collecttype(self, tp, name): if isinstance(tp, model.EnumType): self._generate_cpy_enum_collecttype(tp, name) else: self._struct_collecttype(tp) def _generate_cpy_anonymous_decl(self, tp, name): if isinstance(tp, model.EnumType): self._generate_cpy_enum_decl(tp) else: self._struct_decl(tp, name, 'typedef_' + name) def _generate_cpy_anonymous_ctx(self, tp, name): if isinstance(tp, model.EnumType): self._enum_ctx(tp, name) else: self._struct_ctx(tp, name, 'typedef_' + name) # ---------- # constants, declared with "static const ..." def _generate_cpy_const(self, is_int, name, tp=None, category='const', check_value=None): if (category, name) in self._seen_constants: raise VerificationError( "duplicate declaration of %s '%s'" % (category, name)) self._seen_constants.add((category, name)) # prnt = self._prnt funcname = '_cffi_%s_%s' % (category, name) if is_int: prnt('static int %s(unsigned long long *o)' % funcname) prnt('{') prnt(' int n = (%s) <= 0;' % (name,)) prnt(' *o = (unsigned long long)((%s) | 0);' ' /* check that %s is an integer */' % (name, name)) if check_value is not None: if check_value > 0: check_value = '%dU' % (check_value,) prnt(' if (!_cffi_check_int(*o, n, %s))' % (check_value,)) prnt(' n |= 2;') prnt(' return n;') prnt('}') else: assert check_value is None prnt('static void %s(char *o)' % funcname) prnt('{') prnt(' *(%s)o = %s;' % (tp.get_c_name('*'), name)) prnt('}') prnt() def _generate_cpy_constant_collecttype(self, tp, name): is_int = tp.is_integer_type() if not is_int or self.target_is_python: self._do_collect_type(tp) def _generate_cpy_constant_decl(self, tp, name): is_int = tp.is_integer_type() self._generate_cpy_const(is_int, name, tp) def _generate_cpy_constant_ctx(self, tp, name): if not self.target_is_python and tp.is_integer_type(): type_op = CffiOp(OP_CONSTANT_INT, -1) else: if self.target_is_python: const_kind = OP_DLOPEN_CONST else: const_kind = OP_CONSTANT type_index = self._typesdict[tp] type_op = CffiOp(const_kind, type_index) self._lsts["global"].append( GlobalExpr(name, '_cffi_const_%s' % name, type_op)) # ---------- # enums def _generate_cpy_enum_collecttype(self, tp, name): self._do_collect_type(tp) def _generate_cpy_enum_decl(self, tp, name=None): for enumerator in tp.enumerators: self._generate_cpy_const(True, enumerator) def _enum_ctx(self, tp, cname): type_index = self._typesdict[tp] type_op = CffiOp(OP_ENUM, -1) if self.target_is_python: tp.check_not_partial() for enumerator, enumvalue in zip(tp.enumerators, tp.enumvalues): self._lsts["global"].append( GlobalExpr(enumerator, '_cffi_const_%s' % enumerator, type_op, check_value=enumvalue)) # if cname is not None and '$' not in cname and not self.target_is_python: size = "sizeof(%s)" % cname signed = "((%s)-1) <= 0" % cname else: basetp = tp.build_baseinttype(self.ffi, []) size = self.ffi.sizeof(basetp) signed = int(int(self.ffi.cast(basetp, -1)) < 0) allenums = ",".join(tp.enumerators) self._lsts["enum"].append( EnumExpr(tp.name, type_index, size, signed, allenums)) def _generate_cpy_enum_ctx(self, tp, name): self._enum_ctx(tp, tp._get_c_name()) # ---------- # macros: for now only for integers def _generate_cpy_macro_collecttype(self, tp, name): pass def _generate_cpy_macro_decl(self, tp, name): if tp == '...': check_value = None else: check_value = tp # an integer self._generate_cpy_const(True, name, check_value=check_value) def _generate_cpy_macro_ctx(self, tp, name): if tp == '...': if self.target_is_python: raise VerificationError( "cannot use the syntax '...' in '#define %s ...' when " "using the ABI mode" % (name,)) check_value = None else: check_value = tp # an integer type_op = CffiOp(OP_CONSTANT_INT, -1) self._lsts["global"].append( GlobalExpr(name, '_cffi_const_%s' % name, type_op, check_value=check_value)) # ---------- # global variables def _global_type(self, tp, global_name): if isinstance(tp, model.ArrayType): actual_length = tp.length if actual_length == '...': actual_length = '_cffi_array_len(%s)' % (global_name,) tp_item = self._global_type(tp.item, '%s[0]' % global_name) tp = model.ArrayType(tp_item, actual_length) return tp def _generate_cpy_variable_collecttype(self, tp, name): self._do_collect_type(self._global_type(tp, name)) def _generate_cpy_variable_decl(self, tp, name): prnt = self._prnt tp = self._global_type(tp, name) if isinstance(tp, model.ArrayType) and tp.length is None: tp = tp.item ampersand = '' else: ampersand = '&' # This code assumes that casts from "tp *" to "void *" is a # no-op, i.e. a function that returns a "tp *" can be called # as if it returned a "void *". This should be generally true # on any modern machine. The only exception to that rule (on # uncommon architectures, and as far as I can tell) might be # if 'tp' were a function type, but that is not possible here. # (If 'tp' is a function _pointer_ type, then casts from "fn_t # **" to "void *" are again no-ops, as far as I can tell.) decl = '*_cffi_var_%s(void)' % (name,) prnt('static ' + tp.get_c_name(decl, quals=self._current_quals)) prnt('{') prnt(' return %s(%s);' % (ampersand, name)) prnt('}') prnt() def _generate_cpy_variable_ctx(self, tp, name): tp = self._global_type(tp, name) type_index = self._typesdict[tp] if self.target_is_python: op = OP_GLOBAL_VAR else: op = OP_GLOBAL_VAR_F self._lsts["global"].append( GlobalExpr(name, '_cffi_var_%s' % name, CffiOp(op, type_index))) # ---------- # extern "Python" def _generate_cpy_extern_python_collecttype(self, tp, name): assert isinstance(tp, model.FunctionPtrType) self._do_collect_type(tp) _generate_cpy_dllexport_python_collecttype = \ _generate_cpy_extern_python_plus_c_collecttype = \ _generate_cpy_extern_python_collecttype def _extern_python_decl(self, tp, name, tag_and_space): prnt = self._prnt if isinstance(tp.result, model.VoidType): size_of_result = '0' else: context = 'result of %s' % name size_of_result = '(int)sizeof(%s)' % ( tp.result.get_c_name('', context),) prnt('static struct _cffi_externpy_s _cffi_externpy__%s =' % name) prnt(' { "%s.%s", %s };' % (self.module_name, name, size_of_result)) prnt() # arguments = [] context = 'argument of %s' % name for i, type in enumerate(tp.args): arg = type.get_c_name(' a%d' % i, context) arguments.append(arg) # repr_arguments = ', '.join(arguments) repr_arguments = repr_arguments or 'void' name_and_arguments = '%s(%s)' % (name, repr_arguments) if tp.abi == "__stdcall": name_and_arguments = '_cffi_stdcall ' + name_and_arguments # def may_need_128_bits(tp): return (isinstance(tp, model.PrimitiveType) and tp.name == 'long double') # size_of_a = max(len(tp.args)*8, 8) if may_need_128_bits(tp.result): size_of_a = max(size_of_a, 16) if isinstance(tp.result, model.StructOrUnion): size_of_a = 'sizeof(%s) > %d ? sizeof(%s) : %d' % ( tp.result.get_c_name(''), size_of_a, tp.result.get_c_name(''), size_of_a) prnt('%s%s' % (tag_and_space, tp.result.get_c_name(name_and_arguments))) prnt('{') prnt(' char a[%s];' % size_of_a) prnt(' char *p = a;') for i, type in enumerate(tp.args): arg = 'a%d' % i if (isinstance(type, model.StructOrUnion) or may_need_128_bits(type)): arg = '&' + arg type = model.PointerType(type) prnt(' *(%s)(p + %d) = %s;' % (type.get_c_name('*'), i*8, arg)) prnt(' _cffi_call_python(&_cffi_externpy__%s, p);' % name) if not isinstance(tp.result, model.VoidType): prnt(' return *(%s)p;' % (tp.result.get_c_name('*'),)) prnt('}') prnt() self._num_externpy += 1 def _generate_cpy_extern_python_decl(self, tp, name): self._extern_python_decl(tp, name, 'static ') def _generate_cpy_dllexport_python_decl(self, tp, name): self._extern_python_decl(tp, name, 'CFFI_DLLEXPORT ') def _generate_cpy_extern_python_plus_c_decl(self, tp, name): self._extern_python_decl(tp, name, '') def _generate_cpy_extern_python_ctx(self, tp, name): if self.target_is_python: raise VerificationError( "cannot use 'extern \"Python\"' in the ABI mode") if tp.ellipsis: raise NotImplementedError("a vararg function is extern \"Python\"") type_index = self._typesdict[tp] type_op = CffiOp(OP_EXTERN_PYTHON, type_index) self._lsts["global"].append( GlobalExpr(name, '&_cffi_externpy__%s' % name, type_op, name)) _generate_cpy_dllexport_python_ctx = \ _generate_cpy_extern_python_plus_c_ctx = \ _generate_cpy_extern_python_ctx def _print_string_literal_in_array(self, s): prnt = self._prnt prnt('// # NB. this is not a string because of a size limit in MSVC') for line in s.splitlines(True): prnt(('// ' + line).rstrip()) printed_line = '' for c in line: if len(printed_line) >= 76: prnt(printed_line) printed_line = '' printed_line += '%d,' % (ord(c),) prnt(printed_line) # ---------- # emitting the opcodes for individual types def _emit_bytecode_VoidType(self, tp, index): self.cffi_types[index] = CffiOp(OP_PRIMITIVE, PRIM_VOID) def _emit_bytecode_PrimitiveType(self, tp, index): prim_index = PRIMITIVE_TO_INDEX[tp.name] self.cffi_types[index] = CffiOp(OP_PRIMITIVE, prim_index) def _emit_bytecode_UnknownIntegerType(self, tp, index): s = ('_cffi_prim_int(sizeof(%s), (\n' ' ((%s)-1) | 0 /* check that %s is an integer type */\n' ' ) <= 0)' % (tp.name, tp.name, tp.name)) self.cffi_types[index] = CffiOp(OP_PRIMITIVE, s) def _emit_bytecode_UnknownFloatType(self, tp, index): s = ('_cffi_prim_float(sizeof(%s) *\n' ' (((%s)1) / 2) * 2 /* integer => 0, float => 1 */\n' ' )' % (tp.name, tp.name)) self.cffi_types[index] = CffiOp(OP_PRIMITIVE, s) def _emit_bytecode_RawFunctionType(self, tp, index): self.cffi_types[index] = CffiOp(OP_FUNCTION, self._typesdict[tp.result]) index += 1 for tp1 in tp.args: realindex = self._typesdict[tp1] if index != realindex: if isinstance(tp1, model.PrimitiveType): self._emit_bytecode_PrimitiveType(tp1, index) else: self.cffi_types[index] = CffiOp(OP_NOOP, realindex) index += 1 flags = int(tp.ellipsis) if tp.abi is not None: if tp.abi == '__stdcall': flags |= 2 else: raise NotImplementedError("abi=%r" % (tp.abi,)) self.cffi_types[index] = CffiOp(OP_FUNCTION_END, flags) def _emit_bytecode_PointerType(self, tp, index): self.cffi_types[index] = CffiOp(OP_POINTER, self._typesdict[tp.totype]) _emit_bytecode_ConstPointerType = _emit_bytecode_PointerType _emit_bytecode_NamedPointerType = _emit_bytecode_PointerType def _emit_bytecode_FunctionPtrType(self, tp, index): raw = tp.as_raw_function() self.cffi_types[index] = CffiOp(OP_POINTER, self._typesdict[raw]) def _emit_bytecode_ArrayType(self, tp, index): item_index = self._typesdict[tp.item] if tp.length is None: self.cffi_types[index] = CffiOp(OP_OPEN_ARRAY, item_index) elif tp.length == '...': raise VerificationError( "type %s badly placed: the '...' array length can only be " "used on global arrays or on fields of structures" % ( str(tp).replace('/*...*/', '...'),)) else: assert self.cffi_types[index + 1] == 'LEN' self.cffi_types[index] = CffiOp(OP_ARRAY, item_index) self.cffi_types[index + 1] = CffiOp(None, str(tp.length)) def _emit_bytecode_StructType(self, tp, index): struct_index = self._struct_unions[tp] self.cffi_types[index] = CffiOp(OP_STRUCT_UNION, struct_index) _emit_bytecode_UnionType = _emit_bytecode_StructType def _emit_bytecode_EnumType(self, tp, index): enum_index = self._enums[tp] self.cffi_types[index] = CffiOp(OP_ENUM, enum_index) if sys.version_info >= (3,): NativeIO = io.StringIO else: class NativeIO(io.BytesIO): def write(self, s): if isinstance(s, unicode): s = s.encode('ascii') super(NativeIO, self).write(s) def _make_c_or_py_source(ffi, module_name, preamble, target_file, verbose): if verbose: print("generating %s" % (target_file,)) recompiler = Recompiler(ffi, module_name, target_is_python=(preamble is None)) recompiler.collect_type_table() recompiler.collect_step_tables() f = NativeIO() recompiler.write_source_to_f(f, preamble) output = f.getvalue() try: with open(target_file, 'r') as f1: if f1.read(len(output) + 1) != output: raise IOError if verbose: print("(already up-to-date)") return False # already up-to-date except IOError: tmp_file = '%s.~%d' % (target_file, os.getpid()) with open(tmp_file, 'w') as f1: f1.write(output) try: os.rename(tmp_file, target_file) except OSError: os.unlink(target_file) os.rename(tmp_file, target_file) return True def make_c_source(ffi, module_name, preamble, target_c_file, verbose=False): assert preamble is not None return _make_c_or_py_source(ffi, module_name, preamble, target_c_file, verbose) def make_py_source(ffi, module_name, target_py_file, verbose=False): return _make_c_or_py_source(ffi, module_name, None, target_py_file, verbose) def _modname_to_file(outputdir, modname, extension): parts = modname.split('.') try: os.makedirs(os.path.join(outputdir, *parts[:-1])) except OSError: pass parts[-1] += extension return os.path.join(outputdir, *parts), parts # Aaargh. Distutils is not tested at all for the purpose of compiling # DLLs that are not extension modules. Here are some hacks to work # around that, in the _patch_for_*() functions... def _patch_meth(patchlist, cls, name, new_meth): old = getattr(cls, name) patchlist.append((cls, name, old)) setattr(cls, name, new_meth) return old def _unpatch_meths(patchlist): for cls, name, old_meth in reversed(patchlist): setattr(cls, name, old_meth) def _patch_for_embedding(patchlist): if sys.platform == 'win32': # we must not remove the manifest when building for embedding! from distutils.msvc9compiler import MSVCCompiler _patch_meth(patchlist, MSVCCompiler, '_remove_visual_c_ref', lambda self, manifest_file: manifest_file) if sys.platform == 'darwin': # we must not make a '-bundle', but a '-dynamiclib' instead from distutils.ccompiler import CCompiler def my_link_shared_object(self, *args, **kwds): if '-bundle' in self.linker_so: self.linker_so = list(self.linker_so) i = self.linker_so.index('-bundle') self.linker_so[i] = '-dynamiclib' return old_link_shared_object(self, *args, **kwds) old_link_shared_object = _patch_meth(patchlist, CCompiler, 'link_shared_object', my_link_shared_object) def _patch_for_target(patchlist, target): from distutils.command.build_ext import build_ext # if 'target' is different from '*', we need to patch some internal # method to just return this 'target' value, instead of having it # built from module_name if target.endswith('.*'): target = target[:-2] if sys.platform == 'win32': target += '.dll' elif sys.platform == 'darwin': target += '.dylib' else: target += '.so' _patch_meth(patchlist, build_ext, 'get_ext_filename', lambda self, ext_name: target) def recompile(ffi, module_name, preamble, tmpdir='.', call_c_compiler=True, c_file=None, source_extension='.c', extradir=None, compiler_verbose=1, target=None, debug=None, **kwds): if not isinstance(module_name, str): module_name = module_name.encode('ascii') if ffi._windows_unicode: ffi._apply_windows_unicode(kwds) if preamble is not None: embedding = (ffi._embedding is not None) if embedding: ffi._apply_embedding_fix(kwds) if c_file is None: c_file, parts = _modname_to_file(tmpdir, module_name, source_extension) if extradir: parts = [extradir] + parts ext_c_file = os.path.join(*parts) else: ext_c_file = c_file # if target is None: if embedding: target = '%s.*' % module_name else: target = '*' # ext = ffiplatform.get_extension(ext_c_file, module_name, **kwds) updated = make_c_source(ffi, module_name, preamble, c_file, verbose=compiler_verbose) if call_c_compiler: patchlist = [] cwd = os.getcwd() try: if embedding: _patch_for_embedding(patchlist) if target != '*': _patch_for_target(patchlist, target) if compiler_verbose: if tmpdir == '.': msg = 'the current directory is' else: msg = 'setting the current directory to' print('%s %r' % (msg, os.path.abspath(tmpdir))) os.chdir(tmpdir) outputfilename = ffiplatform.compile('.', ext, compiler_verbose, debug) finally: os.chdir(cwd) _unpatch_meths(patchlist) return outputfilename else: return ext, updated else: if c_file is None: c_file, _ = _modname_to_file(tmpdir, module_name, '.py') updated = make_py_source(ffi, module_name, c_file, verbose=compiler_verbose) if call_c_compiler: return c_file else: return None, updated ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/cffi/setuptools_ext.py ================================================ import os import sys try: basestring except NameError: # Python 3.x basestring = str def error(msg): from distutils.errors import DistutilsSetupError raise DistutilsSetupError(msg) def execfile(filename, glob): # We use execfile() (here rewritten for Python 3) instead of # __import__() to load the build script. The problem with # a normal import is that in some packages, the intermediate # __init__.py files may already try to import the file that # we are generating. with open(filename) as f: src = f.read() src += '\n' # Python 2.6 compatibility code = compile(src, filename, 'exec') exec(code, glob, glob) def add_cffi_module(dist, mod_spec): from cffi.api import FFI if not isinstance(mod_spec, basestring): error("argument to 'cffi_modules=...' must be a str or a list of str," " not %r" % (type(mod_spec).__name__,)) mod_spec = str(mod_spec) try: build_file_name, ffi_var_name = mod_spec.split(':') except ValueError: error("%r must be of the form 'path/build.py:ffi_variable'" % (mod_spec,)) if not os.path.exists(build_file_name): ext = '' rewritten = build_file_name.replace('.', '/') + '.py' if os.path.exists(rewritten): ext = ' (rewrite cffi_modules to [%r])' % ( rewritten + ':' + ffi_var_name,) error("%r does not name an existing file%s" % (build_file_name, ext)) mod_vars = {'__name__': '__cffi__', '__file__': build_file_name} execfile(build_file_name, mod_vars) try: ffi = mod_vars[ffi_var_name] except KeyError: error("%r: object %r not found in module" % (mod_spec, ffi_var_name)) if not isinstance(ffi, FFI): ffi = ffi() # maybe it's a function instead of directly an ffi if not isinstance(ffi, FFI): error("%r is not an FFI instance (got %r)" % (mod_spec, type(ffi).__name__)) if not hasattr(ffi, '_assigned_source'): error("%r: the set_source() method was not called" % (mod_spec,)) module_name, source, source_extension, kwds = ffi._assigned_source if ffi._windows_unicode: kwds = kwds.copy() ffi._apply_windows_unicode(kwds) if source is None: _add_py_module(dist, ffi, module_name) else: _add_c_module(dist, ffi, module_name, source, source_extension, kwds) def _set_py_limited_api(Extension, kwds): """ Add py_limited_api to kwds if setuptools >= 26 is in use. Do not alter the setting if it already exists. Setuptools takes care of ignoring the flag on Python 2 and PyPy. CPython itself should ignore the flag in a debugging version (by not listing .abi3.so in the extensions it supports), but it doesn't so far, creating troubles. That's why we check for "not hasattr(sys, 'gettotalrefcount')" (the 2.7 compatible equivalent of 'd' not in sys.abiflags). (http://bugs.python.org/issue28401) On Windows, with CPython <= 3.4, it's better not to use py_limited_api because virtualenv *still* doesn't copy PYTHON3.DLL on these versions. For now we'll skip py_limited_api on all Windows versions to avoid an inconsistent mess. """ if ('py_limited_api' not in kwds and not hasattr(sys, 'gettotalrefcount') and sys.platform != 'win32'): import setuptools try: setuptools_major_version = int(setuptools.__version__.partition('.')[0]) if setuptools_major_version >= 26: kwds['py_limited_api'] = True except ValueError: # certain development versions of setuptools # If we don't know the version number of setuptools, we # try to set 'py_limited_api' anyway. At worst, we get a # warning. kwds['py_limited_api'] = True return kwds def _add_c_module(dist, ffi, module_name, source, source_extension, kwds): from distutils.core import Extension # We are a setuptools extension. Need this build_ext for py_limited_api. from setuptools.command.build_ext import build_ext from distutils.dir_util import mkpath from distutils import log from cffi import recompiler allsources = ['$PLACEHOLDER'] allsources.extend(kwds.pop('sources', [])) kwds = _set_py_limited_api(Extension, kwds) ext = Extension(name=module_name, sources=allsources, **kwds) def make_mod(tmpdir, pre_run=None): c_file = os.path.join(tmpdir, module_name + source_extension) log.info("generating cffi module %r" % c_file) mkpath(tmpdir) # a setuptools-only, API-only hook: called with the "ext" and "ffi" # arguments just before we turn the ffi into C code. To use it, # subclass the 'distutils.command.build_ext.build_ext' class and # add a method 'def pre_run(self, ext, ffi)'. if pre_run is not None: pre_run(ext, ffi) updated = recompiler.make_c_source(ffi, module_name, source, c_file) if not updated: log.info("already up-to-date") return c_file if dist.ext_modules is None: dist.ext_modules = [] dist.ext_modules.append(ext) base_class = dist.cmdclass.get('build_ext', build_ext) class build_ext_make_mod(base_class): def run(self): if ext.sources[0] == '$PLACEHOLDER': pre_run = getattr(self, 'pre_run', None) ext.sources[0] = make_mod(self.build_temp, pre_run) base_class.run(self) dist.cmdclass['build_ext'] = build_ext_make_mod # NB. multiple runs here will create multiple 'build_ext_make_mod' # classes. Even in this case the 'build_ext' command should be # run once; but just in case, the logic above does nothing if # called again. def _add_py_module(dist, ffi, module_name): from distutils.dir_util import mkpath from setuptools.command.build_py import build_py from setuptools.command.build_ext import build_ext from distutils import log from cffi import recompiler def generate_mod(py_file): log.info("generating cffi module %r" % py_file) mkpath(os.path.dirname(py_file)) updated = recompiler.make_py_source(ffi, module_name, py_file) if not updated: log.info("already up-to-date") base_class = dist.cmdclass.get('build_py', build_py) class build_py_make_mod(base_class): def run(self): base_class.run(self) module_path = module_name.split('.') module_path[-1] += '.py' generate_mod(os.path.join(self.build_lib, *module_path)) def get_source_files(self): # This is called from 'setup.py sdist' only. Exclude # the generate .py module in this case. saved_py_modules = self.py_modules try: if saved_py_modules: self.py_modules = [m for m in saved_py_modules if m != module_name] return base_class.get_source_files(self) finally: self.py_modules = saved_py_modules dist.cmdclass['build_py'] = build_py_make_mod # distutils and setuptools have no notion I could find of a # generated python module. If we don't add module_name to # dist.py_modules, then things mostly work but there are some # combination of options (--root and --record) that will miss # the module. So we add it here, which gives a few apparently # harmless warnings about not finding the file outside the # build directory. # Then we need to hack more in get_source_files(); see above. if dist.py_modules is None: dist.py_modules = [] dist.py_modules.append(module_name) # the following is only for "build_ext -i" base_class_2 = dist.cmdclass.get('build_ext', build_ext) class build_ext_make_mod(base_class_2): def run(self): base_class_2.run(self) if self.inplace: # from get_ext_fullpath() in distutils/command/build_ext.py module_path = module_name.split('.') package = '.'.join(module_path[:-1]) build_py = self.get_finalized_command('build_py') package_dir = build_py.get_package_dir(package) file_name = module_path[-1] + '.py' generate_mod(os.path.join(package_dir, file_name)) dist.cmdclass['build_ext'] = build_ext_make_mod def cffi_modules(dist, attr, value): assert attr == 'cffi_modules' if isinstance(value, basestring): value = [value] for cffi_module in value: add_cffi_module(dist, cffi_module) ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/cffi/vengine_cpy.py ================================================ # # DEPRECATED: implementation for ffi.verify() # import sys, imp from . import model from .error import VerificationError class VCPythonEngine(object): _class_key = 'x' _gen_python_module = True def __init__(self, verifier): self.verifier = verifier self.ffi = verifier.ffi self._struct_pending_verification = {} self._types_of_builtin_functions = {} def patch_extension_kwds(self, kwds): pass def find_module(self, module_name, path, so_suffixes): try: f, filename, descr = imp.find_module(module_name, path) except ImportError: return None if f is not None: f.close() # Note that after a setuptools installation, there are both .py # and .so files with the same basename. The code here relies on # imp.find_module() locating the .so in priority. if descr[0] not in so_suffixes: return None return filename def collect_types(self): self._typesdict = {} self._generate("collecttype") def _prnt(self, what=''): self._f.write(what + '\n') def _gettypenum(self, type): # a KeyError here is a bug. please report it! :-) return self._typesdict[type] def _do_collect_type(self, tp): if ((not isinstance(tp, model.PrimitiveType) or tp.name == 'long double') and tp not in self._typesdict): num = len(self._typesdict) self._typesdict[tp] = num def write_source_to_f(self): self.collect_types() # # The new module will have a _cffi_setup() function that receives # objects from the ffi world, and that calls some setup code in # the module. This setup code is split in several independent # functions, e.g. one per constant. The functions are "chained" # by ending in a tail call to each other. # # This is further split in two chained lists, depending on if we # can do it at import-time or if we must wait for _cffi_setup() to # provide us with the objects. This is needed because we # need the values of the enum constants in order to build the # that we may have to pass to _cffi_setup(). # # The following two 'chained_list_constants' items contains # the head of these two chained lists, as a string that gives the # call to do, if any. self._chained_list_constants = ['((void)lib,0)', '((void)lib,0)'] # prnt = self._prnt # first paste some standard set of lines that are mostly '#define' prnt(cffimod_header) prnt() # then paste the C source given by the user, verbatim. prnt(self.verifier.preamble) prnt() # # call generate_cpy_xxx_decl(), for every xxx found from # ffi._parser._declarations. This generates all the functions. self._generate("decl") # # implement the function _cffi_setup_custom() as calling the # head of the chained list. self._generate_setup_custom() prnt() # # produce the method table, including the entries for the # generated Python->C function wrappers, which are done # by generate_cpy_function_method(). prnt('static PyMethodDef _cffi_methods[] = {') self._generate("method") prnt(' {"_cffi_setup", _cffi_setup, METH_VARARGS, NULL},') prnt(' {NULL, NULL, 0, NULL} /* Sentinel */') prnt('};') prnt() # # standard init. modname = self.verifier.get_module_name() constants = self._chained_list_constants[False] prnt('#if PY_MAJOR_VERSION >= 3') prnt() prnt('static struct PyModuleDef _cffi_module_def = {') prnt(' PyModuleDef_HEAD_INIT,') prnt(' "%s",' % modname) prnt(' NULL,') prnt(' -1,') prnt(' _cffi_methods,') prnt(' NULL, NULL, NULL, NULL') prnt('};') prnt() prnt('PyMODINIT_FUNC') prnt('PyInit_%s(void)' % modname) prnt('{') prnt(' PyObject *lib;') prnt(' lib = PyModule_Create(&_cffi_module_def);') prnt(' if (lib == NULL)') prnt(' return NULL;') prnt(' if (%s < 0 || _cffi_init() < 0) {' % (constants,)) prnt(' Py_DECREF(lib);') prnt(' return NULL;') prnt(' }') prnt(' return lib;') prnt('}') prnt() prnt('#else') prnt() prnt('PyMODINIT_FUNC') prnt('init%s(void)' % modname) prnt('{') prnt(' PyObject *lib;') prnt(' lib = Py_InitModule("%s", _cffi_methods);' % modname) prnt(' if (lib == NULL)') prnt(' return;') prnt(' if (%s < 0 || _cffi_init() < 0)' % (constants,)) prnt(' return;') prnt(' return;') prnt('}') prnt() prnt('#endif') def load_library(self, flags=None): # XXX review all usages of 'self' here! # import it as a new extension module imp.acquire_lock() try: if hasattr(sys, "getdlopenflags"): previous_flags = sys.getdlopenflags() try: if hasattr(sys, "setdlopenflags") and flags is not None: sys.setdlopenflags(flags) module = imp.load_dynamic(self.verifier.get_module_name(), self.verifier.modulefilename) except ImportError as e: error = "importing %r: %s" % (self.verifier.modulefilename, e) raise VerificationError(error) finally: if hasattr(sys, "setdlopenflags"): sys.setdlopenflags(previous_flags) finally: imp.release_lock() # # call loading_cpy_struct() to get the struct layout inferred by # the C compiler self._load(module, 'loading') # # the C code will need the objects. Collect them in # order in a list. revmapping = dict([(value, key) for (key, value) in self._typesdict.items()]) lst = [revmapping[i] for i in range(len(revmapping))] lst = list(map(self.ffi._get_cached_btype, lst)) # # build the FFILibrary class and instance and call _cffi_setup(). # this will set up some fields like '_cffi_types', and only then # it will invoke the chained list of functions that will really # build (notably) the constant objects, as if they are # pointers, and store them as attributes on the 'library' object. class FFILibrary(object): _cffi_python_module = module _cffi_ffi = self.ffi _cffi_dir = [] def __dir__(self): return FFILibrary._cffi_dir + list(self.__dict__) library = FFILibrary() if module._cffi_setup(lst, VerificationError, library): import warnings warnings.warn("reimporting %r might overwrite older definitions" % (self.verifier.get_module_name())) # # finally, call the loaded_cpy_xxx() functions. This will perform # the final adjustments, like copying the Python->C wrapper # functions from the module to the 'library' object, and setting # up the FFILibrary class with properties for the global C variables. self._load(module, 'loaded', library=library) module._cffi_original_ffi = self.ffi module._cffi_types_of_builtin_funcs = self._types_of_builtin_functions return library def _get_declarations(self): lst = [(key, tp) for (key, (tp, qual)) in self.ffi._parser._declarations.items()] lst.sort() return lst def _generate(self, step_name): for name, tp in self._get_declarations(): kind, realname = name.split(' ', 1) try: method = getattr(self, '_generate_cpy_%s_%s' % (kind, step_name)) except AttributeError: raise VerificationError( "not implemented in verify(): %r" % name) try: method(tp, realname) except Exception as e: model.attach_exception_info(e, name) raise def _load(self, module, step_name, **kwds): for name, tp in self._get_declarations(): kind, realname = name.split(' ', 1) method = getattr(self, '_%s_cpy_%s' % (step_name, kind)) try: method(tp, realname, module, **kwds) except Exception as e: model.attach_exception_info(e, name) raise def _generate_nothing(self, tp, name): pass def _loaded_noop(self, tp, name, module, **kwds): pass # ---------- def _convert_funcarg_to_c(self, tp, fromvar, tovar, errcode): extraarg = '' if isinstance(tp, model.PrimitiveType): if tp.is_integer_type() and tp.name != '_Bool': converter = '_cffi_to_c_int' extraarg = ', %s' % tp.name else: converter = '(%s)_cffi_to_c_%s' % (tp.get_c_name(''), tp.name.replace(' ', '_')) errvalue = '-1' # elif isinstance(tp, model.PointerType): self._convert_funcarg_to_c_ptr_or_array(tp, fromvar, tovar, errcode) return # elif isinstance(tp, (model.StructOrUnion, model.EnumType)): # a struct (not a struct pointer) as a function argument self._prnt(' if (_cffi_to_c((char *)&%s, _cffi_type(%d), %s) < 0)' % (tovar, self._gettypenum(tp), fromvar)) self._prnt(' %s;' % errcode) return # elif isinstance(tp, model.FunctionPtrType): converter = '(%s)_cffi_to_c_pointer' % tp.get_c_name('') extraarg = ', _cffi_type(%d)' % self._gettypenum(tp) errvalue = 'NULL' # else: raise NotImplementedError(tp) # self._prnt(' %s = %s(%s%s);' % (tovar, converter, fromvar, extraarg)) self._prnt(' if (%s == (%s)%s && PyErr_Occurred())' % ( tovar, tp.get_c_name(''), errvalue)) self._prnt(' %s;' % errcode) def _extra_local_variables(self, tp, localvars): if isinstance(tp, model.PointerType): localvars.add('Py_ssize_t datasize') def _convert_funcarg_to_c_ptr_or_array(self, tp, fromvar, tovar, errcode): self._prnt(' datasize = _cffi_prepare_pointer_call_argument(') self._prnt(' _cffi_type(%d), %s, (char **)&%s);' % ( self._gettypenum(tp), fromvar, tovar)) self._prnt(' if (datasize != 0) {') self._prnt(' if (datasize < 0)') self._prnt(' %s;' % errcode) self._prnt(' %s = alloca((size_t)datasize);' % (tovar,)) self._prnt(' memset((void *)%s, 0, (size_t)datasize);' % (tovar,)) self._prnt(' if (_cffi_convert_array_from_object(' '(char *)%s, _cffi_type(%d), %s) < 0)' % ( tovar, self._gettypenum(tp), fromvar)) self._prnt(' %s;' % errcode) self._prnt(' }') def _convert_expr_from_c(self, tp, var, context): if isinstance(tp, model.PrimitiveType): if tp.is_integer_type() and tp.name != '_Bool': return '_cffi_from_c_int(%s, %s)' % (var, tp.name) elif tp.name != 'long double': return '_cffi_from_c_%s(%s)' % (tp.name.replace(' ', '_'), var) else: return '_cffi_from_c_deref((char *)&%s, _cffi_type(%d))' % ( var, self._gettypenum(tp)) elif isinstance(tp, (model.PointerType, model.FunctionPtrType)): return '_cffi_from_c_pointer((char *)%s, _cffi_type(%d))' % ( var, self._gettypenum(tp)) elif isinstance(tp, model.ArrayType): return '_cffi_from_c_pointer((char *)%s, _cffi_type(%d))' % ( var, self._gettypenum(model.PointerType(tp.item))) elif isinstance(tp, model.StructOrUnion): if tp.fldnames is None: raise TypeError("'%s' is used as %s, but is opaque" % ( tp._get_c_name(), context)) return '_cffi_from_c_struct((char *)&%s, _cffi_type(%d))' % ( var, self._gettypenum(tp)) elif isinstance(tp, model.EnumType): return '_cffi_from_c_deref((char *)&%s, _cffi_type(%d))' % ( var, self._gettypenum(tp)) else: raise NotImplementedError(tp) # ---------- # typedefs: generates no code so far _generate_cpy_typedef_collecttype = _generate_nothing _generate_cpy_typedef_decl = _generate_nothing _generate_cpy_typedef_method = _generate_nothing _loading_cpy_typedef = _loaded_noop _loaded_cpy_typedef = _loaded_noop # ---------- # function declarations def _generate_cpy_function_collecttype(self, tp, name): assert isinstance(tp, model.FunctionPtrType) if tp.ellipsis: self._do_collect_type(tp) else: # don't call _do_collect_type(tp) in this common case, # otherwise test_autofilled_struct_as_argument fails for type in tp.args: self._do_collect_type(type) self._do_collect_type(tp.result) def _generate_cpy_function_decl(self, tp, name): assert isinstance(tp, model.FunctionPtrType) if tp.ellipsis: # cannot support vararg functions better than this: check for its # exact type (including the fixed arguments), and build it as a # constant function pointer (no CPython wrapper) self._generate_cpy_const(False, name, tp) return prnt = self._prnt numargs = len(tp.args) if numargs == 0: argname = 'noarg' elif numargs == 1: argname = 'arg0' else: argname = 'args' prnt('static PyObject *') prnt('_cffi_f_%s(PyObject *self, PyObject *%s)' % (name, argname)) prnt('{') # context = 'argument of %s' % name for i, type in enumerate(tp.args): prnt(' %s;' % type.get_c_name(' x%d' % i, context)) # localvars = set() for type in tp.args: self._extra_local_variables(type, localvars) for decl in localvars: prnt(' %s;' % (decl,)) # if not isinstance(tp.result, model.VoidType): result_code = 'result = ' context = 'result of %s' % name prnt(' %s;' % tp.result.get_c_name(' result', context)) else: result_code = '' # if len(tp.args) > 1: rng = range(len(tp.args)) for i in rng: prnt(' PyObject *arg%d;' % i) prnt() prnt(' if (!PyArg_ParseTuple(args, "%s:%s", %s))' % ( 'O' * numargs, name, ', '.join(['&arg%d' % i for i in rng]))) prnt(' return NULL;') prnt() # for i, type in enumerate(tp.args): self._convert_funcarg_to_c(type, 'arg%d' % i, 'x%d' % i, 'return NULL') prnt() # prnt(' Py_BEGIN_ALLOW_THREADS') prnt(' _cffi_restore_errno();') prnt(' { %s%s(%s); }' % ( result_code, name, ', '.join(['x%d' % i for i in range(len(tp.args))]))) prnt(' _cffi_save_errno();') prnt(' Py_END_ALLOW_THREADS') prnt() # prnt(' (void)self; /* unused */') if numargs == 0: prnt(' (void)noarg; /* unused */') if result_code: prnt(' return %s;' % self._convert_expr_from_c(tp.result, 'result', 'result type')) else: prnt(' Py_INCREF(Py_None);') prnt(' return Py_None;') prnt('}') prnt() def _generate_cpy_function_method(self, tp, name): if tp.ellipsis: return numargs = len(tp.args) if numargs == 0: meth = 'METH_NOARGS' elif numargs == 1: meth = 'METH_O' else: meth = 'METH_VARARGS' self._prnt(' {"%s", _cffi_f_%s, %s, NULL},' % (name, name, meth)) _loading_cpy_function = _loaded_noop def _loaded_cpy_function(self, tp, name, module, library): if tp.ellipsis: return func = getattr(module, name) setattr(library, name, func) self._types_of_builtin_functions[func] = tp # ---------- # named structs _generate_cpy_struct_collecttype = _generate_nothing def _generate_cpy_struct_decl(self, tp, name): assert name == tp.name self._generate_struct_or_union_decl(tp, 'struct', name) def _generate_cpy_struct_method(self, tp, name): self._generate_struct_or_union_method(tp, 'struct', name) def _loading_cpy_struct(self, tp, name, module): self._loading_struct_or_union(tp, 'struct', name, module) def _loaded_cpy_struct(self, tp, name, module, **kwds): self._loaded_struct_or_union(tp) _generate_cpy_union_collecttype = _generate_nothing def _generate_cpy_union_decl(self, tp, name): assert name == tp.name self._generate_struct_or_union_decl(tp, 'union', name) def _generate_cpy_union_method(self, tp, name): self._generate_struct_or_union_method(tp, 'union', name) def _loading_cpy_union(self, tp, name, module): self._loading_struct_or_union(tp, 'union', name, module) def _loaded_cpy_union(self, tp, name, module, **kwds): self._loaded_struct_or_union(tp) def _generate_struct_or_union_decl(self, tp, prefix, name): if tp.fldnames is None: return # nothing to do with opaque structs checkfuncname = '_cffi_check_%s_%s' % (prefix, name) layoutfuncname = '_cffi_layout_%s_%s' % (prefix, name) cname = ('%s %s' % (prefix, name)).strip() # prnt = self._prnt prnt('static void %s(%s *p)' % (checkfuncname, cname)) prnt('{') prnt(' /* only to generate compile-time warnings or errors */') prnt(' (void)p;') for fname, ftype, fbitsize, fqual in tp.enumfields(): if (isinstance(ftype, model.PrimitiveType) and ftype.is_integer_type()) or fbitsize >= 0: # accept all integers, but complain on float or double prnt(' (void)((p->%s) << 1);' % fname) else: # only accept exactly the type declared. try: prnt(' { %s = &p->%s; (void)tmp; }' % ( ftype.get_c_name('*tmp', 'field %r'%fname, quals=fqual), fname)) except VerificationError as e: prnt(' /* %s */' % str(e)) # cannot verify it, ignore prnt('}') prnt('static PyObject *') prnt('%s(PyObject *self, PyObject *noarg)' % (layoutfuncname,)) prnt('{') prnt(' struct _cffi_aligncheck { char x; %s y; };' % cname) prnt(' static Py_ssize_t nums[] = {') prnt(' sizeof(%s),' % cname) prnt(' offsetof(struct _cffi_aligncheck, y),') for fname, ftype, fbitsize, fqual in tp.enumfields(): if fbitsize >= 0: continue # xxx ignore fbitsize for now prnt(' offsetof(%s, %s),' % (cname, fname)) if isinstance(ftype, model.ArrayType) and ftype.length is None: prnt(' 0, /* %s */' % ftype._get_c_name()) else: prnt(' sizeof(((%s *)0)->%s),' % (cname, fname)) prnt(' -1') prnt(' };') prnt(' (void)self; /* unused */') prnt(' (void)noarg; /* unused */') prnt(' return _cffi_get_struct_layout(nums);') prnt(' /* the next line is not executed, but compiled */') prnt(' %s(0);' % (checkfuncname,)) prnt('}') prnt() def _generate_struct_or_union_method(self, tp, prefix, name): if tp.fldnames is None: return # nothing to do with opaque structs layoutfuncname = '_cffi_layout_%s_%s' % (prefix, name) self._prnt(' {"%s", %s, METH_NOARGS, NULL},' % (layoutfuncname, layoutfuncname)) def _loading_struct_or_union(self, tp, prefix, name, module): if tp.fldnames is None: return # nothing to do with opaque structs layoutfuncname = '_cffi_layout_%s_%s' % (prefix, name) # function = getattr(module, layoutfuncname) layout = function() if isinstance(tp, model.StructOrUnion) and tp.partial: # use the function()'s sizes and offsets to guide the # layout of the struct totalsize = layout[0] totalalignment = layout[1] fieldofs = layout[2::2] fieldsize = layout[3::2] tp.force_flatten() assert len(fieldofs) == len(fieldsize) == len(tp.fldnames) tp.fixedlayout = fieldofs, fieldsize, totalsize, totalalignment else: cname = ('%s %s' % (prefix, name)).strip() self._struct_pending_verification[tp] = layout, cname def _loaded_struct_or_union(self, tp): if tp.fldnames is None: return # nothing to do with opaque structs self.ffi._get_cached_btype(tp) # force 'fixedlayout' to be considered if tp in self._struct_pending_verification: # check that the layout sizes and offsets match the real ones def check(realvalue, expectedvalue, msg): if realvalue != expectedvalue: raise VerificationError( "%s (we have %d, but C compiler says %d)" % (msg, expectedvalue, realvalue)) ffi = self.ffi BStruct = ffi._get_cached_btype(tp) layout, cname = self._struct_pending_verification.pop(tp) check(layout[0], ffi.sizeof(BStruct), "wrong total size") check(layout[1], ffi.alignof(BStruct), "wrong total alignment") i = 2 for fname, ftype, fbitsize, fqual in tp.enumfields(): if fbitsize >= 0: continue # xxx ignore fbitsize for now check(layout[i], ffi.offsetof(BStruct, fname), "wrong offset for field %r" % (fname,)) if layout[i+1] != 0: BField = ffi._get_cached_btype(ftype) check(layout[i+1], ffi.sizeof(BField), "wrong size for field %r" % (fname,)) i += 2 assert i == len(layout) # ---------- # 'anonymous' declarations. These are produced for anonymous structs # or unions; the 'name' is obtained by a typedef. _generate_cpy_anonymous_collecttype = _generate_nothing def _generate_cpy_anonymous_decl(self, tp, name): if isinstance(tp, model.EnumType): self._generate_cpy_enum_decl(tp, name, '') else: self._generate_struct_or_union_decl(tp, '', name) def _generate_cpy_anonymous_method(self, tp, name): if not isinstance(tp, model.EnumType): self._generate_struct_or_union_method(tp, '', name) def _loading_cpy_anonymous(self, tp, name, module): if isinstance(tp, model.EnumType): self._loading_cpy_enum(tp, name, module) else: self._loading_struct_or_union(tp, '', name, module) def _loaded_cpy_anonymous(self, tp, name, module, **kwds): if isinstance(tp, model.EnumType): self._loaded_cpy_enum(tp, name, module, **kwds) else: self._loaded_struct_or_union(tp) # ---------- # constants, likely declared with '#define' def _generate_cpy_const(self, is_int, name, tp=None, category='const', vartp=None, delayed=True, size_too=False, check_value=None): prnt = self._prnt funcname = '_cffi_%s_%s' % (category, name) prnt('static int %s(PyObject *lib)' % funcname) prnt('{') prnt(' PyObject *o;') prnt(' int res;') if not is_int: prnt(' %s;' % (vartp or tp).get_c_name(' i', name)) else: assert category == 'const' # if check_value is not None: self._check_int_constant_value(name, check_value) # if not is_int: if category == 'var': realexpr = '&' + name else: realexpr = name prnt(' i = (%s);' % (realexpr,)) prnt(' o = %s;' % (self._convert_expr_from_c(tp, 'i', 'variable type'),)) assert delayed else: prnt(' o = _cffi_from_c_int_const(%s);' % name) prnt(' if (o == NULL)') prnt(' return -1;') if size_too: prnt(' {') prnt(' PyObject *o1 = o;') prnt(' o = Py_BuildValue("On", o1, (Py_ssize_t)sizeof(%s));' % (name,)) prnt(' Py_DECREF(o1);') prnt(' if (o == NULL)') prnt(' return -1;') prnt(' }') prnt(' res = PyObject_SetAttrString(lib, "%s", o);' % name) prnt(' Py_DECREF(o);') prnt(' if (res < 0)') prnt(' return -1;') prnt(' return %s;' % self._chained_list_constants[delayed]) self._chained_list_constants[delayed] = funcname + '(lib)' prnt('}') prnt() def _generate_cpy_constant_collecttype(self, tp, name): is_int = isinstance(tp, model.PrimitiveType) and tp.is_integer_type() if not is_int: self._do_collect_type(tp) def _generate_cpy_constant_decl(self, tp, name): is_int = isinstance(tp, model.PrimitiveType) and tp.is_integer_type() self._generate_cpy_const(is_int, name, tp) _generate_cpy_constant_method = _generate_nothing _loading_cpy_constant = _loaded_noop _loaded_cpy_constant = _loaded_noop # ---------- # enums def _check_int_constant_value(self, name, value, err_prefix=''): prnt = self._prnt if value <= 0: prnt(' if ((%s) > 0 || (long)(%s) != %dL) {' % ( name, name, value)) else: prnt(' if ((%s) <= 0 || (unsigned long)(%s) != %dUL) {' % ( name, name, value)) prnt(' char buf[64];') prnt(' if ((%s) <= 0)' % name) prnt(' snprintf(buf, 63, "%%ld", (long)(%s));' % name) prnt(' else') prnt(' snprintf(buf, 63, "%%lu", (unsigned long)(%s));' % name) prnt(' PyErr_Format(_cffi_VerificationError,') prnt(' "%s%s has the real value %s, not %s",') prnt(' "%s", "%s", buf, "%d");' % ( err_prefix, name, value)) prnt(' return -1;') prnt(' }') def _enum_funcname(self, prefix, name): # "$enum_$1" => "___D_enum____D_1" name = name.replace('$', '___D_') return '_cffi_e_%s_%s' % (prefix, name) def _generate_cpy_enum_decl(self, tp, name, prefix='enum'): if tp.partial: for enumerator in tp.enumerators: self._generate_cpy_const(True, enumerator, delayed=False) return # funcname = self._enum_funcname(prefix, name) prnt = self._prnt prnt('static int %s(PyObject *lib)' % funcname) prnt('{') for enumerator, enumvalue in zip(tp.enumerators, tp.enumvalues): self._check_int_constant_value(enumerator, enumvalue, "enum %s: " % name) prnt(' return %s;' % self._chained_list_constants[True]) self._chained_list_constants[True] = funcname + '(lib)' prnt('}') prnt() _generate_cpy_enum_collecttype = _generate_nothing _generate_cpy_enum_method = _generate_nothing def _loading_cpy_enum(self, tp, name, module): if tp.partial: enumvalues = [getattr(module, enumerator) for enumerator in tp.enumerators] tp.enumvalues = tuple(enumvalues) tp.partial_resolved = True def _loaded_cpy_enum(self, tp, name, module, library): for enumerator, enumvalue in zip(tp.enumerators, tp.enumvalues): setattr(library, enumerator, enumvalue) # ---------- # macros: for now only for integers def _generate_cpy_macro_decl(self, tp, name): if tp == '...': check_value = None else: check_value = tp # an integer self._generate_cpy_const(True, name, check_value=check_value) _generate_cpy_macro_collecttype = _generate_nothing _generate_cpy_macro_method = _generate_nothing _loading_cpy_macro = _loaded_noop _loaded_cpy_macro = _loaded_noop # ---------- # global variables def _generate_cpy_variable_collecttype(self, tp, name): if isinstance(tp, model.ArrayType): tp_ptr = model.PointerType(tp.item) else: tp_ptr = model.PointerType(tp) self._do_collect_type(tp_ptr) def _generate_cpy_variable_decl(self, tp, name): if isinstance(tp, model.ArrayType): tp_ptr = model.PointerType(tp.item) self._generate_cpy_const(False, name, tp, vartp=tp_ptr, size_too = (tp.length == '...')) else: tp_ptr = model.PointerType(tp) self._generate_cpy_const(False, name, tp_ptr, category='var') _generate_cpy_variable_method = _generate_nothing _loading_cpy_variable = _loaded_noop def _loaded_cpy_variable(self, tp, name, module, library): value = getattr(library, name) if isinstance(tp, model.ArrayType): # int a[5] is "constant" in the # sense that "a=..." is forbidden if tp.length == '...': assert isinstance(value, tuple) (value, size) = value BItemType = self.ffi._get_cached_btype(tp.item) length, rest = divmod(size, self.ffi.sizeof(BItemType)) if rest != 0: raise VerificationError( "bad size: %r does not seem to be an array of %s" % (name, tp.item)) tp = tp.resolve_length(length) # 'value' is a which we have to replace with # a if the N is actually known if tp.length is not None: BArray = self.ffi._get_cached_btype(tp) value = self.ffi.cast(BArray, value) setattr(library, name, value) return # remove ptr= from the library instance, and replace # it by a property on the class, which reads/writes into ptr[0]. ptr = value delattr(library, name) def getter(library): return ptr[0] def setter(library, value): ptr[0] = value setattr(type(library), name, property(getter, setter)) type(library)._cffi_dir.append(name) # ---------- def _generate_setup_custom(self): prnt = self._prnt prnt('static int _cffi_setup_custom(PyObject *lib)') prnt('{') prnt(' return %s;' % self._chained_list_constants[True]) prnt('}') cffimod_header = r''' #include #include /* this block of #ifs should be kept exactly identical between c/_cffi_backend.c, cffi/vengine_cpy.py, cffi/vengine_gen.py and cffi/_cffi_include.h */ #if defined(_MSC_VER) # include /* for alloca() */ # if _MSC_VER < 1600 /* MSVC < 2010 */ typedef __int8 int8_t; typedef __int16 int16_t; typedef __int32 int32_t; typedef __int64 int64_t; typedef unsigned __int8 uint8_t; typedef unsigned __int16 uint16_t; typedef unsigned __int32 uint32_t; typedef unsigned __int64 uint64_t; typedef __int8 int_least8_t; typedef __int16 int_least16_t; typedef __int32 int_least32_t; typedef __int64 int_least64_t; typedef unsigned __int8 uint_least8_t; typedef unsigned __int16 uint_least16_t; typedef unsigned __int32 uint_least32_t; typedef unsigned __int64 uint_least64_t; typedef __int8 int_fast8_t; typedef __int16 int_fast16_t; typedef __int32 int_fast32_t; typedef __int64 int_fast64_t; typedef unsigned __int8 uint_fast8_t; typedef unsigned __int16 uint_fast16_t; typedef unsigned __int32 uint_fast32_t; typedef unsigned __int64 uint_fast64_t; typedef __int64 intmax_t; typedef unsigned __int64 uintmax_t; # else # include # endif # if _MSC_VER < 1800 /* MSVC < 2013 */ # ifndef __cplusplus typedef unsigned char _Bool; # endif # endif #else # include # if (defined (__SVR4) && defined (__sun)) || defined(_AIX) || defined(__hpux) # include # endif #endif #if PY_MAJOR_VERSION < 3 # undef PyCapsule_CheckExact # undef PyCapsule_GetPointer # define PyCapsule_CheckExact(capsule) (PyCObject_Check(capsule)) # define PyCapsule_GetPointer(capsule, name) \ (PyCObject_AsVoidPtr(capsule)) #endif #if PY_MAJOR_VERSION >= 3 # define PyInt_FromLong PyLong_FromLong #endif #define _cffi_from_c_double PyFloat_FromDouble #define _cffi_from_c_float PyFloat_FromDouble #define _cffi_from_c_long PyInt_FromLong #define _cffi_from_c_ulong PyLong_FromUnsignedLong #define _cffi_from_c_longlong PyLong_FromLongLong #define _cffi_from_c_ulonglong PyLong_FromUnsignedLongLong #define _cffi_from_c__Bool PyBool_FromLong #define _cffi_to_c_double PyFloat_AsDouble #define _cffi_to_c_float PyFloat_AsDouble #define _cffi_from_c_int_const(x) \ (((x) > 0) ? \ ((unsigned long long)(x) <= (unsigned long long)LONG_MAX) ? \ PyInt_FromLong((long)(x)) : \ PyLong_FromUnsignedLongLong((unsigned long long)(x)) : \ ((long long)(x) >= (long long)LONG_MIN) ? \ PyInt_FromLong((long)(x)) : \ PyLong_FromLongLong((long long)(x))) #define _cffi_from_c_int(x, type) \ (((type)-1) > 0 ? /* unsigned */ \ (sizeof(type) < sizeof(long) ? \ PyInt_FromLong((long)x) : \ sizeof(type) == sizeof(long) ? \ PyLong_FromUnsignedLong((unsigned long)x) : \ PyLong_FromUnsignedLongLong((unsigned long long)x)) : \ (sizeof(type) <= sizeof(long) ? \ PyInt_FromLong((long)x) : \ PyLong_FromLongLong((long long)x))) #define _cffi_to_c_int(o, type) \ ((type)( \ sizeof(type) == 1 ? (((type)-1) > 0 ? (type)_cffi_to_c_u8(o) \ : (type)_cffi_to_c_i8(o)) : \ sizeof(type) == 2 ? (((type)-1) > 0 ? (type)_cffi_to_c_u16(o) \ : (type)_cffi_to_c_i16(o)) : \ sizeof(type) == 4 ? (((type)-1) > 0 ? (type)_cffi_to_c_u32(o) \ : (type)_cffi_to_c_i32(o)) : \ sizeof(type) == 8 ? (((type)-1) > 0 ? (type)_cffi_to_c_u64(o) \ : (type)_cffi_to_c_i64(o)) : \ (Py_FatalError("unsupported size for type " #type), (type)0))) #define _cffi_to_c_i8 \ ((int(*)(PyObject *))_cffi_exports[1]) #define _cffi_to_c_u8 \ ((int(*)(PyObject *))_cffi_exports[2]) #define _cffi_to_c_i16 \ ((int(*)(PyObject *))_cffi_exports[3]) #define _cffi_to_c_u16 \ ((int(*)(PyObject *))_cffi_exports[4]) #define _cffi_to_c_i32 \ ((int(*)(PyObject *))_cffi_exports[5]) #define _cffi_to_c_u32 \ ((unsigned int(*)(PyObject *))_cffi_exports[6]) #define _cffi_to_c_i64 \ ((long long(*)(PyObject *))_cffi_exports[7]) #define _cffi_to_c_u64 \ ((unsigned long long(*)(PyObject *))_cffi_exports[8]) #define _cffi_to_c_char \ ((int(*)(PyObject *))_cffi_exports[9]) #define _cffi_from_c_pointer \ ((PyObject *(*)(char *, CTypeDescrObject *))_cffi_exports[10]) #define _cffi_to_c_pointer \ ((char *(*)(PyObject *, CTypeDescrObject *))_cffi_exports[11]) #define _cffi_get_struct_layout \ ((PyObject *(*)(Py_ssize_t[]))_cffi_exports[12]) #define _cffi_restore_errno \ ((void(*)(void))_cffi_exports[13]) #define _cffi_save_errno \ ((void(*)(void))_cffi_exports[14]) #define _cffi_from_c_char \ ((PyObject *(*)(char))_cffi_exports[15]) #define _cffi_from_c_deref \ ((PyObject *(*)(char *, CTypeDescrObject *))_cffi_exports[16]) #define _cffi_to_c \ ((int(*)(char *, CTypeDescrObject *, PyObject *))_cffi_exports[17]) #define _cffi_from_c_struct \ ((PyObject *(*)(char *, CTypeDescrObject *))_cffi_exports[18]) #define _cffi_to_c_wchar_t \ ((wchar_t(*)(PyObject *))_cffi_exports[19]) #define _cffi_from_c_wchar_t \ ((PyObject *(*)(wchar_t))_cffi_exports[20]) #define _cffi_to_c_long_double \ ((long double(*)(PyObject *))_cffi_exports[21]) #define _cffi_to_c__Bool \ ((_Bool(*)(PyObject *))_cffi_exports[22]) #define _cffi_prepare_pointer_call_argument \ ((Py_ssize_t(*)(CTypeDescrObject *, PyObject *, char **))_cffi_exports[23]) #define _cffi_convert_array_from_object \ ((int(*)(char *, CTypeDescrObject *, PyObject *))_cffi_exports[24]) #define _CFFI_NUM_EXPORTS 25 typedef struct _ctypedescr CTypeDescrObject; static void *_cffi_exports[_CFFI_NUM_EXPORTS]; static PyObject *_cffi_types, *_cffi_VerificationError; static int _cffi_setup_custom(PyObject *lib); /* forward */ static PyObject *_cffi_setup(PyObject *self, PyObject *args) { PyObject *library; int was_alive = (_cffi_types != NULL); (void)self; /* unused */ if (!PyArg_ParseTuple(args, "OOO", &_cffi_types, &_cffi_VerificationError, &library)) return NULL; Py_INCREF(_cffi_types); Py_INCREF(_cffi_VerificationError); if (_cffi_setup_custom(library) < 0) return NULL; return PyBool_FromLong(was_alive); } static int _cffi_init(void) { PyObject *module, *c_api_object = NULL; module = PyImport_ImportModule("_cffi_backend"); if (module == NULL) goto failure; c_api_object = PyObject_GetAttrString(module, "_C_API"); if (c_api_object == NULL) goto failure; if (!PyCapsule_CheckExact(c_api_object)) { PyErr_SetNone(PyExc_ImportError); goto failure; } memcpy(_cffi_exports, PyCapsule_GetPointer(c_api_object, "cffi"), _CFFI_NUM_EXPORTS * sizeof(void *)); Py_DECREF(module); Py_DECREF(c_api_object); return 0; failure: Py_XDECREF(module); Py_XDECREF(c_api_object); return -1; } #define _cffi_type(num) ((CTypeDescrObject *)PyList_GET_ITEM(_cffi_types, num)) /**********/ ''' ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/cffi/vengine_gen.py ================================================ # # DEPRECATED: implementation for ffi.verify() # import sys, os import types from . import model from .error import VerificationError class VGenericEngine(object): _class_key = 'g' _gen_python_module = False def __init__(self, verifier): self.verifier = verifier self.ffi = verifier.ffi self.export_symbols = [] self._struct_pending_verification = {} def patch_extension_kwds(self, kwds): # add 'export_symbols' to the dictionary. Note that we add the # list before filling it. When we fill it, it will thus also show # up in kwds['export_symbols']. kwds.setdefault('export_symbols', self.export_symbols) def find_module(self, module_name, path, so_suffixes): for so_suffix in so_suffixes: basename = module_name + so_suffix if path is None: path = sys.path for dirname in path: filename = os.path.join(dirname, basename) if os.path.isfile(filename): return filename def collect_types(self): pass # not needed in the generic engine def _prnt(self, what=''): self._f.write(what + '\n') def write_source_to_f(self): prnt = self._prnt # first paste some standard set of lines that are mostly '#include' prnt(cffimod_header) # then paste the C source given by the user, verbatim. prnt(self.verifier.preamble) # # call generate_gen_xxx_decl(), for every xxx found from # ffi._parser._declarations. This generates all the functions. self._generate('decl') # # on Windows, distutils insists on putting init_cffi_xyz in # 'export_symbols', so instead of fighting it, just give up and # give it one if sys.platform == 'win32': if sys.version_info >= (3,): prefix = 'PyInit_' else: prefix = 'init' modname = self.verifier.get_module_name() prnt("void %s%s(void) { }\n" % (prefix, modname)) def load_library(self, flags=0): # import it with the CFFI backend backend = self.ffi._backend # needs to make a path that contains '/', on Posix filename = os.path.join(os.curdir, self.verifier.modulefilename) module = backend.load_library(filename, flags) # # call loading_gen_struct() to get the struct layout inferred by # the C compiler self._load(module, 'loading') # build the FFILibrary class and instance, this is a module subclass # because modules are expected to have usually-constant-attributes and # in PyPy this means the JIT is able to treat attributes as constant, # which we want. class FFILibrary(types.ModuleType): _cffi_generic_module = module _cffi_ffi = self.ffi _cffi_dir = [] def __dir__(self): return FFILibrary._cffi_dir library = FFILibrary("") # # finally, call the loaded_gen_xxx() functions. This will set # up the 'library' object. self._load(module, 'loaded', library=library) return library def _get_declarations(self): lst = [(key, tp) for (key, (tp, qual)) in self.ffi._parser._declarations.items()] lst.sort() return lst def _generate(self, step_name): for name, tp in self._get_declarations(): kind, realname = name.split(' ', 1) try: method = getattr(self, '_generate_gen_%s_%s' % (kind, step_name)) except AttributeError: raise VerificationError( "not implemented in verify(): %r" % name) try: method(tp, realname) except Exception as e: model.attach_exception_info(e, name) raise def _load(self, module, step_name, **kwds): for name, tp in self._get_declarations(): kind, realname = name.split(' ', 1) method = getattr(self, '_%s_gen_%s' % (step_name, kind)) try: method(tp, realname, module, **kwds) except Exception as e: model.attach_exception_info(e, name) raise def _generate_nothing(self, tp, name): pass def _loaded_noop(self, tp, name, module, **kwds): pass # ---------- # typedefs: generates no code so far _generate_gen_typedef_decl = _generate_nothing _loading_gen_typedef = _loaded_noop _loaded_gen_typedef = _loaded_noop # ---------- # function declarations def _generate_gen_function_decl(self, tp, name): assert isinstance(tp, model.FunctionPtrType) if tp.ellipsis: # cannot support vararg functions better than this: check for its # exact type (including the fixed arguments), and build it as a # constant function pointer (no _cffi_f_%s wrapper) self._generate_gen_const(False, name, tp) return prnt = self._prnt numargs = len(tp.args) argnames = [] for i, type in enumerate(tp.args): indirection = '' if isinstance(type, model.StructOrUnion): indirection = '*' argnames.append('%sx%d' % (indirection, i)) context = 'argument of %s' % name arglist = [type.get_c_name(' %s' % arg, context) for type, arg in zip(tp.args, argnames)] tpresult = tp.result if isinstance(tpresult, model.StructOrUnion): arglist.insert(0, tpresult.get_c_name(' *r', context)) tpresult = model.void_type arglist = ', '.join(arglist) or 'void' wrappername = '_cffi_f_%s' % name self.export_symbols.append(wrappername) if tp.abi: abi = tp.abi + ' ' else: abi = '' funcdecl = ' %s%s(%s)' % (abi, wrappername, arglist) context = 'result of %s' % name prnt(tpresult.get_c_name(funcdecl, context)) prnt('{') # if isinstance(tp.result, model.StructOrUnion): result_code = '*r = ' elif not isinstance(tp.result, model.VoidType): result_code = 'return ' else: result_code = '' prnt(' %s%s(%s);' % (result_code, name, ', '.join(argnames))) prnt('}') prnt() _loading_gen_function = _loaded_noop def _loaded_gen_function(self, tp, name, module, library): assert isinstance(tp, model.FunctionPtrType) if tp.ellipsis: newfunction = self._load_constant(False, tp, name, module) else: indirections = [] base_tp = tp if (any(isinstance(typ, model.StructOrUnion) for typ in tp.args) or isinstance(tp.result, model.StructOrUnion)): indirect_args = [] for i, typ in enumerate(tp.args): if isinstance(typ, model.StructOrUnion): typ = model.PointerType(typ) indirections.append((i, typ)) indirect_args.append(typ) indirect_result = tp.result if isinstance(indirect_result, model.StructOrUnion): if indirect_result.fldtypes is None: raise TypeError("'%s' is used as result type, " "but is opaque" % ( indirect_result._get_c_name(),)) indirect_result = model.PointerType(indirect_result) indirect_args.insert(0, indirect_result) indirections.insert(0, ("result", indirect_result)) indirect_result = model.void_type tp = model.FunctionPtrType(tuple(indirect_args), indirect_result, tp.ellipsis) BFunc = self.ffi._get_cached_btype(tp) wrappername = '_cffi_f_%s' % name newfunction = module.load_function(BFunc, wrappername) for i, typ in indirections: newfunction = self._make_struct_wrapper(newfunction, i, typ, base_tp) setattr(library, name, newfunction) type(library)._cffi_dir.append(name) def _make_struct_wrapper(self, oldfunc, i, tp, base_tp): backend = self.ffi._backend BType = self.ffi._get_cached_btype(tp) if i == "result": ffi = self.ffi def newfunc(*args): res = ffi.new(BType) oldfunc(res, *args) return res[0] else: def newfunc(*args): args = args[:i] + (backend.newp(BType, args[i]),) + args[i+1:] return oldfunc(*args) newfunc._cffi_base_type = base_tp return newfunc # ---------- # named structs def _generate_gen_struct_decl(self, tp, name): assert name == tp.name self._generate_struct_or_union_decl(tp, 'struct', name) def _loading_gen_struct(self, tp, name, module): self._loading_struct_or_union(tp, 'struct', name, module) def _loaded_gen_struct(self, tp, name, module, **kwds): self._loaded_struct_or_union(tp) def _generate_gen_union_decl(self, tp, name): assert name == tp.name self._generate_struct_or_union_decl(tp, 'union', name) def _loading_gen_union(self, tp, name, module): self._loading_struct_or_union(tp, 'union', name, module) def _loaded_gen_union(self, tp, name, module, **kwds): self._loaded_struct_or_union(tp) def _generate_struct_or_union_decl(self, tp, prefix, name): if tp.fldnames is None: return # nothing to do with opaque structs checkfuncname = '_cffi_check_%s_%s' % (prefix, name) layoutfuncname = '_cffi_layout_%s_%s' % (prefix, name) cname = ('%s %s' % (prefix, name)).strip() # prnt = self._prnt prnt('static void %s(%s *p)' % (checkfuncname, cname)) prnt('{') prnt(' /* only to generate compile-time warnings or errors */') prnt(' (void)p;') for fname, ftype, fbitsize, fqual in tp.enumfields(): if (isinstance(ftype, model.PrimitiveType) and ftype.is_integer_type()) or fbitsize >= 0: # accept all integers, but complain on float or double prnt(' (void)((p->%s) << 1);' % fname) else: # only accept exactly the type declared. try: prnt(' { %s = &p->%s; (void)tmp; }' % ( ftype.get_c_name('*tmp', 'field %r'%fname, quals=fqual), fname)) except VerificationError as e: prnt(' /* %s */' % str(e)) # cannot verify it, ignore prnt('}') self.export_symbols.append(layoutfuncname) prnt('intptr_t %s(intptr_t i)' % (layoutfuncname,)) prnt('{') prnt(' struct _cffi_aligncheck { char x; %s y; };' % cname) prnt(' static intptr_t nums[] = {') prnt(' sizeof(%s),' % cname) prnt(' offsetof(struct _cffi_aligncheck, y),') for fname, ftype, fbitsize, fqual in tp.enumfields(): if fbitsize >= 0: continue # xxx ignore fbitsize for now prnt(' offsetof(%s, %s),' % (cname, fname)) if isinstance(ftype, model.ArrayType) and ftype.length is None: prnt(' 0, /* %s */' % ftype._get_c_name()) else: prnt(' sizeof(((%s *)0)->%s),' % (cname, fname)) prnt(' -1') prnt(' };') prnt(' return nums[i];') prnt(' /* the next line is not executed, but compiled */') prnt(' %s(0);' % (checkfuncname,)) prnt('}') prnt() def _loading_struct_or_union(self, tp, prefix, name, module): if tp.fldnames is None: return # nothing to do with opaque structs layoutfuncname = '_cffi_layout_%s_%s' % (prefix, name) # BFunc = self.ffi._typeof_locked("intptr_t(*)(intptr_t)")[0] function = module.load_function(BFunc, layoutfuncname) layout = [] num = 0 while True: x = function(num) if x < 0: break layout.append(x) num += 1 if isinstance(tp, model.StructOrUnion) and tp.partial: # use the function()'s sizes and offsets to guide the # layout of the struct totalsize = layout[0] totalalignment = layout[1] fieldofs = layout[2::2] fieldsize = layout[3::2] tp.force_flatten() assert len(fieldofs) == len(fieldsize) == len(tp.fldnames) tp.fixedlayout = fieldofs, fieldsize, totalsize, totalalignment else: cname = ('%s %s' % (prefix, name)).strip() self._struct_pending_verification[tp] = layout, cname def _loaded_struct_or_union(self, tp): if tp.fldnames is None: return # nothing to do with opaque structs self.ffi._get_cached_btype(tp) # force 'fixedlayout' to be considered if tp in self._struct_pending_verification: # check that the layout sizes and offsets match the real ones def check(realvalue, expectedvalue, msg): if realvalue != expectedvalue: raise VerificationError( "%s (we have %d, but C compiler says %d)" % (msg, expectedvalue, realvalue)) ffi = self.ffi BStruct = ffi._get_cached_btype(tp) layout, cname = self._struct_pending_verification.pop(tp) check(layout[0], ffi.sizeof(BStruct), "wrong total size") check(layout[1], ffi.alignof(BStruct), "wrong total alignment") i = 2 for fname, ftype, fbitsize, fqual in tp.enumfields(): if fbitsize >= 0: continue # xxx ignore fbitsize for now check(layout[i], ffi.offsetof(BStruct, fname), "wrong offset for field %r" % (fname,)) if layout[i+1] != 0: BField = ffi._get_cached_btype(ftype) check(layout[i+1], ffi.sizeof(BField), "wrong size for field %r" % (fname,)) i += 2 assert i == len(layout) # ---------- # 'anonymous' declarations. These are produced for anonymous structs # or unions; the 'name' is obtained by a typedef. def _generate_gen_anonymous_decl(self, tp, name): if isinstance(tp, model.EnumType): self._generate_gen_enum_decl(tp, name, '') else: self._generate_struct_or_union_decl(tp, '', name) def _loading_gen_anonymous(self, tp, name, module): if isinstance(tp, model.EnumType): self._loading_gen_enum(tp, name, module, '') else: self._loading_struct_or_union(tp, '', name, module) def _loaded_gen_anonymous(self, tp, name, module, **kwds): if isinstance(tp, model.EnumType): self._loaded_gen_enum(tp, name, module, **kwds) else: self._loaded_struct_or_union(tp) # ---------- # constants, likely declared with '#define' def _generate_gen_const(self, is_int, name, tp=None, category='const', check_value=None): prnt = self._prnt funcname = '_cffi_%s_%s' % (category, name) self.export_symbols.append(funcname) if check_value is not None: assert is_int assert category == 'const' prnt('int %s(char *out_error)' % funcname) prnt('{') self._check_int_constant_value(name, check_value) prnt(' return 0;') prnt('}') elif is_int: assert category == 'const' prnt('int %s(long long *out_value)' % funcname) prnt('{') prnt(' *out_value = (long long)(%s);' % (name,)) prnt(' return (%s) <= 0;' % (name,)) prnt('}') else: assert tp is not None assert check_value is None if category == 'var': ampersand = '&' else: ampersand = '' extra = '' if category == 'const' and isinstance(tp, model.StructOrUnion): extra = 'const *' ampersand = '&' prnt(tp.get_c_name(' %s%s(void)' % (extra, funcname), name)) prnt('{') prnt(' return (%s%s);' % (ampersand, name)) prnt('}') prnt() def _generate_gen_constant_decl(self, tp, name): is_int = isinstance(tp, model.PrimitiveType) and tp.is_integer_type() self._generate_gen_const(is_int, name, tp) _loading_gen_constant = _loaded_noop def _load_constant(self, is_int, tp, name, module, check_value=None): funcname = '_cffi_const_%s' % name if check_value is not None: assert is_int self._load_known_int_constant(module, funcname) value = check_value elif is_int: BType = self.ffi._typeof_locked("long long*")[0] BFunc = self.ffi._typeof_locked("int(*)(long long*)")[0] function = module.load_function(BFunc, funcname) p = self.ffi.new(BType) negative = function(p) value = int(p[0]) if value < 0 and not negative: BLongLong = self.ffi._typeof_locked("long long")[0] value += (1 << (8*self.ffi.sizeof(BLongLong))) else: assert check_value is None fntypeextra = '(*)(void)' if isinstance(tp, model.StructOrUnion): fntypeextra = '*' + fntypeextra BFunc = self.ffi._typeof_locked(tp.get_c_name(fntypeextra, name))[0] function = module.load_function(BFunc, funcname) value = function() if isinstance(tp, model.StructOrUnion): value = value[0] return value def _loaded_gen_constant(self, tp, name, module, library): is_int = isinstance(tp, model.PrimitiveType) and tp.is_integer_type() value = self._load_constant(is_int, tp, name, module) setattr(library, name, value) type(library)._cffi_dir.append(name) # ---------- # enums def _check_int_constant_value(self, name, value): prnt = self._prnt if value <= 0: prnt(' if ((%s) > 0 || (long)(%s) != %dL) {' % ( name, name, value)) else: prnt(' if ((%s) <= 0 || (unsigned long)(%s) != %dUL) {' % ( name, name, value)) prnt(' char buf[64];') prnt(' if ((%s) <= 0)' % name) prnt(' sprintf(buf, "%%ld", (long)(%s));' % name) prnt(' else') prnt(' sprintf(buf, "%%lu", (unsigned long)(%s));' % name) prnt(' sprintf(out_error, "%s has the real value %s, not %s",') prnt(' "%s", buf, "%d");' % (name[:100], value)) prnt(' return -1;') prnt(' }') def _load_known_int_constant(self, module, funcname): BType = self.ffi._typeof_locked("char[]")[0] BFunc = self.ffi._typeof_locked("int(*)(char*)")[0] function = module.load_function(BFunc, funcname) p = self.ffi.new(BType, 256) if function(p) < 0: error = self.ffi.string(p) if sys.version_info >= (3,): error = str(error, 'utf-8') raise VerificationError(error) def _enum_funcname(self, prefix, name): # "$enum_$1" => "___D_enum____D_1" name = name.replace('$', '___D_') return '_cffi_e_%s_%s' % (prefix, name) def _generate_gen_enum_decl(self, tp, name, prefix='enum'): if tp.partial: for enumerator in tp.enumerators: self._generate_gen_const(True, enumerator) return # funcname = self._enum_funcname(prefix, name) self.export_symbols.append(funcname) prnt = self._prnt prnt('int %s(char *out_error)' % funcname) prnt('{') for enumerator, enumvalue in zip(tp.enumerators, tp.enumvalues): self._check_int_constant_value(enumerator, enumvalue) prnt(' return 0;') prnt('}') prnt() def _loading_gen_enum(self, tp, name, module, prefix='enum'): if tp.partial: enumvalues = [self._load_constant(True, tp, enumerator, module) for enumerator in tp.enumerators] tp.enumvalues = tuple(enumvalues) tp.partial_resolved = True else: funcname = self._enum_funcname(prefix, name) self._load_known_int_constant(module, funcname) def _loaded_gen_enum(self, tp, name, module, library): for enumerator, enumvalue in zip(tp.enumerators, tp.enumvalues): setattr(library, enumerator, enumvalue) type(library)._cffi_dir.append(enumerator) # ---------- # macros: for now only for integers def _generate_gen_macro_decl(self, tp, name): if tp == '...': check_value = None else: check_value = tp # an integer self._generate_gen_const(True, name, check_value=check_value) _loading_gen_macro = _loaded_noop def _loaded_gen_macro(self, tp, name, module, library): if tp == '...': check_value = None else: check_value = tp # an integer value = self._load_constant(True, tp, name, module, check_value=check_value) setattr(library, name, value) type(library)._cffi_dir.append(name) # ---------- # global variables def _generate_gen_variable_decl(self, tp, name): if isinstance(tp, model.ArrayType): if tp.length == '...': prnt = self._prnt funcname = '_cffi_sizeof_%s' % (name,) self.export_symbols.append(funcname) prnt("size_t %s(void)" % funcname) prnt("{") prnt(" return sizeof(%s);" % (name,)) prnt("}") tp_ptr = model.PointerType(tp.item) self._generate_gen_const(False, name, tp_ptr) else: tp_ptr = model.PointerType(tp) self._generate_gen_const(False, name, tp_ptr, category='var') _loading_gen_variable = _loaded_noop def _loaded_gen_variable(self, tp, name, module, library): if isinstance(tp, model.ArrayType): # int a[5] is "constant" in the # sense that "a=..." is forbidden if tp.length == '...': funcname = '_cffi_sizeof_%s' % (name,) BFunc = self.ffi._typeof_locked('size_t(*)(void)')[0] function = module.load_function(BFunc, funcname) size = function() BItemType = self.ffi._get_cached_btype(tp.item) length, rest = divmod(size, self.ffi.sizeof(BItemType)) if rest != 0: raise VerificationError( "bad size: %r does not seem to be an array of %s" % (name, tp.item)) tp = tp.resolve_length(length) tp_ptr = model.PointerType(tp.item) value = self._load_constant(False, tp_ptr, name, module) # 'value' is a which we have to replace with # a if the N is actually known if tp.length is not None: BArray = self.ffi._get_cached_btype(tp) value = self.ffi.cast(BArray, value) setattr(library, name, value) type(library)._cffi_dir.append(name) return # remove ptr= from the library instance, and replace # it by a property on the class, which reads/writes into ptr[0]. funcname = '_cffi_var_%s' % name BFunc = self.ffi._typeof_locked(tp.get_c_name('*(*)(void)', name))[0] function = module.load_function(BFunc, funcname) ptr = function() def getter(library): return ptr[0] def setter(library, value): ptr[0] = value setattr(type(library), name, property(getter, setter)) type(library)._cffi_dir.append(name) cffimod_header = r''' #include #include #include #include #include /* XXX for ssize_t on some platforms */ /* this block of #ifs should be kept exactly identical between c/_cffi_backend.c, cffi/vengine_cpy.py, cffi/vengine_gen.py and cffi/_cffi_include.h */ #if defined(_MSC_VER) # include /* for alloca() */ # if _MSC_VER < 1600 /* MSVC < 2010 */ typedef __int8 int8_t; typedef __int16 int16_t; typedef __int32 int32_t; typedef __int64 int64_t; typedef unsigned __int8 uint8_t; typedef unsigned __int16 uint16_t; typedef unsigned __int32 uint32_t; typedef unsigned __int64 uint64_t; typedef __int8 int_least8_t; typedef __int16 int_least16_t; typedef __int32 int_least32_t; typedef __int64 int_least64_t; typedef unsigned __int8 uint_least8_t; typedef unsigned __int16 uint_least16_t; typedef unsigned __int32 uint_least32_t; typedef unsigned __int64 uint_least64_t; typedef __int8 int_fast8_t; typedef __int16 int_fast16_t; typedef __int32 int_fast32_t; typedef __int64 int_fast64_t; typedef unsigned __int8 uint_fast8_t; typedef unsigned __int16 uint_fast16_t; typedef unsigned __int32 uint_fast32_t; typedef unsigned __int64 uint_fast64_t; typedef __int64 intmax_t; typedef unsigned __int64 uintmax_t; # else # include # endif # if _MSC_VER < 1800 /* MSVC < 2013 */ # ifndef __cplusplus typedef unsigned char _Bool; # endif # endif #else # include # if (defined (__SVR4) && defined (__sun)) || defined(_AIX) || defined(__hpux) # include # endif #endif ''' ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/cffi/verifier.py ================================================ # # DEPRECATED: implementation for ffi.verify() # import sys, os, binascii, shutil, io from . import __version_verifier_modules__ from . import ffiplatform from .error import VerificationError if sys.version_info >= (3, 3): import importlib.machinery def _extension_suffixes(): return importlib.machinery.EXTENSION_SUFFIXES[:] else: import imp def _extension_suffixes(): return [suffix for suffix, _, type in imp.get_suffixes() if type == imp.C_EXTENSION] if sys.version_info >= (3,): NativeIO = io.StringIO else: class NativeIO(io.BytesIO): def write(self, s): if isinstance(s, unicode): s = s.encode('ascii') super(NativeIO, self).write(s) class Verifier(object): def __init__(self, ffi, preamble, tmpdir=None, modulename=None, ext_package=None, tag='', force_generic_engine=False, source_extension='.c', flags=None, relative_to=None, **kwds): if ffi._parser._uses_new_feature: raise VerificationError( "feature not supported with ffi.verify(), but only " "with ffi.set_source(): %s" % (ffi._parser._uses_new_feature,)) self.ffi = ffi self.preamble = preamble if not modulename: flattened_kwds = ffiplatform.flatten(kwds) vengine_class = _locate_engine_class(ffi, force_generic_engine) self._vengine = vengine_class(self) self._vengine.patch_extension_kwds(kwds) self.flags = flags self.kwds = self.make_relative_to(kwds, relative_to) # if modulename: if tag: raise TypeError("can't specify both 'modulename' and 'tag'") else: key = '\x00'.join([sys.version[:3], __version_verifier_modules__, preamble, flattened_kwds] + ffi._cdefsources) if sys.version_info >= (3,): key = key.encode('utf-8') k1 = hex(binascii.crc32(key[0::2]) & 0xffffffff) k1 = k1.lstrip('0x').rstrip('L') k2 = hex(binascii.crc32(key[1::2]) & 0xffffffff) k2 = k2.lstrip('0').rstrip('L') modulename = '_cffi_%s_%s%s%s' % (tag, self._vengine._class_key, k1, k2) suffix = _get_so_suffixes()[0] self.tmpdir = tmpdir or _caller_dir_pycache() self.sourcefilename = os.path.join(self.tmpdir, modulename + source_extension) self.modulefilename = os.path.join(self.tmpdir, modulename + suffix) self.ext_package = ext_package self._has_source = False self._has_module = False def write_source(self, file=None): """Write the C source code. It is produced in 'self.sourcefilename', which can be tweaked beforehand.""" with self.ffi._lock: if self._has_source and file is None: raise VerificationError( "source code already written") self._write_source(file) def compile_module(self): """Write the C source code (if not done already) and compile it. This produces a dynamic link library in 'self.modulefilename'.""" with self.ffi._lock: if self._has_module: raise VerificationError("module already compiled") if not self._has_source: self._write_source() self._compile_module() def load_library(self): """Get a C module from this Verifier instance. Returns an instance of a FFILibrary class that behaves like the objects returned by ffi.dlopen(), but that delegates all operations to the C module. If necessary, the C code is written and compiled first. """ with self.ffi._lock: if not self._has_module: self._locate_module() if not self._has_module: if not self._has_source: self._write_source() self._compile_module() return self._load_library() def get_module_name(self): basename = os.path.basename(self.modulefilename) # kill both the .so extension and the other .'s, as introduced # by Python 3: 'basename.cpython-33m.so' basename = basename.split('.', 1)[0] # and the _d added in Python 2 debug builds --- but try to be # conservative and not kill a legitimate _d if basename.endswith('_d') and hasattr(sys, 'gettotalrefcount'): basename = basename[:-2] return basename def get_extension(self): ffiplatform._hack_at_distutils() # backward compatibility hack if not self._has_source: with self.ffi._lock: if not self._has_source: self._write_source() sourcename = ffiplatform.maybe_relative_path(self.sourcefilename) modname = self.get_module_name() return ffiplatform.get_extension(sourcename, modname, **self.kwds) def generates_python_module(self): return self._vengine._gen_python_module def make_relative_to(self, kwds, relative_to): if relative_to and os.path.dirname(relative_to): dirname = os.path.dirname(relative_to) kwds = kwds.copy() for key in ffiplatform.LIST_OF_FILE_NAMES: if key in kwds: lst = kwds[key] if not isinstance(lst, (list, tuple)): raise TypeError("keyword '%s' should be a list or tuple" % (key,)) lst = [os.path.join(dirname, fn) for fn in lst] kwds[key] = lst return kwds # ---------- def _locate_module(self): if not os.path.isfile(self.modulefilename): if self.ext_package: try: pkg = __import__(self.ext_package, None, None, ['__doc__']) except ImportError: return # cannot import the package itself, give up # (e.g. it might be called differently before installation) path = pkg.__path__ else: path = None filename = self._vengine.find_module(self.get_module_name(), path, _get_so_suffixes()) if filename is None: return self.modulefilename = filename self._vengine.collect_types() self._has_module = True def _write_source_to(self, file): self._vengine._f = file try: self._vengine.write_source_to_f() finally: del self._vengine._f def _write_source(self, file=None): if file is not None: self._write_source_to(file) else: # Write our source file to an in memory file. f = NativeIO() self._write_source_to(f) source_data = f.getvalue() # Determine if this matches the current file if os.path.exists(self.sourcefilename): with open(self.sourcefilename, "r") as fp: needs_written = not (fp.read() == source_data) else: needs_written = True # Actually write the file out if it doesn't match if needs_written: _ensure_dir(self.sourcefilename) with open(self.sourcefilename, "w") as fp: fp.write(source_data) # Set this flag self._has_source = True def _compile_module(self): # compile this C source tmpdir = os.path.dirname(self.sourcefilename) outputfilename = ffiplatform.compile(tmpdir, self.get_extension()) try: same = ffiplatform.samefile(outputfilename, self.modulefilename) except OSError: same = False if not same: _ensure_dir(self.modulefilename) shutil.move(outputfilename, self.modulefilename) self._has_module = True def _load_library(self): assert self._has_module if self.flags is not None: return self._vengine.load_library(self.flags) else: return self._vengine.load_library() # ____________________________________________________________ _FORCE_GENERIC_ENGINE = False # for tests def _locate_engine_class(ffi, force_generic_engine): if _FORCE_GENERIC_ENGINE: force_generic_engine = True if not force_generic_engine: if '__pypy__' in sys.builtin_module_names: force_generic_engine = True else: try: import _cffi_backend except ImportError: _cffi_backend = '?' if ffi._backend is not _cffi_backend: force_generic_engine = True if force_generic_engine: from . import vengine_gen return vengine_gen.VGenericEngine else: from . import vengine_cpy return vengine_cpy.VCPythonEngine # ____________________________________________________________ _TMPDIR = None def _caller_dir_pycache(): if _TMPDIR: return _TMPDIR result = os.environ.get('CFFI_TMPDIR') if result: return result filename = sys._getframe(2).f_code.co_filename return os.path.abspath(os.path.join(os.path.dirname(filename), '__pycache__')) def set_tmpdir(dirname): """Set the temporary directory to use instead of __pycache__.""" global _TMPDIR _TMPDIR = dirname def cleanup_tmpdir(tmpdir=None, keep_so=False): """Clean up the temporary directory by removing all files in it called `_cffi_*.{c,so}` as well as the `build` subdirectory.""" tmpdir = tmpdir or _caller_dir_pycache() try: filelist = os.listdir(tmpdir) except OSError: return if keep_so: suffix = '.c' # only remove .c files else: suffix = _get_so_suffixes()[0].lower() for fn in filelist: if fn.lower().startswith('_cffi_') and ( fn.lower().endswith(suffix) or fn.lower().endswith('.c')): try: os.unlink(os.path.join(tmpdir, fn)) except OSError: pass clean_dir = [os.path.join(tmpdir, 'build')] for dir in clean_dir: try: for fn in os.listdir(dir): fn = os.path.join(dir, fn) if os.path.isdir(fn): clean_dir.append(fn) else: os.unlink(fn) except OSError: pass def _get_so_suffixes(): suffixes = _extension_suffixes() if not suffixes: # bah, no C_EXTENSION available. Occurs on pypy without cpyext if sys.platform == 'win32': suffixes = [".pyd"] else: suffixes = [".so"] return suffixes def _ensure_dir(filename): dirname = os.path.dirname(filename) if dirname and not os.path.isdir(dirname): os.makedirs(dirname) ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/cffi-1.13.1.dist-info/INSTALLER ================================================ pip ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/cffi-1.13.1.dist-info/LICENSE.txt ================================================ Except when otherwise stated (look for LICENSE files in directories or information at the beginning of each file) all software and documentation is licensed as follows: The MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/cffi-1.13.1.dist-info/METADATA ================================================ Metadata-Version: 2.1 Name: cffi Version: 1.13.1 Summary: Foreign Function Interface for Python calling C code. Home-page: http://cffi.readthedocs.org Author: Armin Rigo, Maciej Fijalkowski Author-email: python-cffi@googlegroups.com License: MIT Platform: UNKNOWN Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 2 Classifier: Programming Language :: Python :: 2.6 Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: 3.2 Classifier: Programming Language :: Python :: 3.3 Classifier: Programming Language :: Python :: 3.4 Classifier: Programming Language :: Python :: 3.5 Classifier: Programming Language :: Python :: 3.6 Classifier: Programming Language :: Python :: Implementation :: CPython Classifier: Programming Language :: Python :: Implementation :: PyPy Requires-Dist: pycparser CFFI ==== Foreign Function Interface for Python calling C code. Please see the `Documentation `_. Contact ------- `Mailing list `_ ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/cffi-1.13.1.dist-info/RECORD ================================================ .libs_cffi_backend/libffi-10449faf.so.5.0.6,sha256=PG7U56gJ8uCf3HUyfp4gVBQTu7rwI2GdyE7quplTB2o,34248 _cffi_backend.cpython-36m-x86_64-linux-gnu.so,sha256=lyO5RSJGQG5eqiZKAfaFBevoOb4awoyRoAXv8qaxO0s,849704 cffi-1.13.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 cffi-1.13.1.dist-info/LICENSE.txt,sha256=BLgPWwd7vtaICM_rreteNSPyqMmpZJXFh72W3x6sKjM,1294 cffi-1.13.1.dist-info/METADATA,sha256=M7h8dR2tpB6Q5V46_Imv7Gxe7pKzA1hufeVHtu2sNAo,1140 cffi-1.13.1.dist-info/RECORD,, cffi-1.13.1.dist-info/WHEEL,sha256=d2ILPScH-y2UwGxsW1PeA2TT-KW0Git4AJ6LeOK8sQo,109 cffi-1.13.1.dist-info/entry_points.txt,sha256=Q9f5C9IpjYxo0d2PK9eUcnkgxHc9pHWwjEMaANPKNCI,76 cffi-1.13.1.dist-info/top_level.txt,sha256=rE7WR3rZfNKxWI9-jn6hsHCAl7MDkB-FmuQbxWjFehQ,19 cffi/__init__.py,sha256=vMoBBQacAlqzOsFf931EfnNqZnslrwcuaSeLUO6JTvY,513 cffi/__pycache__/__init__.cpython-36.pyc,, cffi/__pycache__/api.cpython-36.pyc,, cffi/__pycache__/backend_ctypes.cpython-36.pyc,, cffi/__pycache__/cffi_opcode.cpython-36.pyc,, cffi/__pycache__/commontypes.cpython-36.pyc,, cffi/__pycache__/cparser.cpython-36.pyc,, cffi/__pycache__/error.cpython-36.pyc,, cffi/__pycache__/ffiplatform.cpython-36.pyc,, cffi/__pycache__/lock.cpython-36.pyc,, cffi/__pycache__/model.cpython-36.pyc,, cffi/__pycache__/pkgconfig.cpython-36.pyc,, cffi/__pycache__/recompiler.cpython-36.pyc,, cffi/__pycache__/setuptools_ext.cpython-36.pyc,, cffi/__pycache__/vengine_cpy.cpython-36.pyc,, cffi/__pycache__/vengine_gen.cpython-36.pyc,, cffi/__pycache__/verifier.cpython-36.pyc,, cffi/_cffi_errors.h,sha256=6nFQ-4dRQI1bXRoSeqdvyKU33TmutQJB_2fAhWSzdl8,3856 cffi/_cffi_include.h,sha256=JuFfmwpRE65vym3Nxr9vDMOIEuv21tXdarkL1l2WNms,12149 cffi/_embedding.h,sha256=bhLhKOkF46V3C5gHLb4OkxH9pdcwMJqpjPHNDYojwbc,17411 cffi/api.py,sha256=Q07iwDD0FRwWa2fx2ZzQft69iJs9aNR52fvrtUy3EY4,41800 cffi/backend_ctypes.py,sha256=h5ZIzLc6BFVXnGyc9xPqZWUS7qGy7yFSDqXe68Sa8z4,42454 cffi/cffi_opcode.py,sha256=v9RdD_ovA8rCtqsC95Ivki5V667rAOhGgs3fb2q9xpM,5724 cffi/commontypes.py,sha256=QS4uxCDI7JhtTyjh1hlnCA-gynmaszWxJaRRLGkJa1A,2689 cffi/cparser.py,sha256=DIChXOqV-T3bZ3APc42V9zgeU0PdF4e57GU4WvIK4JQ,42079 cffi/error.py,sha256=v6xTiS4U0kvDcy4h_BDRo5v39ZQuj-IMRYLv5ETddZs,877 cffi/ffiplatform.py,sha256=HMXqR8ks2wtdsNxGaWpQ_PyqIvtiuos_vf1qKCy-cwg,4046 cffi/lock.py,sha256=l9TTdwMIMpi6jDkJGnQgE9cvTIR7CAntIJr8EGHt3pY,747 cffi/model.py,sha256=AYyjS26uiFKXtkm43qmStpy9zfGh5HVJF4UETYFBt6w,21682 cffi/parse_c_type.h,sha256=OdwQfwM9ktq6vlCB43exFQmxDBtj2MBNdK8LYl15tjw,5976 cffi/pkgconfig.py,sha256=LP1w7vmWvmKwyqLaU1Z243FOWGNQMrgMUZrvgFuOlco,4374 cffi/recompiler.py,sha256=9BR4oOQ9wFTMrp6CGa4Pa4U1pAU64Mv5-KwW5Hdn3ZM,62755 cffi/setuptools_ext.py,sha256=qc6arfrSzm4RNT5oJz6d5td7KJ-pHfI7bqYD0X4Q-08,8848 cffi/vengine_cpy.py,sha256=hdyjjZNijLrg_uGMnnFyC-7GG_LxWtwB8BlS2vvVDQ0,41470 cffi/vengine_gen.py,sha256=Zkq0-EdeZwn6qUvf_CI8iUEs2UxVIvDmKCH1j0-y0GI,26676 cffi/verifier.py,sha256=J9Enz2rbJb9CHPqWlWQ5uQESoyr0uc7MNWugchjXBv4,11207 ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/cffi-1.13.1.dist-info/WHEEL ================================================ Wheel-Version: 1.0 Generator: bdist_wheel (0.31.1) Root-Is-Purelib: false Tag: cp36-cp36m-manylinux1_x86_64 ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/cffi-1.13.1.dist-info/entry_points.txt ================================================ [distutils.setup_keywords] cffi_modules = cffi.setuptools_ext:cffi_modules ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/cffi-1.13.1.dist-info/top_level.txt ================================================ _cffi_backend cffi ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/constantly/__init__.py ================================================ # Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. from constantly._constants import ( NamedConstant, Names, ValueConstant, Values, FlagConstant, Flags ) from ._version import get_versions __version__ = get_versions()['version'] del get_versions __author__ = "Twisted Matrix Laboratories" __license__ = "MIT" __copyright__ = "Copyright 2011-2015 {0}".format(__author__) __all__ = [ 'NamedConstant', 'ValueConstant', 'FlagConstant', 'Names', 'Values', 'Flags', ] ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/constantly/_constants.py ================================================ # -*- test-case-name: constantly.test.test_constants -*- # Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. """ Symbolic constant support, including collections and constants with text, numeric, and bit flag values. """ from __future__ import division, absolute_import __all__ = [ 'NamedConstant', 'ValueConstant', 'FlagConstant', 'Names', 'Values', 'Flags'] from functools import partial from itertools import count from operator import and_, or_, xor _unspecified = object() _constantOrder = partial(next, count()) class _Constant(object): """ @ivar _index: A C{int} allocated from a shared counter in order to keep track of the order in which L{_Constant}s are instantiated. @ivar name: A C{str} giving the name of this constant; only set once the constant is initialized by L{_ConstantsContainer}. @ivar _container: The L{_ConstantsContainer} subclass this constant belongs to; C{None} until the constant is initialized by that subclass. """ def __init__(self): self._container = None self._index = _constantOrder() def __repr__(self): """ Return text identifying both which constant this is and which collection it belongs to. """ return "<%s=%s>" % (self._container.__name__, self.name) def __lt__(self, other): """ Implements C{<}. Order is defined by instantiation order. @param other: An object. @return: C{NotImplemented} if C{other} is not a constant belonging to the same container as this constant, C{True} if this constant is defined before C{other}, otherwise C{False}. """ if ( not isinstance(other, self.__class__) or not self._container == other._container ): return NotImplemented return self._index < other._index def __le__(self, other): """ Implements C{<=}. Order is defined by instantiation order. @param other: An object. @return: C{NotImplemented} if C{other} is not a constant belonging to the same container as this constant, C{True} if this constant is defined before or equal to C{other}, otherwise C{False}. """ if ( not isinstance(other, self.__class__) or not self._container == other._container ): return NotImplemented return self is other or self._index < other._index def __gt__(self, other): """ Implements C{>}. Order is defined by instantiation order. @param other: An object. @return: C{NotImplemented} if C{other} is not a constant belonging to the same container as this constant, C{True} if this constant is defined after C{other}, otherwise C{False}. """ if ( not isinstance(other, self.__class__) or not self._container == other._container ): return NotImplemented return self._index > other._index def __ge__(self, other): """ Implements C{>=}. Order is defined by instantiation order. @param other: An object. @return: C{NotImplemented} if C{other} is not a constant belonging to the same container as this constant, C{True} if this constant is defined after or equal to C{other}, otherwise C{False}. """ if ( not isinstance(other, self.__class__) or not self._container == other._container ): return NotImplemented return self is other or self._index > other._index def _realize(self, container, name, value): """ Complete the initialization of this L{_Constant}. @param container: The L{_ConstantsContainer} subclass this constant is part of. @param name: The name of this constant in its container. @param value: The value of this constant; not used, as named constants have no value apart from their identity. """ self._container = container self.name = name class _ConstantsContainerType(type): """ L{_ConstantsContainerType} is a metaclass for creating constants container classes. """ def __new__(self, name, bases, attributes): """ Create a new constants container class. If C{attributes} includes a value of C{None} for the C{"_constantType"} key, the new class will not be initialized as a constants container and it will behave as a normal class. @param name: The name of the container class. @type name: L{str} @param bases: A tuple of the base classes for the new container class. @type bases: L{tuple} of L{_ConstantsContainerType} instances @param attributes: The attributes of the new container class, including any constants it is to contain. @type attributes: L{dict} """ cls = super(_ConstantsContainerType, self).__new__( self, name, bases, attributes) # Only realize constants in concrete _ConstantsContainer subclasses. # Ignore intermediate base classes. constantType = getattr(cls, '_constantType', None) if constantType is None: return cls constants = [] for (name, descriptor) in attributes.items(): if isinstance(descriptor, cls._constantType): if descriptor._container is not None: raise ValueError( "Cannot use %s as the value of an attribute on %s" % ( descriptor, cls.__name__)) constants.append((descriptor._index, name, descriptor)) enumerants = {} for (index, enumerant, descriptor) in sorted(constants): value = cls._constantFactory(enumerant, descriptor) descriptor._realize(cls, enumerant, value) enumerants[enumerant] = descriptor # Save the dictionary which contains *only* constants (distinct from # any other attributes the application may have given the container) # where the class can use it later (eg for lookupByName). cls._enumerants = enumerants return cls # In Python3 metaclasses are defined using a C{metaclass} keyword argument in # the class definition. This would cause a syntax error in Python2. # So we use L{type} to introduce an intermediate base class with the desired # metaclass. # See: # * http://docs.python.org/2/library/functions.html#type # * http://docs.python.org/3/reference/datamodel.html#customizing-class-creation class _ConstantsContainer(_ConstantsContainerType('', (object,), {})): """ L{_ConstantsContainer} is a class with attributes used as symbolic constants. It is up to subclasses to specify what kind of constants are allowed. @cvar _constantType: Specified by a L{_ConstantsContainer} subclass to specify the type of constants allowed by that subclass. @cvar _enumerants: A C{dict} mapping the names of constants (eg L{NamedConstant} instances) found in the class definition to those instances. """ _constantType = None def __new__(cls): """ Classes representing constants containers are not intended to be instantiated. The class object itself is used directly. """ raise TypeError("%s may not be instantiated." % (cls.__name__,)) @classmethod def _constantFactory(cls, name, descriptor): """ Construct the value for a new constant to add to this container. @param name: The name of the constant to create. @param descriptor: An instance of a L{_Constant} subclass (eg L{NamedConstant}) which is assigned to C{name}. @return: L{NamedConstant} instances have no value apart from identity, so return a meaningless dummy value. """ return _unspecified @classmethod def lookupByName(cls, name): """ Retrieve a constant by its name or raise a C{ValueError} if there is no constant associated with that name. @param name: A C{str} giving the name of one of the constants defined by C{cls}. @raise ValueError: If C{name} is not the name of one of the constants defined by C{cls}. @return: The L{NamedConstant} associated with C{name}. """ if name in cls._enumerants: return getattr(cls, name) raise ValueError(name) @classmethod def iterconstants(cls): """ Iteration over a L{Names} subclass results in all of the constants it contains. @return: an iterator the elements of which are the L{NamedConstant} instances defined in the body of this L{Names} subclass. """ constants = cls._enumerants.values() return iter( sorted(constants, key=lambda descriptor: descriptor._index)) class NamedConstant(_Constant): """ L{NamedConstant} defines an attribute to be a named constant within a collection defined by a L{Names} subclass. L{NamedConstant} is only for use in the definition of L{Names} subclasses. Do not instantiate L{NamedConstant} elsewhere and do not subclass it. """ class Names(_ConstantsContainer): """ A L{Names} subclass contains constants which differ only in their names and identities. """ _constantType = NamedConstant class ValueConstant(_Constant): """ L{ValueConstant} defines an attribute to be a named constant within a collection defined by a L{Values} subclass. L{ValueConstant} is only for use in the definition of L{Values} subclasses. Do not instantiate L{ValueConstant} elsewhere and do not subclass it. """ def __init__(self, value): _Constant.__init__(self) self.value = value class Values(_ConstantsContainer): """ A L{Values} subclass contains constants which are associated with arbitrary values. """ _constantType = ValueConstant @classmethod def lookupByValue(cls, value): """ Retrieve a constant by its value or raise a C{ValueError} if there is no constant associated with that value. @param value: The value of one of the constants defined by C{cls}. @raise ValueError: If C{value} is not the value of one of the constants defined by C{cls}. @return: The L{ValueConstant} associated with C{value}. """ for constant in cls.iterconstants(): if constant.value == value: return constant raise ValueError(value) def _flagOp(op, left, right): """ Implement a binary operator for a L{FlagConstant} instance. @param op: A two-argument callable implementing the binary operation. For example, C{operator.or_}. @param left: The left-hand L{FlagConstant} instance. @param right: The right-hand L{FlagConstant} instance. @return: A new L{FlagConstant} instance representing the result of the operation. """ value = op(left.value, right.value) names = op(left.names, right.names) result = FlagConstant() result._realize(left._container, names, value) return result class FlagConstant(_Constant): """ L{FlagConstant} defines an attribute to be a flag constant within a collection defined by a L{Flags} subclass. L{FlagConstant} is only for use in the definition of L{Flags} subclasses. Do not instantiate L{FlagConstant} elsewhere and do not subclass it. """ def __init__(self, value=_unspecified): _Constant.__init__(self) self.value = value def _realize(self, container, names, value): """ Complete the initialization of this L{FlagConstant}. This implementation differs from other C{_realize} implementations in that a L{FlagConstant} may have several names which apply to it, due to flags being combined with various operators. @param container: The L{Flags} subclass this constant is part of. @param names: When a single-flag value is being initialized, a C{str} giving the name of that flag. This is the case which happens when a L{Flags} subclass is being initialized and L{FlagConstant} instances from its body are being realized. Otherwise, a C{set} of C{str} giving names of all the flags set on this L{FlagConstant} instance. This is the case when two flags are combined using C{|}, for example. """ if isinstance(names, str): name = names names = set([names]) elif len(names) == 1: (name,) = names else: name = "{" + ",".join(sorted(names)) + "}" _Constant._realize(self, container, name, value) self.value = value self.names = names def __or__(self, other): """ Define C{|} on two L{FlagConstant} instances to create a new L{FlagConstant} instance with all flags set in either instance set. """ return _flagOp(or_, self, other) def __and__(self, other): """ Define C{&} on two L{FlagConstant} instances to create a new L{FlagConstant} instance with only flags set in both instances set. """ return _flagOp(and_, self, other) def __xor__(self, other): """ Define C{^} on two L{FlagConstant} instances to create a new L{FlagConstant} instance with only flags set on exactly one instance set. """ return _flagOp(xor, self, other) def __invert__(self): """ Define C{~} on a L{FlagConstant} instance to create a new L{FlagConstant} instance with all flags not set on this instance set. """ result = FlagConstant() result._realize(self._container, set(), 0) for flag in self._container.iterconstants(): if flag.value & self.value == 0: result |= flag return result def __iter__(self): """ @return: An iterator of flags set on this instance set. """ return (self._container.lookupByName(name) for name in self.names) def __contains__(self, flag): """ @param flag: The flag to test for membership in this instance set. @return: C{True} if C{flag} is in this instance set, else C{False}. """ # Optimization for testing membership without iteration. return bool(flag & self) def __nonzero__(self): """ @return: C{False} if this flag's value is 0, else C{True}. """ return bool(self.value) __bool__ = __nonzero__ class Flags(Values): """ A L{Flags} subclass contains constants which can be combined using the common bitwise operators (C{|}, C{&}, etc) similar to a I{bitvector} from a language like C. """ _constantType = FlagConstant _value = 1 @classmethod def _constantFactory(cls, name, descriptor): """ For L{FlagConstant} instances with no explicitly defined value, assign the next power of two as its value. @param name: The name of the constant to create. @param descriptor: An instance of a L{FlagConstant} which is assigned to C{name}. @return: Either the value passed to the C{descriptor} constructor, or the next power of 2 value which will be assigned to C{descriptor}, relative to the value of the last defined L{FlagConstant}. """ if descriptor.value is _unspecified: value = cls._value cls._value <<= 1 else: value = descriptor.value cls._value = value << 1 return value ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/constantly/_version.py ================================================ # This file was generated by 'versioneer.py' (0.15) from # revision-control system data, or from the parent directory name of an # unpacked source archive. Distribution tarballs contain a pre-generated copy # of this file. import json import sys version_json = ''' { "dirty": false, "error": null, "full-revisionid": "c8375a7e3431792ea1b1b44678f3f6878d5e8c9a", "version": "15.1.0" } ''' # END VERSION_JSON def get_versions(): return json.loads(version_json) ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/constantly-15.1.0.dist-info/DESCRIPTION.rst ================================================ Constantly ========== A library that provides symbolic constant support. It includes collections and constants with text, numeric, and bit flag values. Originally ``twisted.python.constants`` from the `Twisted `_ project. Tests ----- To run tests:: $ tox This will run tests on Python 2.7, 3.3, 3.4, and PyPy, as well as doing coverage and pyflakes checks. ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/constantly-15.1.0.dist-info/INSTALLER ================================================ pip ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/constantly-15.1.0.dist-info/METADATA ================================================ Metadata-Version: 2.0 Name: constantly Version: 15.1.0 Summary: Symbolic constants in Python Home-page: https://github.com/twisted/constantly Author: Twisted Matrix Labs Developers Author-email: UNKNOWN License: MIT Keywords: constants,enum,twisted Platform: UNKNOWN Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: MIT License Classifier: Operating System :: OS Independent Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3.3 Classifier: Programming Language :: Python :: 3.4 Classifier: Programming Language :: Python :: Implementation :: CPython Classifier: Programming Language :: Python :: Implementation :: PyPy Classifier: Topic :: Software Development :: Libraries :: Python Modules Constantly ========== A library that provides symbolic constant support. It includes collections and constants with text, numeric, and bit flag values. Originally ``twisted.python.constants`` from the `Twisted `_ project. Tests ----- To run tests:: $ tox This will run tests on Python 2.7, 3.3, 3.4, and PyPy, as well as doing coverage and pyflakes checks. ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/constantly-15.1.0.dist-info/RECORD ================================================ constantly-15.1.0.dist-info/DESCRIPTION.rst,sha256=sx7cfQa9trLrI06ORsPDOgA4UkW9KdPxYfygiqt50R4,397 constantly-15.1.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 constantly-15.1.0.dist-info/METADATA,sha256=4Rt-WjQ0S-JhhzVk__zpXfYLaC7KaVjQzW9SVaBhwoY,1214 constantly-15.1.0.dist-info/RECORD,, constantly-15.1.0.dist-info/WHEEL,sha256=AvR0WeTpDaxT645bl5FQxUK6NPsTls2ttpcGJg3j1Xg,110 constantly-15.1.0.dist-info/metadata.json,sha256=y1-W-VJW79doSoMail8qNDduY5oHC2JGG1-tBZ_dA0k,923 constantly-15.1.0.dist-info/pbr.json,sha256=of4UIk4TOAoS3Gxf7oE2PwaRBcQW2ij9ZLRX1LMhy1A,47 constantly-15.1.0.dist-info/top_level.txt,sha256=Z3LZxRT3sV7OIcLddygWy8rRaguc4a1hlGotDs-vFIM,11 constantly/__init__.py,sha256=K2EFx89mIF8TkuE4F2ZhqeiE9UuB9S0DpFy0SNhu6uc,517 constantly/__pycache__/__init__.cpython-36.pyc,, constantly/__pycache__/_constants.cpython-36.pyc,, constantly/__pycache__/_version.cpython-36.pyc,, constantly/_constants.py,sha256=n-QpkK73fCIyebkqp6hvUMuEe3uYeIptBtl4KahxpcI,16090 constantly/_version.py,sha256=kp8Hoj2tpH_Xpb4CONVFfYjTpEOr3EGzNRaT_IFZ3Ao,472 ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/constantly-15.1.0.dist-info/WHEEL ================================================ Wheel-Version: 1.0 Generator: bdist_wheel (0.24.0) Root-Is-Purelib: true Tag: py2-none-any Tag: py3-none-any ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/constantly-15.1.0.dist-info/metadata.json ================================================ {"license": "MIT", "name": "constantly", "metadata_version": "2.0", "generator": "bdist_wheel (0.24.0)", "summary": "Symbolic constants in Python", "version": "15.1.0", "extensions": {"python.details": {"project_urls": {"Home": "https://github.com/twisted/constantly"}, "document_names": {"description": "DESCRIPTION.rst"}, "contacts": [{"role": "author", "name": "Twisted Matrix Labs Developers"}]}}, "keywords": ["constants", "enum", "twisted"], "classifiers": ["Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Operating System :: OS Independent", "Programming Language :: Python", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3.3", "Programming Language :: Python :: 3.4", "Programming Language :: Python :: Implementation :: CPython", "Programming Language :: Python :: Implementation :: PyPy", "Topic :: Software Development :: Libraries :: Python Modules"]} ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/constantly-15.1.0.dist-info/pbr.json ================================================ {"is_release": false, "git_version": "c8375a7"} ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/constantly-15.1.0.dist-info/top_level.txt ================================================ constantly ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/cryptography/__about__.py ================================================ # This file is dual licensed under the terms of the Apache License, Version # 2.0, and the BSD License. See the LICENSE file in the root of this repository # for complete details. from __future__ import absolute_import, division, print_function __all__ = [ "__title__", "__summary__", "__uri__", "__version__", "__author__", "__email__", "__license__", "__copyright__", ] __title__ = "cryptography" __summary__ = ("cryptography is a package which provides cryptographic recipes" " and primitives to Python developers.") __uri__ = "https://github.com/pyca/cryptography" __version__ = "2.8" __author__ = "The cryptography developers" __email__ = "cryptography-dev@python.org" __license__ = "BSD or Apache License, Version 2.0" __copyright__ = "Copyright 2013-2019 {}".format(__author__) ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/cryptography/__init__.py ================================================ # This file is dual licensed under the terms of the Apache License, Version # 2.0, and the BSD License. See the LICENSE file in the root of this repository # for complete details. from __future__ import absolute_import, division, print_function from cryptography.__about__ import ( __author__, __copyright__, __email__, __license__, __summary__, __title__, __uri__, __version__ ) __all__ = [ "__title__", "__summary__", "__uri__", "__version__", "__author__", "__email__", "__license__", "__copyright__", ] ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/cryptography/exceptions.py ================================================ # This file is dual licensed under the terms of the Apache License, Version # 2.0, and the BSD License. See the LICENSE file in the root of this repository # for complete details. from __future__ import absolute_import, division, print_function from enum import Enum class _Reasons(Enum): BACKEND_MISSING_INTERFACE = 0 UNSUPPORTED_HASH = 1 UNSUPPORTED_CIPHER = 2 UNSUPPORTED_PADDING = 3 UNSUPPORTED_MGF = 4 UNSUPPORTED_PUBLIC_KEY_ALGORITHM = 5 UNSUPPORTED_ELLIPTIC_CURVE = 6 UNSUPPORTED_SERIALIZATION = 7 UNSUPPORTED_X509 = 8 UNSUPPORTED_EXCHANGE_ALGORITHM = 9 UNSUPPORTED_DIFFIE_HELLMAN = 10 UNSUPPORTED_MAC = 11 class UnsupportedAlgorithm(Exception): def __init__(self, message, reason=None): super(UnsupportedAlgorithm, self).__init__(message) self._reason = reason class AlreadyFinalized(Exception): pass class AlreadyUpdated(Exception): pass class NotYetFinalized(Exception): pass class InvalidTag(Exception): pass class InvalidSignature(Exception): pass class InternalError(Exception): def __init__(self, msg, err_code): super(InternalError, self).__init__(msg) self.err_code = err_code class InvalidKey(Exception): pass ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/cryptography/fernet.py ================================================ # This file is dual licensed under the terms of the Apache License, Version # 2.0, and the BSD License. See the LICENSE file in the root of this repository # for complete details. from __future__ import absolute_import, division, print_function import base64 import binascii import os import struct import time import six from cryptography import utils from cryptography.exceptions import InvalidSignature from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives import hashes, padding from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes from cryptography.hazmat.primitives.hmac import HMAC class InvalidToken(Exception): pass _MAX_CLOCK_SKEW = 60 class Fernet(object): def __init__(self, key, backend=None): if backend is None: backend = default_backend() key = base64.urlsafe_b64decode(key) if len(key) != 32: raise ValueError( "Fernet key must be 32 url-safe base64-encoded bytes." ) self._signing_key = key[:16] self._encryption_key = key[16:] self._backend = backend @classmethod def generate_key(cls): return base64.urlsafe_b64encode(os.urandom(32)) def encrypt(self, data): current_time = int(time.time()) iv = os.urandom(16) return self._encrypt_from_parts(data, current_time, iv) def _encrypt_from_parts(self, data, current_time, iv): utils._check_bytes("data", data) padder = padding.PKCS7(algorithms.AES.block_size).padder() padded_data = padder.update(data) + padder.finalize() encryptor = Cipher( algorithms.AES(self._encryption_key), modes.CBC(iv), self._backend ).encryptor() ciphertext = encryptor.update(padded_data) + encryptor.finalize() basic_parts = ( b"\x80" + struct.pack(">Q", current_time) + iv + ciphertext ) h = HMAC(self._signing_key, hashes.SHA256(), backend=self._backend) h.update(basic_parts) hmac = h.finalize() return base64.urlsafe_b64encode(basic_parts + hmac) def decrypt(self, token, ttl=None): timestamp, data = Fernet._get_unverified_token_data(token) return self._decrypt_data(data, timestamp, ttl) def extract_timestamp(self, token): timestamp, data = Fernet._get_unverified_token_data(token) # Verify the token was not tampered with. self._verify_signature(data) return timestamp @staticmethod def _get_unverified_token_data(token): utils._check_bytes("token", token) try: data = base64.urlsafe_b64decode(token) except (TypeError, binascii.Error): raise InvalidToken if not data or six.indexbytes(data, 0) != 0x80: raise InvalidToken try: timestamp, = struct.unpack(">Q", data[1:9]) except struct.error: raise InvalidToken return timestamp, data def _verify_signature(self, data): h = HMAC(self._signing_key, hashes.SHA256(), backend=self._backend) h.update(data[:-32]) try: h.verify(data[-32:]) except InvalidSignature: raise InvalidToken def _decrypt_data(self, data, timestamp, ttl): current_time = int(time.time()) if ttl is not None: if timestamp + ttl < current_time: raise InvalidToken if current_time + _MAX_CLOCK_SKEW < timestamp: raise InvalidToken self._verify_signature(data) iv = data[9:25] ciphertext = data[25:-32] decryptor = Cipher( algorithms.AES(self._encryption_key), modes.CBC(iv), self._backend ).decryptor() plaintext_padded = decryptor.update(ciphertext) try: plaintext_padded += decryptor.finalize() except ValueError: raise InvalidToken unpadder = padding.PKCS7(algorithms.AES.block_size).unpadder() unpadded = unpadder.update(plaintext_padded) try: unpadded += unpadder.finalize() except ValueError: raise InvalidToken return unpadded class MultiFernet(object): def __init__(self, fernets): fernets = list(fernets) if not fernets: raise ValueError( "MultiFernet requires at least one Fernet instance" ) self._fernets = fernets def encrypt(self, msg): return self._fernets[0].encrypt(msg) def rotate(self, msg): timestamp, data = Fernet._get_unverified_token_data(msg) for f in self._fernets: try: p = f._decrypt_data(data, timestamp, None) break except InvalidToken: pass else: raise InvalidToken iv = os.urandom(16) return self._fernets[0]._encrypt_from_parts(p, timestamp, iv) def decrypt(self, msg, ttl=None): for f in self._fernets: try: return f.decrypt(msg, ttl) except InvalidToken: pass raise InvalidToken ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/cryptography/hazmat/__init__.py ================================================ # This file is dual licensed under the terms of the Apache License, Version # 2.0, and the BSD License. See the LICENSE file in the root of this repository # for complete details. """ Hazardous Materials This is a "Hazardous Materials" module. You should ONLY use it if you're 100% absolutely sure that you know what you're doing because this module is full of land mines, dragons, and dinosaurs with laser guns. """ from __future__ import absolute_import, division, print_function ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/cryptography/hazmat/_der.py ================================================ # This file is dual licensed under the terms of the Apache License, Version # 2.0, and the BSD License. See the LICENSE file in the root of this repository # for complete details. from __future__ import absolute_import, division, print_function import six from cryptography.utils import int_from_bytes, int_to_bytes # This module contains a lightweight DER encoder and decoder. See X.690 for the # specification. This module intentionally does not implement the more complex # BER encoding, only DER. # # Note this implementation treats an element's constructed bit as part of the # tag. This is fine for DER, where the bit is always computable from the type. CONSTRUCTED = 0x20 CONTEXT_SPECIFIC = 0x80 INTEGER = 0x02 BIT_STRING = 0x03 OCTET_STRING = 0x04 NULL = 0x05 OBJECT_IDENTIFIER = 0x06 SEQUENCE = 0x10 | CONSTRUCTED SET = 0x11 | CONSTRUCTED PRINTABLE_STRING = 0x13 UTC_TIME = 0x17 GENERALIZED_TIME = 0x18 class DERReader(object): def __init__(self, data): self.data = memoryview(data) def __enter__(self): return self def __exit__(self, exc_type, exc_value, tb): if exc_value is None: self.check_empty() def is_empty(self): return len(self.data) == 0 def check_empty(self): if not self.is_empty(): raise ValueError("Invalid DER input: trailing data") def read_byte(self): if len(self.data) < 1: raise ValueError("Invalid DER input: insufficient data") ret = six.indexbytes(self.data, 0) self.data = self.data[1:] return ret def read_bytes(self, n): if len(self.data) < n: raise ValueError("Invalid DER input: insufficient data") ret = self.data[:n] self.data = self.data[n:] return ret def read_any_element(self): tag = self.read_byte() # Tag numbers 31 or higher are stored in multiple bytes. No supported # ASN.1 types use such tags, so reject these. if tag & 0x1f == 0x1f: raise ValueError("Invalid DER input: unexpected high tag number") length_byte = self.read_byte() if length_byte & 0x80 == 0: # If the high bit is clear, the first length byte is the length. length = length_byte else: # If the high bit is set, the first length byte encodes the length # of the length. length_byte &= 0x7f if length_byte == 0: raise ValueError( "Invalid DER input: indefinite length form is not allowed " "in DER" ) length = 0 for i in range(length_byte): length <<= 8 length |= self.read_byte() if length == 0: raise ValueError( "Invalid DER input: length was not minimally-encoded" ) if length < 0x80: # If the length could have been encoded in short form, it must # not use long form. raise ValueError( "Invalid DER input: length was not minimally-encoded" ) body = self.read_bytes(length) return tag, DERReader(body) def read_element(self, expected_tag): tag, body = self.read_any_element() if tag != expected_tag: raise ValueError("Invalid DER input: unexpected tag") return body def read_single_element(self, expected_tag): with self: return self.read_element(expected_tag) def read_optional_element(self, expected_tag): if len(self.data) > 0 and six.indexbytes(self.data, 0) == expected_tag: return self.read_element(expected_tag) return None def as_integer(self): if len(self.data) == 0: raise ValueError("Invalid DER input: empty integer contents") first = six.indexbytes(self.data, 0) if first & 0x80 == 0x80: raise ValueError("Negative DER integers are not supported") # The first 9 bits must not all be zero or all be ones. Otherwise, the # encoding should have been one byte shorter. if len(self.data) > 1: second = six.indexbytes(self.data, 1) if first == 0 and second & 0x80 == 0: raise ValueError( "Invalid DER input: integer not minimally-encoded" ) return int_from_bytes(self.data, "big") def encode_der_integer(x): if not isinstance(x, six.integer_types): raise ValueError("Value must be an integer") if x < 0: raise ValueError("Negative integers are not supported") n = x.bit_length() // 8 + 1 return int_to_bytes(x, n) def encode_der(tag, *children): length = 0 for child in children: length += len(child) chunks = [six.int2byte(tag)] if length < 0x80: chunks.append(six.int2byte(length)) else: length_bytes = int_to_bytes(length) chunks.append(six.int2byte(0x80 | len(length_bytes))) chunks.append(length_bytes) chunks.extend(children) return b"".join(chunks) ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/cryptography/hazmat/_oid.py ================================================ # This file is dual licensed under the terms of the Apache License, Version # 2.0, and the BSD License. See the LICENSE file in the root of this repository # for complete details. from __future__ import absolute_import, division, print_function from cryptography import utils class ObjectIdentifier(object): def __init__(self, dotted_string): self._dotted_string = dotted_string nodes = self._dotted_string.split(".") intnodes = [] # There must be at least 2 nodes, the first node must be 0..2, and # if less than 2, the second node cannot have a value outside the # range 0..39. All nodes must be integers. for node in nodes: try: intnodes.append(int(node, 0)) except ValueError: raise ValueError( "Malformed OID: %s (non-integer nodes)" % ( self._dotted_string)) if len(nodes) < 2: raise ValueError( "Malformed OID: %s (insufficient number of nodes)" % ( self._dotted_string)) if intnodes[0] > 2: raise ValueError( "Malformed OID: %s (first node outside valid range)" % ( self._dotted_string)) if intnodes[0] < 2 and intnodes[1] >= 40: raise ValueError( "Malformed OID: %s (second node outside valid range)" % ( self._dotted_string)) def __eq__(self, other): if not isinstance(other, ObjectIdentifier): return NotImplemented return self.dotted_string == other.dotted_string def __ne__(self, other): return not self == other def __repr__(self): return "".format( self.dotted_string, self._name ) def __hash__(self): return hash(self.dotted_string) @property def _name(self): # Lazy import to avoid an import cycle from cryptography.x509.oid import _OID_NAMES return _OID_NAMES.get(self, "Unknown OID") dotted_string = utils.read_only_property("_dotted_string") ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/cryptography/hazmat/backends/__init__.py ================================================ # This file is dual licensed under the terms of the Apache License, Version # 2.0, and the BSD License. See the LICENSE file in the root of this repository # for complete details. from __future__ import absolute_import, division, print_function _default_backend = None def default_backend(): global _default_backend if _default_backend is None: from cryptography.hazmat.backends.openssl.backend import backend _default_backend = backend return _default_backend ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/cryptography/hazmat/backends/interfaces.py ================================================ # This file is dual licensed under the terms of the Apache License, Version # 2.0, and the BSD License. See the LICENSE file in the root of this repository # for complete details. from __future__ import absolute_import, division, print_function import abc import six @six.add_metaclass(abc.ABCMeta) class CipherBackend(object): @abc.abstractmethod def cipher_supported(self, cipher, mode): """ Return True if the given cipher and mode are supported. """ @abc.abstractmethod def create_symmetric_encryption_ctx(self, cipher, mode): """ Get a CipherContext that can be used for encryption. """ @abc.abstractmethod def create_symmetric_decryption_ctx(self, cipher, mode): """ Get a CipherContext that can be used for decryption. """ @six.add_metaclass(abc.ABCMeta) class HashBackend(object): @abc.abstractmethod def hash_supported(self, algorithm): """ Return True if the hash algorithm is supported by this backend. """ @abc.abstractmethod def create_hash_ctx(self, algorithm): """ Create a HashContext for calculating a message digest. """ @six.add_metaclass(abc.ABCMeta) class HMACBackend(object): @abc.abstractmethod def hmac_supported(self, algorithm): """ Return True if the hash algorithm is supported for HMAC by this backend. """ @abc.abstractmethod def create_hmac_ctx(self, key, algorithm): """ Create a context for calculating a message authentication code. """ @six.add_metaclass(abc.ABCMeta) class CMACBackend(object): @abc.abstractmethod def cmac_algorithm_supported(self, algorithm): """ Returns True if the block cipher is supported for CMAC by this backend """ @abc.abstractmethod def create_cmac_ctx(self, algorithm): """ Create a context for calculating a message authentication code. """ @six.add_metaclass(abc.ABCMeta) class PBKDF2HMACBackend(object): @abc.abstractmethod def pbkdf2_hmac_supported(self, algorithm): """ Return True if the hash algorithm is supported for PBKDF2 by this backend. """ @abc.abstractmethod def derive_pbkdf2_hmac(self, algorithm, length, salt, iterations, key_material): """ Return length bytes derived from provided PBKDF2 parameters. """ @six.add_metaclass(abc.ABCMeta) class RSABackend(object): @abc.abstractmethod def generate_rsa_private_key(self, public_exponent, key_size): """ Generate an RSAPrivateKey instance with public_exponent and a modulus of key_size bits. """ @abc.abstractmethod def rsa_padding_supported(self, padding): """ Returns True if the backend supports the given padding options. """ @abc.abstractmethod def generate_rsa_parameters_supported(self, public_exponent, key_size): """ Returns True if the backend supports the given parameters for key generation. """ @abc.abstractmethod def load_rsa_private_numbers(self, numbers): """ Returns an RSAPrivateKey provider. """ @abc.abstractmethod def load_rsa_public_numbers(self, numbers): """ Returns an RSAPublicKey provider. """ @six.add_metaclass(abc.ABCMeta) class DSABackend(object): @abc.abstractmethod def generate_dsa_parameters(self, key_size): """ Generate a DSAParameters instance with a modulus of key_size bits. """ @abc.abstractmethod def generate_dsa_private_key(self, parameters): """ Generate a DSAPrivateKey instance with parameters as a DSAParameters object. """ @abc.abstractmethod def generate_dsa_private_key_and_parameters(self, key_size): """ Generate a DSAPrivateKey instance using key size only. """ @abc.abstractmethod def dsa_hash_supported(self, algorithm): """ Return True if the hash algorithm is supported by the backend for DSA. """ @abc.abstractmethod def dsa_parameters_supported(self, p, q, g): """ Return True if the parameters are supported by the backend for DSA. """ @abc.abstractmethod def load_dsa_private_numbers(self, numbers): """ Returns a DSAPrivateKey provider. """ @abc.abstractmethod def load_dsa_public_numbers(self, numbers): """ Returns a DSAPublicKey provider. """ @abc.abstractmethod def load_dsa_parameter_numbers(self, numbers): """ Returns a DSAParameters provider. """ @six.add_metaclass(abc.ABCMeta) class EllipticCurveBackend(object): @abc.abstractmethod def elliptic_curve_signature_algorithm_supported( self, signature_algorithm, curve ): """ Returns True if the backend supports the named elliptic curve with the specified signature algorithm. """ @abc.abstractmethod def elliptic_curve_supported(self, curve): """ Returns True if the backend supports the named elliptic curve. """ @abc.abstractmethod def generate_elliptic_curve_private_key(self, curve): """ Return an object conforming to the EllipticCurvePrivateKey interface. """ @abc.abstractmethod def load_elliptic_curve_public_numbers(self, numbers): """ Return an EllipticCurvePublicKey provider using the given numbers. """ @abc.abstractmethod def load_elliptic_curve_private_numbers(self, numbers): """ Return an EllipticCurvePrivateKey provider using the given numbers. """ @abc.abstractmethod def elliptic_curve_exchange_algorithm_supported(self, algorithm, curve): """ Returns whether the exchange algorithm is supported by this backend. """ @abc.abstractmethod def derive_elliptic_curve_private_key(self, private_value, curve): """ Compute the private key given the private value and curve. """ @six.add_metaclass(abc.ABCMeta) class PEMSerializationBackend(object): @abc.abstractmethod def load_pem_private_key(self, data, password): """ Loads a private key from PEM encoded data, using the provided password if the data is encrypted. """ @abc.abstractmethod def load_pem_public_key(self, data): """ Loads a public key from PEM encoded data. """ @abc.abstractmethod def load_pem_parameters(self, data): """ Load encryption parameters from PEM encoded data. """ @six.add_metaclass(abc.ABCMeta) class DERSerializationBackend(object): @abc.abstractmethod def load_der_private_key(self, data, password): """ Loads a private key from DER encoded data. Uses the provided password if the data is encrypted. """ @abc.abstractmethod def load_der_public_key(self, data): """ Loads a public key from DER encoded data. """ @abc.abstractmethod def load_der_parameters(self, data): """ Load encryption parameters from DER encoded data. """ @six.add_metaclass(abc.ABCMeta) class X509Backend(object): @abc.abstractmethod def load_pem_x509_certificate(self, data): """ Load an X.509 certificate from PEM encoded data. """ @abc.abstractmethod def load_der_x509_certificate(self, data): """ Load an X.509 certificate from DER encoded data. """ @abc.abstractmethod def load_der_x509_csr(self, data): """ Load an X.509 CSR from DER encoded data. """ @abc.abstractmethod def load_pem_x509_csr(self, data): """ Load an X.509 CSR from PEM encoded data. """ @abc.abstractmethod def create_x509_csr(self, builder, private_key, algorithm): """ Create and sign an X.509 CSR from a CSR builder object. """ @abc.abstractmethod def create_x509_certificate(self, builder, private_key, algorithm): """ Create and sign an X.509 certificate from a CertificateBuilder object. """ @abc.abstractmethod def create_x509_crl(self, builder, private_key, algorithm): """ Create and sign an X.509 CertificateRevocationList from a CertificateRevocationListBuilder object. """ @abc.abstractmethod def create_x509_revoked_certificate(self, builder): """ Create a RevokedCertificate object from a RevokedCertificateBuilder object. """ @abc.abstractmethod def x509_name_bytes(self, name): """ Compute the DER encoded bytes of an X509 Name object. """ @six.add_metaclass(abc.ABCMeta) class DHBackend(object): @abc.abstractmethod def generate_dh_parameters(self, generator, key_size): """ Generate a DHParameters instance with a modulus of key_size bits. Using the given generator. Often 2 or 5. """ @abc.abstractmethod def generate_dh_private_key(self, parameters): """ Generate a DHPrivateKey instance with parameters as a DHParameters object. """ @abc.abstractmethod def generate_dh_private_key_and_parameters(self, generator, key_size): """ Generate a DHPrivateKey instance using key size only. Using the given generator. Often 2 or 5. """ @abc.abstractmethod def load_dh_private_numbers(self, numbers): """ Load a DHPrivateKey from DHPrivateNumbers """ @abc.abstractmethod def load_dh_public_numbers(self, numbers): """ Load a DHPublicKey from DHPublicNumbers. """ @abc.abstractmethod def load_dh_parameter_numbers(self, numbers): """ Load DHParameters from DHParameterNumbers. """ @abc.abstractmethod def dh_parameters_supported(self, p, g, q=None): """ Returns whether the backend supports DH with these parameter values. """ @abc.abstractmethod def dh_x942_serialization_supported(self): """ Returns True if the backend supports the serialization of DH objects with subgroup order (q). """ @six.add_metaclass(abc.ABCMeta) class ScryptBackend(object): @abc.abstractmethod def derive_scrypt(self, key_material, salt, length, n, r, p): """ Return bytes derived from provided Scrypt parameters. """ ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/cryptography/hazmat/backends/openssl/__init__.py ================================================ # This file is dual licensed under the terms of the Apache License, Version # 2.0, and the BSD License. See the LICENSE file in the root of this repository # for complete details. from __future__ import absolute_import, division, print_function from cryptography.hazmat.backends.openssl.backend import backend __all__ = ["backend"] ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/cryptography/hazmat/backends/openssl/aead.py ================================================ # This file is dual licensed under the terms of the Apache License, Version # 2.0, and the BSD License. See the LICENSE file in the root of this repository # for complete details. from __future__ import absolute_import, division, print_function from cryptography.exceptions import InvalidTag _ENCRYPT = 1 _DECRYPT = 0 def _aead_cipher_name(cipher): from cryptography.hazmat.primitives.ciphers.aead import ( AESCCM, AESGCM, ChaCha20Poly1305 ) if isinstance(cipher, ChaCha20Poly1305): return b"chacha20-poly1305" elif isinstance(cipher, AESCCM): return "aes-{}-ccm".format(len(cipher._key) * 8).encode("ascii") else: assert isinstance(cipher, AESGCM) return "aes-{}-gcm".format(len(cipher._key) * 8).encode("ascii") def _aead_setup(backend, cipher_name, key, nonce, tag, tag_len, operation): evp_cipher = backend._lib.EVP_get_cipherbyname(cipher_name) backend.openssl_assert(evp_cipher != backend._ffi.NULL) ctx = backend._lib.EVP_CIPHER_CTX_new() ctx = backend._ffi.gc(ctx, backend._lib.EVP_CIPHER_CTX_free) res = backend._lib.EVP_CipherInit_ex( ctx, evp_cipher, backend._ffi.NULL, backend._ffi.NULL, backend._ffi.NULL, int(operation == _ENCRYPT) ) backend.openssl_assert(res != 0) res = backend._lib.EVP_CIPHER_CTX_set_key_length(ctx, len(key)) backend.openssl_assert(res != 0) res = backend._lib.EVP_CIPHER_CTX_ctrl( ctx, backend._lib.EVP_CTRL_AEAD_SET_IVLEN, len(nonce), backend._ffi.NULL ) backend.openssl_assert(res != 0) if operation == _DECRYPT: res = backend._lib.EVP_CIPHER_CTX_ctrl( ctx, backend._lib.EVP_CTRL_AEAD_SET_TAG, len(tag), tag ) backend.openssl_assert(res != 0) elif cipher_name.endswith(b"-ccm"): res = backend._lib.EVP_CIPHER_CTX_ctrl( ctx, backend._lib.EVP_CTRL_AEAD_SET_TAG, tag_len, backend._ffi.NULL ) backend.openssl_assert(res != 0) nonce_ptr = backend._ffi.from_buffer(nonce) key_ptr = backend._ffi.from_buffer(key) res = backend._lib.EVP_CipherInit_ex( ctx, backend._ffi.NULL, backend._ffi.NULL, key_ptr, nonce_ptr, int(operation == _ENCRYPT) ) backend.openssl_assert(res != 0) return ctx def _set_length(backend, ctx, data_len): intptr = backend._ffi.new("int *") res = backend._lib.EVP_CipherUpdate( ctx, backend._ffi.NULL, intptr, backend._ffi.NULL, data_len ) backend.openssl_assert(res != 0) def _process_aad(backend, ctx, associated_data): outlen = backend._ffi.new("int *") res = backend._lib.EVP_CipherUpdate( ctx, backend._ffi.NULL, outlen, associated_data, len(associated_data) ) backend.openssl_assert(res != 0) def _process_data(backend, ctx, data): outlen = backend._ffi.new("int *") buf = backend._ffi.new("unsigned char[]", len(data)) res = backend._lib.EVP_CipherUpdate(ctx, buf, outlen, data, len(data)) backend.openssl_assert(res != 0) return backend._ffi.buffer(buf, outlen[0])[:] def _encrypt(backend, cipher, nonce, data, associated_data, tag_length): from cryptography.hazmat.primitives.ciphers.aead import AESCCM cipher_name = _aead_cipher_name(cipher) ctx = _aead_setup( backend, cipher_name, cipher._key, nonce, None, tag_length, _ENCRYPT ) # CCM requires us to pass the length of the data before processing anything # However calling this with any other AEAD results in an error if isinstance(cipher, AESCCM): _set_length(backend, ctx, len(data)) _process_aad(backend, ctx, associated_data) processed_data = _process_data(backend, ctx, data) outlen = backend._ffi.new("int *") res = backend._lib.EVP_CipherFinal_ex(ctx, backend._ffi.NULL, outlen) backend.openssl_assert(res != 0) backend.openssl_assert(outlen[0] == 0) tag_buf = backend._ffi.new("unsigned char[]", tag_length) res = backend._lib.EVP_CIPHER_CTX_ctrl( ctx, backend._lib.EVP_CTRL_AEAD_GET_TAG, tag_length, tag_buf ) backend.openssl_assert(res != 0) tag = backend._ffi.buffer(tag_buf)[:] return processed_data + tag def _decrypt(backend, cipher, nonce, data, associated_data, tag_length): from cryptography.hazmat.primitives.ciphers.aead import AESCCM if len(data) < tag_length: raise InvalidTag tag = data[-tag_length:] data = data[:-tag_length] cipher_name = _aead_cipher_name(cipher) ctx = _aead_setup( backend, cipher_name, cipher._key, nonce, tag, tag_length, _DECRYPT ) # CCM requires us to pass the length of the data before processing anything # However calling this with any other AEAD results in an error if isinstance(cipher, AESCCM): _set_length(backend, ctx, len(data)) _process_aad(backend, ctx, associated_data) # CCM has a different error path if the tag doesn't match. Errors are # raised in Update and Final is irrelevant. if isinstance(cipher, AESCCM): outlen = backend._ffi.new("int *") buf = backend._ffi.new("unsigned char[]", len(data)) res = backend._lib.EVP_CipherUpdate(ctx, buf, outlen, data, len(data)) if res != 1: backend._consume_errors() raise InvalidTag processed_data = backend._ffi.buffer(buf, outlen[0])[:] else: processed_data = _process_data(backend, ctx, data) outlen = backend._ffi.new("int *") res = backend._lib.EVP_CipherFinal_ex(ctx, backend._ffi.NULL, outlen) if res == 0: backend._consume_errors() raise InvalidTag return processed_data ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/cryptography/hazmat/backends/openssl/backend.py ================================================ # This file is dual licensed under the terms of the Apache License, Version # 2.0, and the BSD License. See the LICENSE file in the root of this repository # for complete details. from __future__ import absolute_import, division, print_function import base64 import collections import contextlib import itertools from contextlib import contextmanager import six from six.moves import range from cryptography import utils, x509 from cryptography.exceptions import UnsupportedAlgorithm, _Reasons from cryptography.hazmat._der import ( INTEGER, NULL, SEQUENCE, encode_der, encode_der_integer ) from cryptography.hazmat.backends.interfaces import ( CMACBackend, CipherBackend, DERSerializationBackend, DHBackend, DSABackend, EllipticCurveBackend, HMACBackend, HashBackend, PBKDF2HMACBackend, PEMSerializationBackend, RSABackend, ScryptBackend, X509Backend ) from cryptography.hazmat.backends.openssl import aead from cryptography.hazmat.backends.openssl.ciphers import _CipherContext from cryptography.hazmat.backends.openssl.cmac import _CMACContext from cryptography.hazmat.backends.openssl.decode_asn1 import ( _CRL_ENTRY_REASON_ENUM_TO_CODE ) from cryptography.hazmat.backends.openssl.dh import ( _DHParameters, _DHPrivateKey, _DHPublicKey, _dh_params_dup ) from cryptography.hazmat.backends.openssl.dsa import ( _DSAParameters, _DSAPrivateKey, _DSAPublicKey ) from cryptography.hazmat.backends.openssl.ec import ( _EllipticCurvePrivateKey, _EllipticCurvePublicKey ) from cryptography.hazmat.backends.openssl.ed25519 import ( _Ed25519PrivateKey, _Ed25519PublicKey ) from cryptography.hazmat.backends.openssl.ed448 import ( _ED448_KEY_SIZE, _Ed448PrivateKey, _Ed448PublicKey ) from cryptography.hazmat.backends.openssl.encode_asn1 import ( _CRL_ENTRY_EXTENSION_ENCODE_HANDLERS, _CRL_EXTENSION_ENCODE_HANDLERS, _EXTENSION_ENCODE_HANDLERS, _OCSP_BASICRESP_EXTENSION_ENCODE_HANDLERS, _OCSP_REQUEST_EXTENSION_ENCODE_HANDLERS, _encode_asn1_int_gc, _encode_asn1_str_gc, _encode_name_gc, _txt2obj_gc, ) from cryptography.hazmat.backends.openssl.hashes import _HashContext from cryptography.hazmat.backends.openssl.hmac import _HMACContext from cryptography.hazmat.backends.openssl.ocsp import ( _OCSPRequest, _OCSPResponse ) from cryptography.hazmat.backends.openssl.poly1305 import ( _POLY1305_KEY_SIZE, _Poly1305Context ) from cryptography.hazmat.backends.openssl.rsa import ( _RSAPrivateKey, _RSAPublicKey ) from cryptography.hazmat.backends.openssl.x25519 import ( _X25519PrivateKey, _X25519PublicKey ) from cryptography.hazmat.backends.openssl.x448 import ( _X448PrivateKey, _X448PublicKey ) from cryptography.hazmat.backends.openssl.x509 import ( _Certificate, _CertificateRevocationList, _CertificateSigningRequest, _RevokedCertificate ) from cryptography.hazmat.bindings.openssl import binding from cryptography.hazmat.primitives import hashes, serialization from cryptography.hazmat.primitives.asymmetric import ( dsa, ec, ed25519, ed448, rsa ) from cryptography.hazmat.primitives.asymmetric.padding import ( MGF1, OAEP, PKCS1v15, PSS ) from cryptography.hazmat.primitives.ciphers.algorithms import ( AES, ARC4, Blowfish, CAST5, Camellia, ChaCha20, IDEA, SEED, TripleDES ) from cryptography.hazmat.primitives.ciphers.modes import ( CBC, CFB, CFB8, CTR, ECB, GCM, OFB, XTS ) from cryptography.hazmat.primitives.kdf import scrypt from cryptography.hazmat.primitives.serialization import ssh from cryptography.x509 import ocsp _MemoryBIO = collections.namedtuple("_MemoryBIO", ["bio", "char_ptr"]) @utils.register_interface(CipherBackend) @utils.register_interface(CMACBackend) @utils.register_interface(DERSerializationBackend) @utils.register_interface(DHBackend) @utils.register_interface(DSABackend) @utils.register_interface(EllipticCurveBackend) @utils.register_interface(HashBackend) @utils.register_interface(HMACBackend) @utils.register_interface(PBKDF2HMACBackend) @utils.register_interface(RSABackend) @utils.register_interface(PEMSerializationBackend) @utils.register_interface(X509Backend) @utils.register_interface_if( binding.Binding().lib.Cryptography_HAS_SCRYPT, ScryptBackend ) class Backend(object): """ OpenSSL API binding interfaces. """ name = "openssl" def __init__(self): self._binding = binding.Binding() self._ffi = self._binding.ffi self._lib = self._binding.lib self._cipher_registry = {} self._register_default_ciphers() self.activate_osrandom_engine() self._dh_types = [self._lib.EVP_PKEY_DH] if self._lib.Cryptography_HAS_EVP_PKEY_DHX: self._dh_types.append(self._lib.EVP_PKEY_DHX) def openssl_assert(self, ok): return binding._openssl_assert(self._lib, ok) def activate_builtin_random(self): if self._lib.Cryptography_HAS_ENGINE: # Obtain a new structural reference. e = self._lib.ENGINE_get_default_RAND() if e != self._ffi.NULL: self._lib.ENGINE_unregister_RAND(e) # Reset the RNG to use the built-in. res = self._lib.RAND_set_rand_method(self._ffi.NULL) self.openssl_assert(res == 1) # decrement the structural reference from get_default_RAND res = self._lib.ENGINE_finish(e) self.openssl_assert(res == 1) @contextlib.contextmanager def _get_osurandom_engine(self): # Fetches an engine by id and returns it. This creates a structural # reference. e = self._lib.ENGINE_by_id(self._lib.Cryptography_osrandom_engine_id) self.openssl_assert(e != self._ffi.NULL) # Initialize the engine for use. This adds a functional reference. res = self._lib.ENGINE_init(e) self.openssl_assert(res == 1) try: yield e finally: # Decrement the structural ref incremented by ENGINE_by_id. res = self._lib.ENGINE_free(e) self.openssl_assert(res == 1) # Decrement the functional ref incremented by ENGINE_init. res = self._lib.ENGINE_finish(e) self.openssl_assert(res == 1) def activate_osrandom_engine(self): if self._lib.Cryptography_HAS_ENGINE: # Unregister and free the current engine. self.activate_builtin_random() with self._get_osurandom_engine() as e: # Set the engine as the default RAND provider. res = self._lib.ENGINE_set_default_RAND(e) self.openssl_assert(res == 1) # Reset the RNG to use the engine res = self._lib.RAND_set_rand_method(self._ffi.NULL) self.openssl_assert(res == 1) def osrandom_engine_implementation(self): buf = self._ffi.new("char[]", 64) with self._get_osurandom_engine() as e: res = self._lib.ENGINE_ctrl_cmd(e, b"get_implementation", len(buf), buf, self._ffi.NULL, 0) self.openssl_assert(res > 0) return self._ffi.string(buf).decode('ascii') def openssl_version_text(self): """ Friendly string name of the loaded OpenSSL library. This is not necessarily the same version as it was compiled against. Example: OpenSSL 1.0.1e 11 Feb 2013 """ return self._ffi.string( self._lib.OpenSSL_version(self._lib.OPENSSL_VERSION) ).decode("ascii") def openssl_version_number(self): return self._lib.OpenSSL_version_num() def create_hmac_ctx(self, key, algorithm): return _HMACContext(self, key, algorithm) def _evp_md_from_algorithm(self, algorithm): if algorithm.name == "blake2b" or algorithm.name == "blake2s": alg = "{}{}".format( algorithm.name, algorithm.digest_size * 8 ).encode("ascii") else: alg = algorithm.name.encode("ascii") evp_md = self._lib.EVP_get_digestbyname(alg) return evp_md def _evp_md_non_null_from_algorithm(self, algorithm): evp_md = self._evp_md_from_algorithm(algorithm) self.openssl_assert(evp_md != self._ffi.NULL) return evp_md def hash_supported(self, algorithm): evp_md = self._evp_md_from_algorithm(algorithm) return evp_md != self._ffi.NULL def hmac_supported(self, algorithm): return self.hash_supported(algorithm) def create_hash_ctx(self, algorithm): return _HashContext(self, algorithm) def cipher_supported(self, cipher, mode): try: adapter = self._cipher_registry[type(cipher), type(mode)] except KeyError: return False evp_cipher = adapter(self, cipher, mode) return self._ffi.NULL != evp_cipher def register_cipher_adapter(self, cipher_cls, mode_cls, adapter): if (cipher_cls, mode_cls) in self._cipher_registry: raise ValueError("Duplicate registration for: {} {}.".format( cipher_cls, mode_cls) ) self._cipher_registry[cipher_cls, mode_cls] = adapter def _register_default_ciphers(self): for mode_cls in [CBC, CTR, ECB, OFB, CFB, CFB8, GCM]: self.register_cipher_adapter( AES, mode_cls, GetCipherByName("{cipher.name}-{cipher.key_size}-{mode.name}") ) for mode_cls in [CBC, CTR, ECB, OFB, CFB]: self.register_cipher_adapter( Camellia, mode_cls, GetCipherByName("{cipher.name}-{cipher.key_size}-{mode.name}") ) for mode_cls in [CBC, CFB, CFB8, OFB]: self.register_cipher_adapter( TripleDES, mode_cls, GetCipherByName("des-ede3-{mode.name}") ) self.register_cipher_adapter( TripleDES, ECB, GetCipherByName("des-ede3") ) for mode_cls in [CBC, CFB, OFB, ECB]: self.register_cipher_adapter( Blowfish, mode_cls, GetCipherByName("bf-{mode.name}") ) for mode_cls in [CBC, CFB, OFB, ECB]: self.register_cipher_adapter( SEED, mode_cls, GetCipherByName("seed-{mode.name}") ) for cipher_cls, mode_cls in itertools.product( [CAST5, IDEA], [CBC, OFB, CFB, ECB], ): self.register_cipher_adapter( cipher_cls, mode_cls, GetCipherByName("{cipher.name}-{mode.name}") ) self.register_cipher_adapter( ARC4, type(None), GetCipherByName("rc4") ) self.register_cipher_adapter( ChaCha20, type(None), GetCipherByName("chacha20") ) self.register_cipher_adapter(AES, XTS, _get_xts_cipher) def create_symmetric_encryption_ctx(self, cipher, mode): return _CipherContext(self, cipher, mode, _CipherContext._ENCRYPT) def create_symmetric_decryption_ctx(self, cipher, mode): return _CipherContext(self, cipher, mode, _CipherContext._DECRYPT) def pbkdf2_hmac_supported(self, algorithm): return self.hmac_supported(algorithm) def derive_pbkdf2_hmac(self, algorithm, length, salt, iterations, key_material): buf = self._ffi.new("unsigned char[]", length) evp_md = self._evp_md_non_null_from_algorithm(algorithm) key_material_ptr = self._ffi.from_buffer(key_material) res = self._lib.PKCS5_PBKDF2_HMAC( key_material_ptr, len(key_material), salt, len(salt), iterations, evp_md, length, buf ) self.openssl_assert(res == 1) return self._ffi.buffer(buf)[:] def _consume_errors(self): return binding._consume_errors(self._lib) def _bn_to_int(self, bn): assert bn != self._ffi.NULL if not six.PY2: # Python 3 has constant time from_bytes, so use that. bn_num_bytes = self._lib.BN_num_bytes(bn) bin_ptr = self._ffi.new("unsigned char[]", bn_num_bytes) bin_len = self._lib.BN_bn2bin(bn, bin_ptr) # A zero length means the BN has value 0 self.openssl_assert(bin_len >= 0) val = int.from_bytes(self._ffi.buffer(bin_ptr)[:bin_len], "big") if self._lib.BN_is_negative(bn): val = -val return val else: # Under Python 2 the best we can do is hex() hex_cdata = self._lib.BN_bn2hex(bn) self.openssl_assert(hex_cdata != self._ffi.NULL) hex_str = self._ffi.string(hex_cdata) self._lib.OPENSSL_free(hex_cdata) return int(hex_str, 16) def _int_to_bn(self, num, bn=None): """ Converts a python integer to a BIGNUM. The returned BIGNUM will not be garbage collected (to support adding them to structs that take ownership of the object). Be sure to register it for GC if it will be discarded after use. """ assert bn is None or bn != self._ffi.NULL if bn is None: bn = self._ffi.NULL if not six.PY2: # Python 3 has constant time to_bytes, so use that. binary = num.to_bytes(int(num.bit_length() / 8.0 + 1), "big") bn_ptr = self._lib.BN_bin2bn(binary, len(binary), bn) self.openssl_assert(bn_ptr != self._ffi.NULL) return bn_ptr else: # Under Python 2 the best we can do is hex(), [2:] removes the 0x # prefix. hex_num = hex(num).rstrip("L")[2:].encode("ascii") bn_ptr = self._ffi.new("BIGNUM **") bn_ptr[0] = bn res = self._lib.BN_hex2bn(bn_ptr, hex_num) self.openssl_assert(res != 0) self.openssl_assert(bn_ptr[0] != self._ffi.NULL) return bn_ptr[0] def generate_rsa_private_key(self, public_exponent, key_size): rsa._verify_rsa_parameters(public_exponent, key_size) rsa_cdata = self._lib.RSA_new() self.openssl_assert(rsa_cdata != self._ffi.NULL) rsa_cdata = self._ffi.gc(rsa_cdata, self._lib.RSA_free) bn = self._int_to_bn(public_exponent) bn = self._ffi.gc(bn, self._lib.BN_free) res = self._lib.RSA_generate_key_ex( rsa_cdata, key_size, bn, self._ffi.NULL ) self.openssl_assert(res == 1) evp_pkey = self._rsa_cdata_to_evp_pkey(rsa_cdata) return _RSAPrivateKey(self, rsa_cdata, evp_pkey) def generate_rsa_parameters_supported(self, public_exponent, key_size): return (public_exponent >= 3 and public_exponent & 1 != 0 and key_size >= 512) def load_rsa_private_numbers(self, numbers): rsa._check_private_key_components( numbers.p, numbers.q, numbers.d, numbers.dmp1, numbers.dmq1, numbers.iqmp, numbers.public_numbers.e, numbers.public_numbers.n ) rsa_cdata = self._lib.RSA_new() self.openssl_assert(rsa_cdata != self._ffi.NULL) rsa_cdata = self._ffi.gc(rsa_cdata, self._lib.RSA_free) p = self._int_to_bn(numbers.p) q = self._int_to_bn(numbers.q) d = self._int_to_bn(numbers.d) dmp1 = self._int_to_bn(numbers.dmp1) dmq1 = self._int_to_bn(numbers.dmq1) iqmp = self._int_to_bn(numbers.iqmp) e = self._int_to_bn(numbers.public_numbers.e) n = self._int_to_bn(numbers.public_numbers.n) res = self._lib.RSA_set0_factors(rsa_cdata, p, q) self.openssl_assert(res == 1) res = self._lib.RSA_set0_key(rsa_cdata, n, e, d) self.openssl_assert(res == 1) res = self._lib.RSA_set0_crt_params(rsa_cdata, dmp1, dmq1, iqmp) self.openssl_assert(res == 1) res = self._lib.RSA_blinding_on(rsa_cdata, self._ffi.NULL) self.openssl_assert(res == 1) evp_pkey = self._rsa_cdata_to_evp_pkey(rsa_cdata) return _RSAPrivateKey(self, rsa_cdata, evp_pkey) def load_rsa_public_numbers(self, numbers): rsa._check_public_key_components(numbers.e, numbers.n) rsa_cdata = self._lib.RSA_new() self.openssl_assert(rsa_cdata != self._ffi.NULL) rsa_cdata = self._ffi.gc(rsa_cdata, self._lib.RSA_free) e = self._int_to_bn(numbers.e) n = self._int_to_bn(numbers.n) res = self._lib.RSA_set0_key(rsa_cdata, n, e, self._ffi.NULL) self.openssl_assert(res == 1) evp_pkey = self._rsa_cdata_to_evp_pkey(rsa_cdata) return _RSAPublicKey(self, rsa_cdata, evp_pkey) def _create_evp_pkey_gc(self): evp_pkey = self._lib.EVP_PKEY_new() self.openssl_assert(evp_pkey != self._ffi.NULL) evp_pkey = self._ffi.gc(evp_pkey, self._lib.EVP_PKEY_free) return evp_pkey def _rsa_cdata_to_evp_pkey(self, rsa_cdata): evp_pkey = self._create_evp_pkey_gc() res = self._lib.EVP_PKEY_set1_RSA(evp_pkey, rsa_cdata) self.openssl_assert(res == 1) return evp_pkey def _bytes_to_bio(self, data): """ Return a _MemoryBIO namedtuple of (BIO, char*). The char* is the storage for the BIO and it must stay alive until the BIO is finished with. """ data_ptr = self._ffi.from_buffer(data) bio = self._lib.BIO_new_mem_buf( data_ptr, len(data) ) self.openssl_assert(bio != self._ffi.NULL) return _MemoryBIO(self._ffi.gc(bio, self._lib.BIO_free), data_ptr) def _create_mem_bio_gc(self): """ Creates an empty memory BIO. """ bio_method = self._lib.BIO_s_mem() self.openssl_assert(bio_method != self._ffi.NULL) bio = self._lib.BIO_new(bio_method) self.openssl_assert(bio != self._ffi.NULL) bio = self._ffi.gc(bio, self._lib.BIO_free) return bio def _read_mem_bio(self, bio): """ Reads a memory BIO. This only works on memory BIOs. """ buf = self._ffi.new("char **") buf_len = self._lib.BIO_get_mem_data(bio, buf) self.openssl_assert(buf_len > 0) self.openssl_assert(buf[0] != self._ffi.NULL) bio_data = self._ffi.buffer(buf[0], buf_len)[:] return bio_data def _evp_pkey_to_private_key(self, evp_pkey): """ Return the appropriate type of PrivateKey given an evp_pkey cdata pointer. """ key_type = self._lib.EVP_PKEY_id(evp_pkey) if key_type == self._lib.EVP_PKEY_RSA: rsa_cdata = self._lib.EVP_PKEY_get1_RSA(evp_pkey) self.openssl_assert(rsa_cdata != self._ffi.NULL) rsa_cdata = self._ffi.gc(rsa_cdata, self._lib.RSA_free) return _RSAPrivateKey(self, rsa_cdata, evp_pkey) elif key_type == self._lib.EVP_PKEY_DSA: dsa_cdata = self._lib.EVP_PKEY_get1_DSA(evp_pkey) self.openssl_assert(dsa_cdata != self._ffi.NULL) dsa_cdata = self._ffi.gc(dsa_cdata, self._lib.DSA_free) return _DSAPrivateKey(self, dsa_cdata, evp_pkey) elif key_type == self._lib.EVP_PKEY_EC: ec_cdata = self._lib.EVP_PKEY_get1_EC_KEY(evp_pkey) self.openssl_assert(ec_cdata != self._ffi.NULL) ec_cdata = self._ffi.gc(ec_cdata, self._lib.EC_KEY_free) return _EllipticCurvePrivateKey(self, ec_cdata, evp_pkey) elif key_type in self._dh_types: dh_cdata = self._lib.EVP_PKEY_get1_DH(evp_pkey) self.openssl_assert(dh_cdata != self._ffi.NULL) dh_cdata = self._ffi.gc(dh_cdata, self._lib.DH_free) return _DHPrivateKey(self, dh_cdata, evp_pkey) elif key_type == getattr(self._lib, "EVP_PKEY_ED25519", None): # EVP_PKEY_ED25519 is not present in OpenSSL < 1.1.1 return _Ed25519PrivateKey(self, evp_pkey) elif key_type == getattr(self._lib, "EVP_PKEY_X448", None): # EVP_PKEY_X448 is not present in OpenSSL < 1.1.1 return _X448PrivateKey(self, evp_pkey) elif key_type == getattr(self._lib, "EVP_PKEY_X25519", None): # EVP_PKEY_X25519 is not present in OpenSSL < 1.1.0 return _X25519PrivateKey(self, evp_pkey) elif key_type == getattr(self._lib, "EVP_PKEY_ED448", None): # EVP_PKEY_ED448 is not present in OpenSSL < 1.1.1 return _Ed448PrivateKey(self, evp_pkey) else: raise UnsupportedAlgorithm("Unsupported key type.") def _evp_pkey_to_public_key(self, evp_pkey): """ Return the appropriate type of PublicKey given an evp_pkey cdata pointer. """ key_type = self._lib.EVP_PKEY_id(evp_pkey) if key_type == self._lib.EVP_PKEY_RSA: rsa_cdata = self._lib.EVP_PKEY_get1_RSA(evp_pkey) self.openssl_assert(rsa_cdata != self._ffi.NULL) rsa_cdata = self._ffi.gc(rsa_cdata, self._lib.RSA_free) return _RSAPublicKey(self, rsa_cdata, evp_pkey) elif key_type == self._lib.EVP_PKEY_DSA: dsa_cdata = self._lib.EVP_PKEY_get1_DSA(evp_pkey) self.openssl_assert(dsa_cdata != self._ffi.NULL) dsa_cdata = self._ffi.gc(dsa_cdata, self._lib.DSA_free) return _DSAPublicKey(self, dsa_cdata, evp_pkey) elif key_type == self._lib.EVP_PKEY_EC: ec_cdata = self._lib.EVP_PKEY_get1_EC_KEY(evp_pkey) self.openssl_assert(ec_cdata != self._ffi.NULL) ec_cdata = self._ffi.gc(ec_cdata, self._lib.EC_KEY_free) return _EllipticCurvePublicKey(self, ec_cdata, evp_pkey) elif key_type in self._dh_types: dh_cdata = self._lib.EVP_PKEY_get1_DH(evp_pkey) self.openssl_assert(dh_cdata != self._ffi.NULL) dh_cdata = self._ffi.gc(dh_cdata, self._lib.DH_free) return _DHPublicKey(self, dh_cdata, evp_pkey) elif key_type == getattr(self._lib, "EVP_PKEY_ED25519", None): # EVP_PKEY_ED25519 is not present in OpenSSL < 1.1.1 return _Ed25519PublicKey(self, evp_pkey) elif key_type == getattr(self._lib, "EVP_PKEY_X448", None): # EVP_PKEY_X448 is not present in OpenSSL < 1.1.1 return _X448PublicKey(self, evp_pkey) elif key_type == getattr(self._lib, "EVP_PKEY_X25519", None): # EVP_PKEY_X25519 is not present in OpenSSL < 1.1.0 return _X25519PublicKey(self, evp_pkey) elif key_type == getattr(self._lib, "EVP_PKEY_ED448", None): # EVP_PKEY_X25519 is not present in OpenSSL < 1.1.1 return _Ed448PublicKey(self, evp_pkey) else: raise UnsupportedAlgorithm("Unsupported key type.") def _oaep_hash_supported(self, algorithm): if self._lib.Cryptography_HAS_RSA_OAEP_MD: return isinstance( algorithm, ( hashes.SHA1, hashes.SHA224, hashes.SHA256, hashes.SHA384, hashes.SHA512, ) ) else: return isinstance(algorithm, hashes.SHA1) def rsa_padding_supported(self, padding): if isinstance(padding, PKCS1v15): return True elif isinstance(padding, PSS) and isinstance(padding._mgf, MGF1): return self.hash_supported(padding._mgf._algorithm) elif isinstance(padding, OAEP) and isinstance(padding._mgf, MGF1): return ( self._oaep_hash_supported(padding._mgf._algorithm) and self._oaep_hash_supported(padding._algorithm) and ( (padding._label is None or len(padding._label) == 0) or self._lib.Cryptography_HAS_RSA_OAEP_LABEL == 1 ) ) else: return False def generate_dsa_parameters(self, key_size): if key_size not in (1024, 2048, 3072): raise ValueError("Key size must be 1024 or 2048 or 3072 bits.") ctx = self._lib.DSA_new() self.openssl_assert(ctx != self._ffi.NULL) ctx = self._ffi.gc(ctx, self._lib.DSA_free) res = self._lib.DSA_generate_parameters_ex( ctx, key_size, self._ffi.NULL, 0, self._ffi.NULL, self._ffi.NULL, self._ffi.NULL ) self.openssl_assert(res == 1) return _DSAParameters(self, ctx) def generate_dsa_private_key(self, parameters): ctx = self._lib.DSAparams_dup(parameters._dsa_cdata) self.openssl_assert(ctx != self._ffi.NULL) ctx = self._ffi.gc(ctx, self._lib.DSA_free) self._lib.DSA_generate_key(ctx) evp_pkey = self._dsa_cdata_to_evp_pkey(ctx) return _DSAPrivateKey(self, ctx, evp_pkey) def generate_dsa_private_key_and_parameters(self, key_size): parameters = self.generate_dsa_parameters(key_size) return self.generate_dsa_private_key(parameters) def _dsa_cdata_set_values(self, dsa_cdata, p, q, g, pub_key, priv_key): res = self._lib.DSA_set0_pqg(dsa_cdata, p, q, g) self.openssl_assert(res == 1) res = self._lib.DSA_set0_key(dsa_cdata, pub_key, priv_key) self.openssl_assert(res == 1) def load_dsa_private_numbers(self, numbers): dsa._check_dsa_private_numbers(numbers) parameter_numbers = numbers.public_numbers.parameter_numbers dsa_cdata = self._lib.DSA_new() self.openssl_assert(dsa_cdata != self._ffi.NULL) dsa_cdata = self._ffi.gc(dsa_cdata, self._lib.DSA_free) p = self._int_to_bn(parameter_numbers.p) q = self._int_to_bn(parameter_numbers.q) g = self._int_to_bn(parameter_numbers.g) pub_key = self._int_to_bn(numbers.public_numbers.y) priv_key = self._int_to_bn(numbers.x) self._dsa_cdata_set_values(dsa_cdata, p, q, g, pub_key, priv_key) evp_pkey = self._dsa_cdata_to_evp_pkey(dsa_cdata) return _DSAPrivateKey(self, dsa_cdata, evp_pkey) def load_dsa_public_numbers(self, numbers): dsa._check_dsa_parameters(numbers.parameter_numbers) dsa_cdata = self._lib.DSA_new() self.openssl_assert(dsa_cdata != self._ffi.NULL) dsa_cdata = self._ffi.gc(dsa_cdata, self._lib.DSA_free) p = self._int_to_bn(numbers.parameter_numbers.p) q = self._int_to_bn(numbers.parameter_numbers.q) g = self._int_to_bn(numbers.parameter_numbers.g) pub_key = self._int_to_bn(numbers.y) priv_key = self._ffi.NULL self._dsa_cdata_set_values(dsa_cdata, p, q, g, pub_key, priv_key) evp_pkey = self._dsa_cdata_to_evp_pkey(dsa_cdata) return _DSAPublicKey(self, dsa_cdata, evp_pkey) def load_dsa_parameter_numbers(self, numbers): dsa._check_dsa_parameters(numbers) dsa_cdata = self._lib.DSA_new() self.openssl_assert(dsa_cdata != self._ffi.NULL) dsa_cdata = self._ffi.gc(dsa_cdata, self._lib.DSA_free) p = self._int_to_bn(numbers.p) q = self._int_to_bn(numbers.q) g = self._int_to_bn(numbers.g) res = self._lib.DSA_set0_pqg(dsa_cdata, p, q, g) self.openssl_assert(res == 1) return _DSAParameters(self, dsa_cdata) def _dsa_cdata_to_evp_pkey(self, dsa_cdata): evp_pkey = self._create_evp_pkey_gc() res = self._lib.EVP_PKEY_set1_DSA(evp_pkey, dsa_cdata) self.openssl_assert(res == 1) return evp_pkey def dsa_hash_supported(self, algorithm): return self.hash_supported(algorithm) def dsa_parameters_supported(self, p, q, g): return True def cmac_algorithm_supported(self, algorithm): return self.cipher_supported( algorithm, CBC(b"\x00" * algorithm.block_size) ) def create_cmac_ctx(self, algorithm): return _CMACContext(self, algorithm) def create_x509_csr(self, builder, private_key, algorithm): if not isinstance(builder, x509.CertificateSigningRequestBuilder): raise TypeError('Builder type mismatch.') if isinstance(private_key, (ed25519.Ed25519PrivateKey, ed448.Ed448PrivateKey)): if algorithm is not None: raise ValueError( "algorithm must be None when signing via ed25519 or ed448" ) elif not isinstance(algorithm, hashes.HashAlgorithm): raise TypeError('Algorithm must be a registered hash algorithm.') elif ( isinstance(algorithm, hashes.MD5) and not isinstance(private_key, rsa.RSAPrivateKey) ): raise ValueError( "MD5 is not a supported hash algorithm for EC/DSA CSRs" ) # Resolve the signature algorithm. evp_md = self._evp_md_x509_null_if_eddsa(private_key, algorithm) # Create an empty request. x509_req = self._lib.X509_REQ_new() self.openssl_assert(x509_req != self._ffi.NULL) x509_req = self._ffi.gc(x509_req, self._lib.X509_REQ_free) # Set x509 version. res = self._lib.X509_REQ_set_version(x509_req, x509.Version.v1.value) self.openssl_assert(res == 1) # Set subject name. res = self._lib.X509_REQ_set_subject_name( x509_req, _encode_name_gc(self, builder._subject_name) ) self.openssl_assert(res == 1) # Set subject public key. public_key = private_key.public_key() res = self._lib.X509_REQ_set_pubkey( x509_req, public_key._evp_pkey ) self.openssl_assert(res == 1) # Add extensions. sk_extension = self._lib.sk_X509_EXTENSION_new_null() self.openssl_assert(sk_extension != self._ffi.NULL) sk_extension = self._ffi.gc( sk_extension, lambda x: self._lib.sk_X509_EXTENSION_pop_free( x, self._ffi.addressof( self._lib._original_lib, "X509_EXTENSION_free" ) ) ) # Don't GC individual extensions because the memory is owned by # sk_extensions and will be freed along with it. self._create_x509_extensions( extensions=builder._extensions, handlers=_EXTENSION_ENCODE_HANDLERS, x509_obj=sk_extension, add_func=self._lib.sk_X509_EXTENSION_insert, gc=False ) res = self._lib.X509_REQ_add_extensions(x509_req, sk_extension) self.openssl_assert(res == 1) # Sign the request using the requester's private key. res = self._lib.X509_REQ_sign( x509_req, private_key._evp_pkey, evp_md ) if res == 0: errors = self._consume_errors() self.openssl_assert( errors[0]._lib_reason_match( self._lib.ERR_LIB_RSA, self._lib.RSA_R_DIGEST_TOO_BIG_FOR_RSA_KEY ) ) raise ValueError("Digest too big for RSA key") return _CertificateSigningRequest(self, x509_req) def create_x509_certificate(self, builder, private_key, algorithm): if not isinstance(builder, x509.CertificateBuilder): raise TypeError('Builder type mismatch.') if isinstance(private_key, (ed25519.Ed25519PrivateKey, ed448.Ed448PrivateKey)): if algorithm is not None: raise ValueError( "algorithm must be None when signing via ed25519 or ed448" ) elif not isinstance(algorithm, hashes.HashAlgorithm): raise TypeError('Algorithm must be a registered hash algorithm.') if ( isinstance(algorithm, hashes.MD5) and not isinstance(private_key, rsa.RSAPrivateKey) ): raise ValueError( "MD5 is only (reluctantly) supported for RSA certificates" ) # Resolve the signature algorithm. evp_md = self._evp_md_x509_null_if_eddsa(private_key, algorithm) # Create an empty certificate. x509_cert = self._lib.X509_new() x509_cert = self._ffi.gc(x509_cert, backend._lib.X509_free) # Set the x509 version. res = self._lib.X509_set_version(x509_cert, builder._version.value) self.openssl_assert(res == 1) # Set the subject's name. res = self._lib.X509_set_subject_name( x509_cert, _encode_name_gc(self, builder._subject_name) ) self.openssl_assert(res == 1) # Set the subject's public key. res = self._lib.X509_set_pubkey( x509_cert, builder._public_key._evp_pkey ) self.openssl_assert(res == 1) # Set the certificate serial number. serial_number = _encode_asn1_int_gc(self, builder._serial_number) res = self._lib.X509_set_serialNumber(x509_cert, serial_number) self.openssl_assert(res == 1) # Set the "not before" time. self._set_asn1_time( self._lib.X509_getm_notBefore(x509_cert), builder._not_valid_before ) # Set the "not after" time. self._set_asn1_time( self._lib.X509_getm_notAfter(x509_cert), builder._not_valid_after ) # Add extensions. self._create_x509_extensions( extensions=builder._extensions, handlers=_EXTENSION_ENCODE_HANDLERS, x509_obj=x509_cert, add_func=self._lib.X509_add_ext, gc=True ) # Set the issuer name. res = self._lib.X509_set_issuer_name( x509_cert, _encode_name_gc(self, builder._issuer_name) ) self.openssl_assert(res == 1) # Sign the certificate with the issuer's private key. res = self._lib.X509_sign( x509_cert, private_key._evp_pkey, evp_md ) if res == 0: errors = self._consume_errors() self.openssl_assert( errors[0]._lib_reason_match( self._lib.ERR_LIB_RSA, self._lib.RSA_R_DIGEST_TOO_BIG_FOR_RSA_KEY ) ) raise ValueError("Digest too big for RSA key") return _Certificate(self, x509_cert) def _evp_md_x509_null_if_eddsa(self, private_key, algorithm): if isinstance(private_key, (ed25519.Ed25519PrivateKey, ed448.Ed448PrivateKey)): # OpenSSL requires us to pass NULL for EVP_MD for ed25519/ed448 return self._ffi.NULL else: return self._evp_md_non_null_from_algorithm(algorithm) def _set_asn1_time(self, asn1_time, time): if time.year >= 2050: asn1_str = time.strftime('%Y%m%d%H%M%SZ').encode('ascii') else: asn1_str = time.strftime('%y%m%d%H%M%SZ').encode('ascii') res = self._lib.ASN1_TIME_set_string(asn1_time, asn1_str) self.openssl_assert(res == 1) def _create_asn1_time(self, time): asn1_time = self._lib.ASN1_TIME_new() self.openssl_assert(asn1_time != self._ffi.NULL) asn1_time = self._ffi.gc(asn1_time, self._lib.ASN1_TIME_free) self._set_asn1_time(asn1_time, time) return asn1_time def create_x509_crl(self, builder, private_key, algorithm): if not isinstance(builder, x509.CertificateRevocationListBuilder): raise TypeError('Builder type mismatch.') if isinstance(private_key, (ed25519.Ed25519PrivateKey, ed448.Ed448PrivateKey)): if algorithm is not None: raise ValueError( "algorithm must be None when signing via ed25519 or ed448" ) elif not isinstance(algorithm, hashes.HashAlgorithm): raise TypeError('Algorithm must be a registered hash algorithm.') if ( isinstance(algorithm, hashes.MD5) and not isinstance(private_key, rsa.RSAPrivateKey) ): raise ValueError( "MD5 is not a supported hash algorithm for EC/DSA CRLs" ) evp_md = self._evp_md_x509_null_if_eddsa(private_key, algorithm) # Create an empty CRL. x509_crl = self._lib.X509_CRL_new() x509_crl = self._ffi.gc(x509_crl, backend._lib.X509_CRL_free) # Set the x509 CRL version. We only support v2 (integer value 1). res = self._lib.X509_CRL_set_version(x509_crl, 1) self.openssl_assert(res == 1) # Set the issuer name. res = self._lib.X509_CRL_set_issuer_name( x509_crl, _encode_name_gc(self, builder._issuer_name) ) self.openssl_assert(res == 1) # Set the last update time. last_update = self._create_asn1_time(builder._last_update) res = self._lib.X509_CRL_set_lastUpdate(x509_crl, last_update) self.openssl_assert(res == 1) # Set the next update time. next_update = self._create_asn1_time(builder._next_update) res = self._lib.X509_CRL_set_nextUpdate(x509_crl, next_update) self.openssl_assert(res == 1) # Add extensions. self._create_x509_extensions( extensions=builder._extensions, handlers=_CRL_EXTENSION_ENCODE_HANDLERS, x509_obj=x509_crl, add_func=self._lib.X509_CRL_add_ext, gc=True ) # add revoked certificates for revoked_cert in builder._revoked_certificates: # Duplicating because the X509_CRL takes ownership and will free # this memory when X509_CRL_free is called. revoked = self._lib.Cryptography_X509_REVOKED_dup( revoked_cert._x509_revoked ) self.openssl_assert(revoked != self._ffi.NULL) res = self._lib.X509_CRL_add0_revoked(x509_crl, revoked) self.openssl_assert(res == 1) res = self._lib.X509_CRL_sign( x509_crl, private_key._evp_pkey, evp_md ) if res == 0: errors = self._consume_errors() self.openssl_assert( errors[0]._lib_reason_match( self._lib.ERR_LIB_RSA, self._lib.RSA_R_DIGEST_TOO_BIG_FOR_RSA_KEY ) ) raise ValueError("Digest too big for RSA key") return _CertificateRevocationList(self, x509_crl) def _create_x509_extensions(self, extensions, handlers, x509_obj, add_func, gc): for i, extension in enumerate(extensions): x509_extension = self._create_x509_extension( handlers, extension ) self.openssl_assert(x509_extension != self._ffi.NULL) if gc: x509_extension = self._ffi.gc( x509_extension, self._lib.X509_EXTENSION_free ) res = add_func(x509_obj, x509_extension, i) self.openssl_assert(res >= 1) def _create_raw_x509_extension(self, extension, value): obj = _txt2obj_gc(self, extension.oid.dotted_string) return self._lib.X509_EXTENSION_create_by_OBJ( self._ffi.NULL, obj, 1 if extension.critical else 0, value ) def _create_x509_extension(self, handlers, extension): if isinstance(extension.value, x509.UnrecognizedExtension): value = _encode_asn1_str_gc(self, extension.value.value) return self._create_raw_x509_extension(extension, value) elif isinstance(extension.value, x509.TLSFeature): asn1 = encode_der( SEQUENCE, *[ encode_der(INTEGER, encode_der_integer(x.value)) for x in extension.value ] ) value = _encode_asn1_str_gc(self, asn1) return self._create_raw_x509_extension(extension, value) elif isinstance(extension.value, x509.PrecertPoison): value = _encode_asn1_str_gc(self, encode_der(NULL)) return self._create_raw_x509_extension(extension, value) else: try: encode = handlers[extension.oid] except KeyError: raise NotImplementedError( 'Extension not supported: {}'.format(extension.oid) ) ext_struct = encode(self, extension.value) nid = self._lib.OBJ_txt2nid( extension.oid.dotted_string.encode("ascii") ) backend.openssl_assert(nid != self._lib.NID_undef) return self._lib.X509V3_EXT_i2d( nid, 1 if extension.critical else 0, ext_struct ) def create_x509_revoked_certificate(self, builder): if not isinstance(builder, x509.RevokedCertificateBuilder): raise TypeError('Builder type mismatch.') x509_revoked = self._lib.X509_REVOKED_new() self.openssl_assert(x509_revoked != self._ffi.NULL) x509_revoked = self._ffi.gc(x509_revoked, self._lib.X509_REVOKED_free) serial_number = _encode_asn1_int_gc(self, builder._serial_number) res = self._lib.X509_REVOKED_set_serialNumber( x509_revoked, serial_number ) self.openssl_assert(res == 1) rev_date = self._create_asn1_time(builder._revocation_date) res = self._lib.X509_REVOKED_set_revocationDate(x509_revoked, rev_date) self.openssl_assert(res == 1) # add CRL entry extensions self._create_x509_extensions( extensions=builder._extensions, handlers=_CRL_ENTRY_EXTENSION_ENCODE_HANDLERS, x509_obj=x509_revoked, add_func=self._lib.X509_REVOKED_add_ext, gc=True ) return _RevokedCertificate(self, None, x509_revoked) def load_pem_private_key(self, data, password): return self._load_key( self._lib.PEM_read_bio_PrivateKey, self._evp_pkey_to_private_key, data, password, ) def load_pem_public_key(self, data): mem_bio = self._bytes_to_bio(data) evp_pkey = self._lib.PEM_read_bio_PUBKEY( mem_bio.bio, self._ffi.NULL, self._ffi.NULL, self._ffi.NULL ) if evp_pkey != self._ffi.NULL: evp_pkey = self._ffi.gc(evp_pkey, self._lib.EVP_PKEY_free) return self._evp_pkey_to_public_key(evp_pkey) else: # It's not a (RSA/DSA/ECDSA) subjectPublicKeyInfo, but we still # need to check to see if it is a pure PKCS1 RSA public key (not # embedded in a subjectPublicKeyInfo) self._consume_errors() res = self._lib.BIO_reset(mem_bio.bio) self.openssl_assert(res == 1) rsa_cdata = self._lib.PEM_read_bio_RSAPublicKey( mem_bio.bio, self._ffi.NULL, self._ffi.NULL, self._ffi.NULL ) if rsa_cdata != self._ffi.NULL: rsa_cdata = self._ffi.gc(rsa_cdata, self._lib.RSA_free) evp_pkey = self._rsa_cdata_to_evp_pkey(rsa_cdata) return _RSAPublicKey(self, rsa_cdata, evp_pkey) else: self._handle_key_loading_error() def load_pem_parameters(self, data): mem_bio = self._bytes_to_bio(data) # only DH is supported currently dh_cdata = self._lib.PEM_read_bio_DHparams( mem_bio.bio, self._ffi.NULL, self._ffi.NULL, self._ffi.NULL) if dh_cdata != self._ffi.NULL: dh_cdata = self._ffi.gc(dh_cdata, self._lib.DH_free) return _DHParameters(self, dh_cdata) else: self._handle_key_loading_error() def load_der_private_key(self, data, password): # OpenSSL has a function called d2i_AutoPrivateKey that in theory # handles this automatically, however it doesn't handle encrypted # private keys. Instead we try to load the key two different ways. # First we'll try to load it as a traditional key. bio_data = self._bytes_to_bio(data) key = self._evp_pkey_from_der_traditional_key(bio_data, password) if key: return self._evp_pkey_to_private_key(key) else: # Finally we try to load it with the method that handles encrypted # PKCS8 properly. return self._load_key( self._lib.d2i_PKCS8PrivateKey_bio, self._evp_pkey_to_private_key, data, password, ) def _evp_pkey_from_der_traditional_key(self, bio_data, password): key = self._lib.d2i_PrivateKey_bio(bio_data.bio, self._ffi.NULL) if key != self._ffi.NULL: key = self._ffi.gc(key, self._lib.EVP_PKEY_free) if password is not None: raise TypeError( "Password was given but private key is not encrypted." ) return key else: self._consume_errors() return None def load_der_public_key(self, data): mem_bio = self._bytes_to_bio(data) evp_pkey = self._lib.d2i_PUBKEY_bio(mem_bio.bio, self._ffi.NULL) if evp_pkey != self._ffi.NULL: evp_pkey = self._ffi.gc(evp_pkey, self._lib.EVP_PKEY_free) return self._evp_pkey_to_public_key(evp_pkey) else: # It's not a (RSA/DSA/ECDSA) subjectPublicKeyInfo, but we still # need to check to see if it is a pure PKCS1 RSA public key (not # embedded in a subjectPublicKeyInfo) self._consume_errors() res = self._lib.BIO_reset(mem_bio.bio) self.openssl_assert(res == 1) rsa_cdata = self._lib.d2i_RSAPublicKey_bio( mem_bio.bio, self._ffi.NULL ) if rsa_cdata != self._ffi.NULL: rsa_cdata = self._ffi.gc(rsa_cdata, self._lib.RSA_free) evp_pkey = self._rsa_cdata_to_evp_pkey(rsa_cdata) return _RSAPublicKey(self, rsa_cdata, evp_pkey) else: self._handle_key_loading_error() def load_der_parameters(self, data): mem_bio = self._bytes_to_bio(data) dh_cdata = self._lib.d2i_DHparams_bio( mem_bio.bio, self._ffi.NULL ) if dh_cdata != self._ffi.NULL: dh_cdata = self._ffi.gc(dh_cdata, self._lib.DH_free) return _DHParameters(self, dh_cdata) elif self._lib.Cryptography_HAS_EVP_PKEY_DHX: # We check to see if the is dhx. self._consume_errors() res = self._lib.BIO_reset(mem_bio.bio) self.openssl_assert(res == 1) dh_cdata = self._lib.Cryptography_d2i_DHxparams_bio( mem_bio.bio, self._ffi.NULL ) if dh_cdata != self._ffi.NULL: dh_cdata = self._ffi.gc(dh_cdata, self._lib.DH_free) return _DHParameters(self, dh_cdata) self._handle_key_loading_error() def load_pem_x509_certificate(self, data): mem_bio = self._bytes_to_bio(data) x509 = self._lib.PEM_read_bio_X509( mem_bio.bio, self._ffi.NULL, self._ffi.NULL, self._ffi.NULL ) if x509 == self._ffi.NULL: self._consume_errors() raise ValueError( "Unable to load certificate. See https://cryptography.io/en/la" "test/faq/#why-can-t-i-import-my-pem-file for more details." ) x509 = self._ffi.gc(x509, self._lib.X509_free) return _Certificate(self, x509) def load_der_x509_certificate(self, data): mem_bio = self._bytes_to_bio(data) x509 = self._lib.d2i_X509_bio(mem_bio.bio, self._ffi.NULL) if x509 == self._ffi.NULL: self._consume_errors() raise ValueError("Unable to load certificate") x509 = self._ffi.gc(x509, self._lib.X509_free) return _Certificate(self, x509) def load_pem_x509_crl(self, data): mem_bio = self._bytes_to_bio(data) x509_crl = self._lib.PEM_read_bio_X509_CRL( mem_bio.bio, self._ffi.NULL, self._ffi.NULL, self._ffi.NULL ) if x509_crl == self._ffi.NULL: self._consume_errors() raise ValueError( "Unable to load CRL. See https://cryptography.io/en/la" "test/faq/#why-can-t-i-import-my-pem-file for more details." ) x509_crl = self._ffi.gc(x509_crl, self._lib.X509_CRL_free) return _CertificateRevocationList(self, x509_crl) def load_der_x509_crl(self, data): mem_bio = self._bytes_to_bio(data) x509_crl = self._lib.d2i_X509_CRL_bio(mem_bio.bio, self._ffi.NULL) if x509_crl == self._ffi.NULL: self._consume_errors() raise ValueError("Unable to load CRL") x509_crl = self._ffi.gc(x509_crl, self._lib.X509_CRL_free) return _CertificateRevocationList(self, x509_crl) def load_pem_x509_csr(self, data): mem_bio = self._bytes_to_bio(data) x509_req = self._lib.PEM_read_bio_X509_REQ( mem_bio.bio, self._ffi.NULL, self._ffi.NULL, self._ffi.NULL ) if x509_req == self._ffi.NULL: self._consume_errors() raise ValueError( "Unable to load request. See https://cryptography.io/en/la" "test/faq/#why-can-t-i-import-my-pem-file for more details." ) x509_req = self._ffi.gc(x509_req, self._lib.X509_REQ_free) return _CertificateSigningRequest(self, x509_req) def load_der_x509_csr(self, data): mem_bio = self._bytes_to_bio(data) x509_req = self._lib.d2i_X509_REQ_bio(mem_bio.bio, self._ffi.NULL) if x509_req == self._ffi.NULL: self._consume_errors() raise ValueError("Unable to load request") x509_req = self._ffi.gc(x509_req, self._lib.X509_REQ_free) return _CertificateSigningRequest(self, x509_req) def _load_key(self, openssl_read_func, convert_func, data, password): mem_bio = self._bytes_to_bio(data) userdata = self._ffi.new("CRYPTOGRAPHY_PASSWORD_DATA *") if password is not None: utils._check_byteslike("password", password) password_ptr = self._ffi.from_buffer(password) userdata.password = password_ptr userdata.length = len(password) evp_pkey = openssl_read_func( mem_bio.bio, self._ffi.NULL, self._ffi.addressof( self._lib._original_lib, "Cryptography_pem_password_cb" ), userdata, ) if evp_pkey == self._ffi.NULL: if userdata.error != 0: errors = self._consume_errors() self.openssl_assert(errors) if userdata.error == -1: raise TypeError( "Password was not given but private key is encrypted" ) else: assert userdata.error == -2 raise ValueError( "Passwords longer than {} bytes are not supported " "by this backend.".format(userdata.maxsize - 1) ) else: self._handle_key_loading_error() evp_pkey = self._ffi.gc(evp_pkey, self._lib.EVP_PKEY_free) if password is not None and userdata.called == 0: raise TypeError( "Password was given but private key is not encrypted.") assert ( (password is not None and userdata.called == 1) or password is None ) return convert_func(evp_pkey) def _handle_key_loading_error(self): errors = self._consume_errors() if not errors: raise ValueError("Could not deserialize key data.") elif ( errors[0]._lib_reason_match( self._lib.ERR_LIB_EVP, self._lib.EVP_R_BAD_DECRYPT ) or errors[0]._lib_reason_match( self._lib.ERR_LIB_PKCS12, self._lib.PKCS12_R_PKCS12_CIPHERFINAL_ERROR ) ): raise ValueError("Bad decrypt. Incorrect password?") elif ( errors[0]._lib_reason_match( self._lib.ERR_LIB_EVP, self._lib.EVP_R_UNKNOWN_PBE_ALGORITHM ) or errors[0]._lib_reason_match( self._lib.ERR_LIB_PEM, self._lib.PEM_R_UNSUPPORTED_ENCRYPTION ) ): raise UnsupportedAlgorithm( "PEM data is encrypted with an unsupported cipher", _Reasons.UNSUPPORTED_CIPHER ) elif any( error._lib_reason_match( self._lib.ERR_LIB_EVP, self._lib.EVP_R_UNSUPPORTED_PRIVATE_KEY_ALGORITHM ) for error in errors ): raise ValueError("Unsupported public key algorithm.") else: assert errors[0].lib in ( self._lib.ERR_LIB_EVP, self._lib.ERR_LIB_PEM, self._lib.ERR_LIB_ASN1, ) raise ValueError("Could not deserialize key data.") def elliptic_curve_supported(self, curve): try: curve_nid = self._elliptic_curve_to_nid(curve) except UnsupportedAlgorithm: curve_nid = self._lib.NID_undef group = self._lib.EC_GROUP_new_by_curve_name(curve_nid) if group == self._ffi.NULL: errors = self._consume_errors() self.openssl_assert( curve_nid == self._lib.NID_undef or errors[0]._lib_reason_match( self._lib.ERR_LIB_EC, self._lib.EC_R_UNKNOWN_GROUP ) ) return False else: self.openssl_assert(curve_nid != self._lib.NID_undef) self._lib.EC_GROUP_free(group) return True def elliptic_curve_signature_algorithm_supported( self, signature_algorithm, curve ): # We only support ECDSA right now. if not isinstance(signature_algorithm, ec.ECDSA): return False return self.elliptic_curve_supported(curve) def generate_elliptic_curve_private_key(self, curve): """ Generate a new private key on the named curve. """ if self.elliptic_curve_supported(curve): ec_cdata = self._ec_key_new_by_curve(curve) res = self._lib.EC_KEY_generate_key(ec_cdata) self.openssl_assert(res == 1) evp_pkey = self._ec_cdata_to_evp_pkey(ec_cdata) return _EllipticCurvePrivateKey(self, ec_cdata, evp_pkey) else: raise UnsupportedAlgorithm( "Backend object does not support {}.".format(curve.name), _Reasons.UNSUPPORTED_ELLIPTIC_CURVE ) def load_elliptic_curve_private_numbers(self, numbers): public = numbers.public_numbers ec_cdata = self._ec_key_new_by_curve(public.curve) private_value = self._ffi.gc( self._int_to_bn(numbers.private_value), self._lib.BN_clear_free ) res = self._lib.EC_KEY_set_private_key(ec_cdata, private_value) self.openssl_assert(res == 1) ec_cdata = self._ec_key_set_public_key_affine_coordinates( ec_cdata, public.x, public.y) evp_pkey = self._ec_cdata_to_evp_pkey(ec_cdata) return _EllipticCurvePrivateKey(self, ec_cdata, evp_pkey) def load_elliptic_curve_public_numbers(self, numbers): ec_cdata = self._ec_key_new_by_curve(numbers.curve) ec_cdata = self._ec_key_set_public_key_affine_coordinates( ec_cdata, numbers.x, numbers.y) evp_pkey = self._ec_cdata_to_evp_pkey(ec_cdata) return _EllipticCurvePublicKey(self, ec_cdata, evp_pkey) def load_elliptic_curve_public_bytes(self, curve, point_bytes): ec_cdata = self._ec_key_new_by_curve(curve) group = self._lib.EC_KEY_get0_group(ec_cdata) self.openssl_assert(group != self._ffi.NULL) point = self._lib.EC_POINT_new(group) self.openssl_assert(point != self._ffi.NULL) point = self._ffi.gc(point, self._lib.EC_POINT_free) with self._tmp_bn_ctx() as bn_ctx: res = self._lib.EC_POINT_oct2point( group, point, point_bytes, len(point_bytes), bn_ctx ) if res != 1: self._consume_errors() raise ValueError("Invalid public bytes for the given curve") res = self._lib.EC_KEY_set_public_key(ec_cdata, point) self.openssl_assert(res == 1) evp_pkey = self._ec_cdata_to_evp_pkey(ec_cdata) return _EllipticCurvePublicKey(self, ec_cdata, evp_pkey) def derive_elliptic_curve_private_key(self, private_value, curve): ec_cdata = self._ec_key_new_by_curve(curve) get_func, group = self._ec_key_determine_group_get_func(ec_cdata) point = self._lib.EC_POINT_new(group) self.openssl_assert(point != self._ffi.NULL) point = self._ffi.gc(point, self._lib.EC_POINT_free) value = self._int_to_bn(private_value) value = self._ffi.gc(value, self._lib.BN_clear_free) with self._tmp_bn_ctx() as bn_ctx: res = self._lib.EC_POINT_mul(group, point, value, self._ffi.NULL, self._ffi.NULL, bn_ctx) self.openssl_assert(res == 1) bn_x = self._lib.BN_CTX_get(bn_ctx) bn_y = self._lib.BN_CTX_get(bn_ctx) res = get_func(group, point, bn_x, bn_y, bn_ctx) self.openssl_assert(res == 1) res = self._lib.EC_KEY_set_public_key(ec_cdata, point) self.openssl_assert(res == 1) private = self._int_to_bn(private_value) private = self._ffi.gc(private, self._lib.BN_clear_free) res = self._lib.EC_KEY_set_private_key(ec_cdata, private) self.openssl_assert(res == 1) evp_pkey = self._ec_cdata_to_evp_pkey(ec_cdata) return _EllipticCurvePrivateKey(self, ec_cdata, evp_pkey) def _ec_key_new_by_curve(self, curve): curve_nid = self._elliptic_curve_to_nid(curve) ec_cdata = self._lib.EC_KEY_new_by_curve_name(curve_nid) self.openssl_assert(ec_cdata != self._ffi.NULL) return self._ffi.gc(ec_cdata, self._lib.EC_KEY_free) def load_der_ocsp_request(self, data): mem_bio = self._bytes_to_bio(data) request = self._lib.d2i_OCSP_REQUEST_bio(mem_bio.bio, self._ffi.NULL) if request == self._ffi.NULL: self._consume_errors() raise ValueError("Unable to load OCSP request") request = self._ffi.gc(request, self._lib.OCSP_REQUEST_free) return _OCSPRequest(self, request) def load_der_ocsp_response(self, data): mem_bio = self._bytes_to_bio(data) response = self._lib.d2i_OCSP_RESPONSE_bio(mem_bio.bio, self._ffi.NULL) if response == self._ffi.NULL: self._consume_errors() raise ValueError("Unable to load OCSP response") response = self._ffi.gc(response, self._lib.OCSP_RESPONSE_free) return _OCSPResponse(self, response) def create_ocsp_request(self, builder): ocsp_req = self._lib.OCSP_REQUEST_new() self.openssl_assert(ocsp_req != self._ffi.NULL) ocsp_req = self._ffi.gc(ocsp_req, self._lib.OCSP_REQUEST_free) cert, issuer, algorithm = builder._request evp_md = self._evp_md_non_null_from_algorithm(algorithm) certid = self._lib.OCSP_cert_to_id( evp_md, cert._x509, issuer._x509 ) self.openssl_assert(certid != self._ffi.NULL) onereq = self._lib.OCSP_request_add0_id(ocsp_req, certid) self.openssl_assert(onereq != self._ffi.NULL) self._create_x509_extensions( extensions=builder._extensions, handlers=_OCSP_REQUEST_EXTENSION_ENCODE_HANDLERS, x509_obj=ocsp_req, add_func=self._lib.OCSP_REQUEST_add_ext, gc=True, ) return _OCSPRequest(self, ocsp_req) def _create_ocsp_basic_response(self, builder, private_key, algorithm): basic = self._lib.OCSP_BASICRESP_new() self.openssl_assert(basic != self._ffi.NULL) basic = self._ffi.gc(basic, self._lib.OCSP_BASICRESP_free) evp_md = self._evp_md_non_null_from_algorithm( builder._response._algorithm ) certid = self._lib.OCSP_cert_to_id( evp_md, builder._response._cert._x509, builder._response._issuer._x509 ) self.openssl_assert(certid != self._ffi.NULL) certid = self._ffi.gc(certid, self._lib.OCSP_CERTID_free) if builder._response._revocation_reason is None: reason = -1 else: reason = _CRL_ENTRY_REASON_ENUM_TO_CODE[ builder._response._revocation_reason ] if builder._response._revocation_time is None: rev_time = self._ffi.NULL else: rev_time = self._create_asn1_time( builder._response._revocation_time ) next_update = self._ffi.NULL if builder._response._next_update is not None: next_update = self._create_asn1_time( builder._response._next_update ) this_update = self._create_asn1_time(builder._response._this_update) res = self._lib.OCSP_basic_add1_status( basic, certid, builder._response._cert_status.value, reason, rev_time, this_update, next_update ) self.openssl_assert(res != self._ffi.NULL) # okay, now sign the basic structure evp_md = self._evp_md_x509_null_if_eddsa(private_key, algorithm) responder_cert, responder_encoding = builder._responder_id flags = self._lib.OCSP_NOCERTS if responder_encoding is ocsp.OCSPResponderEncoding.HASH: flags |= self._lib.OCSP_RESPID_KEY if builder._certs is not None: for cert in builder._certs: res = self._lib.OCSP_basic_add1_cert(basic, cert._x509) self.openssl_assert(res == 1) self._create_x509_extensions( extensions=builder._extensions, handlers=_OCSP_BASICRESP_EXTENSION_ENCODE_HANDLERS, x509_obj=basic, add_func=self._lib.OCSP_BASICRESP_add_ext, gc=True, ) res = self._lib.OCSP_basic_sign( basic, responder_cert._x509, private_key._evp_pkey, evp_md, self._ffi.NULL, flags ) if res != 1: errors = self._consume_errors() self.openssl_assert( errors[0]._lib_reason_match( self._lib.ERR_LIB_X509, self._lib.X509_R_KEY_VALUES_MISMATCH ) ) raise ValueError("responder_cert must be signed by private_key") return basic def create_ocsp_response(self, response_status, builder, private_key, algorithm): if response_status is ocsp.OCSPResponseStatus.SUCCESSFUL: basic = self._create_ocsp_basic_response( builder, private_key, algorithm ) else: basic = self._ffi.NULL ocsp_resp = self._lib.OCSP_response_create( response_status.value, basic ) self.openssl_assert(ocsp_resp != self._ffi.NULL) ocsp_resp = self._ffi.gc(ocsp_resp, self._lib.OCSP_RESPONSE_free) return _OCSPResponse(self, ocsp_resp) def elliptic_curve_exchange_algorithm_supported(self, algorithm, curve): return ( self.elliptic_curve_supported(curve) and isinstance(algorithm, ec.ECDH) ) def _ec_cdata_to_evp_pkey(self, ec_cdata): evp_pkey = self._create_evp_pkey_gc() res = self._lib.EVP_PKEY_set1_EC_KEY(evp_pkey, ec_cdata) self.openssl_assert(res == 1) return evp_pkey def _elliptic_curve_to_nid(self, curve): """ Get the NID for a curve name. """ curve_aliases = { "secp192r1": "prime192v1", "secp256r1": "prime256v1" } curve_name = curve_aliases.get(curve.name, curve.name) curve_nid = self._lib.OBJ_sn2nid(curve_name.encode()) if curve_nid == self._lib.NID_undef: raise UnsupportedAlgorithm( "{} is not a supported elliptic curve".format(curve.name), _Reasons.UNSUPPORTED_ELLIPTIC_CURVE ) return curve_nid @contextmanager def _tmp_bn_ctx(self): bn_ctx = self._lib.BN_CTX_new() self.openssl_assert(bn_ctx != self._ffi.NULL) bn_ctx = self._ffi.gc(bn_ctx, self._lib.BN_CTX_free) self._lib.BN_CTX_start(bn_ctx) try: yield bn_ctx finally: self._lib.BN_CTX_end(bn_ctx) def _ec_key_determine_group_get_func(self, ctx): """ Given an EC_KEY determine the group and what function is required to get point coordinates. """ self.openssl_assert(ctx != self._ffi.NULL) nid_two_field = self._lib.OBJ_sn2nid(b"characteristic-two-field") self.openssl_assert(nid_two_field != self._lib.NID_undef) group = self._lib.EC_KEY_get0_group(ctx) self.openssl_assert(group != self._ffi.NULL) method = self._lib.EC_GROUP_method_of(group) self.openssl_assert(method != self._ffi.NULL) nid = self._lib.EC_METHOD_get_field_type(method) self.openssl_assert(nid != self._lib.NID_undef) if nid == nid_two_field and self._lib.Cryptography_HAS_EC2M: get_func = self._lib.EC_POINT_get_affine_coordinates_GF2m else: get_func = self._lib.EC_POINT_get_affine_coordinates_GFp assert get_func return get_func, group def _ec_key_set_public_key_affine_coordinates(self, ctx, x, y): """ Sets the public key point in the EC_KEY context to the affine x and y values. """ if x < 0 or y < 0: raise ValueError( "Invalid EC key. Both x and y must be non-negative." ) x = self._ffi.gc(self._int_to_bn(x), self._lib.BN_free) y = self._ffi.gc(self._int_to_bn(y), self._lib.BN_free) res = self._lib.EC_KEY_set_public_key_affine_coordinates(ctx, x, y) if res != 1: self._consume_errors() raise ValueError("Invalid EC key.") return ctx def _private_key_bytes(self, encoding, format, encryption_algorithm, evp_pkey, cdata): if not isinstance(format, serialization.PrivateFormat): raise TypeError( "format must be an item from the PrivateFormat enum" ) # X9.62 encoding is only valid for EC public keys if encoding is serialization.Encoding.X962: raise ValueError("X9.62 format is only valid for EC public keys") # Raw format and encoding are only valid for X25519, Ed25519, X448, and # Ed448 keys. We capture those cases before this method is called so if # we see those enum values here it means the caller has passed them to # a key that doesn't support raw type if format is serialization.PrivateFormat.Raw: raise ValueError("raw format is invalid with this key or encoding") if encoding is serialization.Encoding.Raw: raise ValueError("raw encoding is invalid with this key or format") if not isinstance(encryption_algorithm, serialization.KeySerializationEncryption): raise TypeError( "Encryption algorithm must be a KeySerializationEncryption " "instance" ) if isinstance(encryption_algorithm, serialization.NoEncryption): password = b"" passlen = 0 evp_cipher = self._ffi.NULL elif isinstance(encryption_algorithm, serialization.BestAvailableEncryption): # This is a curated value that we will update over time. evp_cipher = self._lib.EVP_get_cipherbyname( b"aes-256-cbc" ) password = encryption_algorithm.password passlen = len(password) if passlen > 1023: raise ValueError( "Passwords longer than 1023 bytes are not supported by " "this backend" ) else: raise ValueError("Unsupported encryption type") key_type = self._lib.EVP_PKEY_id(evp_pkey) if encoding is serialization.Encoding.PEM: if format is serialization.PrivateFormat.PKCS8: write_bio = self._lib.PEM_write_bio_PKCS8PrivateKey key = evp_pkey else: assert format is serialization.PrivateFormat.TraditionalOpenSSL if key_type == self._lib.EVP_PKEY_RSA: write_bio = self._lib.PEM_write_bio_RSAPrivateKey elif key_type == self._lib.EVP_PKEY_DSA: write_bio = self._lib.PEM_write_bio_DSAPrivateKey else: assert key_type == self._lib.EVP_PKEY_EC write_bio = self._lib.PEM_write_bio_ECPrivateKey key = cdata elif encoding is serialization.Encoding.DER: if format is serialization.PrivateFormat.TraditionalOpenSSL: if not isinstance( encryption_algorithm, serialization.NoEncryption ): raise ValueError( "Encryption is not supported for DER encoded " "traditional OpenSSL keys" ) return self._private_key_bytes_traditional_der(key_type, cdata) else: assert format is serialization.PrivateFormat.PKCS8 write_bio = self._lib.i2d_PKCS8PrivateKey_bio key = evp_pkey else: raise TypeError("encoding must be Encoding.PEM or Encoding.DER") bio = self._create_mem_bio_gc() res = write_bio( bio, key, evp_cipher, password, passlen, self._ffi.NULL, self._ffi.NULL ) self.openssl_assert(res == 1) return self._read_mem_bio(bio) def _private_key_bytes_traditional_der(self, key_type, cdata): if key_type == self._lib.EVP_PKEY_RSA: write_bio = self._lib.i2d_RSAPrivateKey_bio elif key_type == self._lib.EVP_PKEY_EC: write_bio = self._lib.i2d_ECPrivateKey_bio else: self.openssl_assert(key_type == self._lib.EVP_PKEY_DSA) write_bio = self._lib.i2d_DSAPrivateKey_bio bio = self._create_mem_bio_gc() res = write_bio(bio, cdata) self.openssl_assert(res == 1) return self._read_mem_bio(bio) def _public_key_bytes(self, encoding, format, key, evp_pkey, cdata): if not isinstance(encoding, serialization.Encoding): raise TypeError("encoding must be an item from the Encoding enum") # Compressed/UncompressedPoint are only valid for EC keys and those # cases are handled by the ECPublicKey public_bytes method before this # method is called if format in (serialization.PublicFormat.UncompressedPoint, serialization.PublicFormat.CompressedPoint): raise ValueError("Point formats are not valid for this key type") # Raw format and encoding are only valid for X25519, Ed25519, X448, and # Ed448 keys. We capture those cases before this method is called so if # we see those enum values here it means the caller has passed them to # a key that doesn't support raw type if format is serialization.PublicFormat.Raw: raise ValueError("raw format is invalid with this key or encoding") if encoding is serialization.Encoding.Raw: raise ValueError("raw encoding is invalid with this key or format") if ( format is serialization.PublicFormat.OpenSSH or encoding is serialization.Encoding.OpenSSH ): if ( format is not serialization.PublicFormat.OpenSSH or encoding is not serialization.Encoding.OpenSSH ): raise ValueError( "OpenSSH format must be used with OpenSSH encoding" ) return self._openssh_public_key_bytes(key) elif format is serialization.PublicFormat.SubjectPublicKeyInfo: if encoding is serialization.Encoding.PEM: write_bio = self._lib.PEM_write_bio_PUBKEY else: assert encoding is serialization.Encoding.DER write_bio = self._lib.i2d_PUBKEY_bio key = evp_pkey elif format is serialization.PublicFormat.PKCS1: # Only RSA is supported here. assert self._lib.EVP_PKEY_id(evp_pkey) == self._lib.EVP_PKEY_RSA if encoding is serialization.Encoding.PEM: write_bio = self._lib.PEM_write_bio_RSAPublicKey else: assert encoding is serialization.Encoding.DER write_bio = self._lib.i2d_RSAPublicKey_bio key = cdata else: raise TypeError( "format must be an item from the PublicFormat enum" ) bio = self._create_mem_bio_gc() res = write_bio(bio, key) self.openssl_assert(res == 1) return self._read_mem_bio(bio) def _openssh_public_key_bytes(self, key): if isinstance(key, rsa.RSAPublicKey): public_numbers = key.public_numbers() return b"ssh-rsa " + base64.b64encode( ssh._ssh_write_string(b"ssh-rsa") + ssh._ssh_write_mpint(public_numbers.e) + ssh._ssh_write_mpint(public_numbers.n) ) elif isinstance(key, dsa.DSAPublicKey): public_numbers = key.public_numbers() parameter_numbers = public_numbers.parameter_numbers return b"ssh-dss " + base64.b64encode( ssh._ssh_write_string(b"ssh-dss") + ssh._ssh_write_mpint(parameter_numbers.p) + ssh._ssh_write_mpint(parameter_numbers.q) + ssh._ssh_write_mpint(parameter_numbers.g) + ssh._ssh_write_mpint(public_numbers.y) ) elif isinstance(key, ed25519.Ed25519PublicKey): raw_bytes = key.public_bytes(serialization.Encoding.Raw, serialization.PublicFormat.Raw) return b"ssh-ed25519 " + base64.b64encode( ssh._ssh_write_string(b"ssh-ed25519") + ssh._ssh_write_string(raw_bytes) ) elif isinstance(key, ec.EllipticCurvePublicKey): public_numbers = key.public_numbers() try: curve_name = { ec.SECP256R1: b"nistp256", ec.SECP384R1: b"nistp384", ec.SECP521R1: b"nistp521", }[type(public_numbers.curve)] except KeyError: raise ValueError( "Only SECP256R1, SECP384R1, and SECP521R1 curves are " "supported by the SSH public key format" ) point = key.public_bytes( serialization.Encoding.X962, serialization.PublicFormat.UncompressedPoint ) return b"ecdsa-sha2-" + curve_name + b" " + base64.b64encode( ssh._ssh_write_string(b"ecdsa-sha2-" + curve_name) + ssh._ssh_write_string(curve_name) + ssh._ssh_write_string(point) ) else: raise ValueError( "OpenSSH encoding is not supported for this key type" ) def _parameter_bytes(self, encoding, format, cdata): if encoding is serialization.Encoding.OpenSSH: raise TypeError( "OpenSSH encoding is not supported" ) # Only DH is supported here currently. q = self._ffi.new("BIGNUM **") self._lib.DH_get0_pqg(cdata, self._ffi.NULL, q, self._ffi.NULL) if encoding is serialization.Encoding.PEM: if q[0] != self._ffi.NULL: write_bio = self._lib.PEM_write_bio_DHxparams else: write_bio = self._lib.PEM_write_bio_DHparams elif encoding is serialization.Encoding.DER: if q[0] != self._ffi.NULL: write_bio = self._lib.Cryptography_i2d_DHxparams_bio else: write_bio = self._lib.i2d_DHparams_bio else: raise TypeError("encoding must be an item from the Encoding enum") bio = self._create_mem_bio_gc() res = write_bio(bio, cdata) self.openssl_assert(res == 1) return self._read_mem_bio(bio) def generate_dh_parameters(self, generator, key_size): if key_size < 512: raise ValueError("DH key_size must be at least 512 bits") if generator not in (2, 5): raise ValueError("DH generator must be 2 or 5") dh_param_cdata = self._lib.DH_new() self.openssl_assert(dh_param_cdata != self._ffi.NULL) dh_param_cdata = self._ffi.gc(dh_param_cdata, self._lib.DH_free) res = self._lib.DH_generate_parameters_ex( dh_param_cdata, key_size, generator, self._ffi.NULL ) self.openssl_assert(res == 1) return _DHParameters(self, dh_param_cdata) def _dh_cdata_to_evp_pkey(self, dh_cdata): evp_pkey = self._create_evp_pkey_gc() res = self._lib.EVP_PKEY_set1_DH(evp_pkey, dh_cdata) self.openssl_assert(res == 1) return evp_pkey def generate_dh_private_key(self, parameters): dh_key_cdata = _dh_params_dup(parameters._dh_cdata, self) res = self._lib.DH_generate_key(dh_key_cdata) self.openssl_assert(res == 1) evp_pkey = self._dh_cdata_to_evp_pkey(dh_key_cdata) return _DHPrivateKey(self, dh_key_cdata, evp_pkey) def generate_dh_private_key_and_parameters(self, generator, key_size): return self.generate_dh_private_key( self.generate_dh_parameters(generator, key_size)) def load_dh_private_numbers(self, numbers): parameter_numbers = numbers.public_numbers.parameter_numbers dh_cdata = self._lib.DH_new() self.openssl_assert(dh_cdata != self._ffi.NULL) dh_cdata = self._ffi.gc(dh_cdata, self._lib.DH_free) p = self._int_to_bn(parameter_numbers.p) g = self._int_to_bn(parameter_numbers.g) if parameter_numbers.q is not None: q = self._int_to_bn(parameter_numbers.q) else: q = self._ffi.NULL pub_key = self._int_to_bn(numbers.public_numbers.y) priv_key = self._int_to_bn(numbers.x) res = self._lib.DH_set0_pqg(dh_cdata, p, q, g) self.openssl_assert(res == 1) res = self._lib.DH_set0_key(dh_cdata, pub_key, priv_key) self.openssl_assert(res == 1) codes = self._ffi.new("int[]", 1) res = self._lib.Cryptography_DH_check(dh_cdata, codes) self.openssl_assert(res == 1) # DH_check will return DH_NOT_SUITABLE_GENERATOR if p % 24 does not # equal 11 when the generator is 2 (a quadratic nonresidue). # We want to ignore that error because p % 24 == 23 is also fine. # Specifically, g is then a quadratic residue. Within the context of # Diffie-Hellman this means it can only generate half the possible # values. That sounds bad, but quadratic nonresidues leak a bit of # the key to the attacker in exchange for having the full key space # available. See: https://crypto.stackexchange.com/questions/12961 if codes[0] != 0 and not ( parameter_numbers.g == 2 and codes[0] ^ self._lib.DH_NOT_SUITABLE_GENERATOR == 0 ): raise ValueError( "DH private numbers did not pass safety checks." ) evp_pkey = self._dh_cdata_to_evp_pkey(dh_cdata) return _DHPrivateKey(self, dh_cdata, evp_pkey) def load_dh_public_numbers(self, numbers): dh_cdata = self._lib.DH_new() self.openssl_assert(dh_cdata != self._ffi.NULL) dh_cdata = self._ffi.gc(dh_cdata, self._lib.DH_free) parameter_numbers = numbers.parameter_numbers p = self._int_to_bn(parameter_numbers.p) g = self._int_to_bn(parameter_numbers.g) if parameter_numbers.q is not None: q = self._int_to_bn(parameter_numbers.q) else: q = self._ffi.NULL pub_key = self._int_to_bn(numbers.y) res = self._lib.DH_set0_pqg(dh_cdata, p, q, g) self.openssl_assert(res == 1) res = self._lib.DH_set0_key(dh_cdata, pub_key, self._ffi.NULL) self.openssl_assert(res == 1) evp_pkey = self._dh_cdata_to_evp_pkey(dh_cdata) return _DHPublicKey(self, dh_cdata, evp_pkey) def load_dh_parameter_numbers(self, numbers): dh_cdata = self._lib.DH_new() self.openssl_assert(dh_cdata != self._ffi.NULL) dh_cdata = self._ffi.gc(dh_cdata, self._lib.DH_free) p = self._int_to_bn(numbers.p) g = self._int_to_bn(numbers.g) if numbers.q is not None: q = self._int_to_bn(numbers.q) else: q = self._ffi.NULL res = self._lib.DH_set0_pqg(dh_cdata, p, q, g) self.openssl_assert(res == 1) return _DHParameters(self, dh_cdata) def dh_parameters_supported(self, p, g, q=None): dh_cdata = self._lib.DH_new() self.openssl_assert(dh_cdata != self._ffi.NULL) dh_cdata = self._ffi.gc(dh_cdata, self._lib.DH_free) p = self._int_to_bn(p) g = self._int_to_bn(g) if q is not None: q = self._int_to_bn(q) else: q = self._ffi.NULL res = self._lib.DH_set0_pqg(dh_cdata, p, q, g) self.openssl_assert(res == 1) codes = self._ffi.new("int[]", 1) res = self._lib.Cryptography_DH_check(dh_cdata, codes) self.openssl_assert(res == 1) return codes[0] == 0 def dh_x942_serialization_supported(self): return self._lib.Cryptography_HAS_EVP_PKEY_DHX == 1 def x509_name_bytes(self, name): x509_name = _encode_name_gc(self, name) pp = self._ffi.new("unsigned char **") res = self._lib.i2d_X509_NAME(x509_name, pp) self.openssl_assert(pp[0] != self._ffi.NULL) pp = self._ffi.gc( pp, lambda pointer: self._lib.OPENSSL_free(pointer[0]) ) self.openssl_assert(res > 0) return self._ffi.buffer(pp[0], res)[:] def x25519_load_public_bytes(self, data): # When we drop support for CRYPTOGRAPHY_OPENSSL_LESS_THAN_111 we can # switch this to EVP_PKEY_new_raw_public_key if len(data) != 32: raise ValueError("An X25519 public key is 32 bytes long") evp_pkey = self._create_evp_pkey_gc() res = self._lib.EVP_PKEY_set_type(evp_pkey, self._lib.NID_X25519) backend.openssl_assert(res == 1) res = self._lib.EVP_PKEY_set1_tls_encodedpoint( evp_pkey, data, len(data) ) backend.openssl_assert(res == 1) return _X25519PublicKey(self, evp_pkey) def x25519_load_private_bytes(self, data): # When we drop support for CRYPTOGRAPHY_OPENSSL_LESS_THAN_111 we can # switch this to EVP_PKEY_new_raw_private_key and drop the # zeroed_bytearray garbage. # OpenSSL only has facilities for loading PKCS8 formatted private # keys using the algorithm identifiers specified in # https://tools.ietf.org/html/draft-ietf-curdle-pkix-09. # This is the standard PKCS8 prefix for a 32 byte X25519 key. # The form is: # 0:d=0 hl=2 l= 46 cons: SEQUENCE # 2:d=1 hl=2 l= 1 prim: INTEGER :00 # 5:d=1 hl=2 l= 5 cons: SEQUENCE # 7:d=2 hl=2 l= 3 prim: OBJECT :1.3.101.110 # 12:d=1 hl=2 l= 34 prim: OCTET STRING (the key) # Of course there's a bit more complexity. In reality OCTET STRING # contains an OCTET STRING of length 32! So the last two bytes here # are \x04\x20, which is an OCTET STRING of length 32. if len(data) != 32: raise ValueError("An X25519 private key is 32 bytes long") pkcs8_prefix = b'0.\x02\x01\x000\x05\x06\x03+en\x04"\x04 ' with self._zeroed_bytearray(48) as ba: ba[0:16] = pkcs8_prefix ba[16:] = data bio = self._bytes_to_bio(ba) evp_pkey = backend._lib.d2i_PrivateKey_bio(bio.bio, self._ffi.NULL) self.openssl_assert(evp_pkey != self._ffi.NULL) evp_pkey = self._ffi.gc(evp_pkey, self._lib.EVP_PKEY_free) self.openssl_assert( self._lib.EVP_PKEY_id(evp_pkey) == self._lib.EVP_PKEY_X25519 ) return _X25519PrivateKey(self, evp_pkey) def _evp_pkey_keygen_gc(self, nid): evp_pkey_ctx = self._lib.EVP_PKEY_CTX_new_id(nid, self._ffi.NULL) self.openssl_assert(evp_pkey_ctx != self._ffi.NULL) evp_pkey_ctx = self._ffi.gc(evp_pkey_ctx, self._lib.EVP_PKEY_CTX_free) res = self._lib.EVP_PKEY_keygen_init(evp_pkey_ctx) self.openssl_assert(res == 1) evp_ppkey = self._ffi.new("EVP_PKEY **") res = self._lib.EVP_PKEY_keygen(evp_pkey_ctx, evp_ppkey) self.openssl_assert(res == 1) self.openssl_assert(evp_ppkey[0] != self._ffi.NULL) evp_pkey = self._ffi.gc(evp_ppkey[0], self._lib.EVP_PKEY_free) return evp_pkey def x25519_generate_key(self): evp_pkey = self._evp_pkey_keygen_gc(self._lib.NID_X25519) return _X25519PrivateKey(self, evp_pkey) def x25519_supported(self): return self._lib.CRYPTOGRAPHY_OPENSSL_110_OR_GREATER def x448_load_public_bytes(self, data): if len(data) != 56: raise ValueError("An X448 public key is 56 bytes long") evp_pkey = self._lib.EVP_PKEY_new_raw_public_key( self._lib.NID_X448, self._ffi.NULL, data, len(data) ) self.openssl_assert(evp_pkey != self._ffi.NULL) evp_pkey = self._ffi.gc(evp_pkey, self._lib.EVP_PKEY_free) return _X448PublicKey(self, evp_pkey) def x448_load_private_bytes(self, data): if len(data) != 56: raise ValueError("An X448 private key is 56 bytes long") data_ptr = self._ffi.from_buffer(data) evp_pkey = self._lib.EVP_PKEY_new_raw_private_key( self._lib.NID_X448, self._ffi.NULL, data_ptr, len(data) ) self.openssl_assert(evp_pkey != self._ffi.NULL) evp_pkey = self._ffi.gc(evp_pkey, self._lib.EVP_PKEY_free) return _X448PrivateKey(self, evp_pkey) def x448_generate_key(self): evp_pkey = self._evp_pkey_keygen_gc(self._lib.NID_X448) return _X448PrivateKey(self, evp_pkey) def x448_supported(self): return not self._lib.CRYPTOGRAPHY_OPENSSL_LESS_THAN_111 def ed25519_supported(self): return not self._lib.CRYPTOGRAPHY_OPENSSL_LESS_THAN_111B def ed25519_load_public_bytes(self, data): utils._check_bytes("data", data) if len(data) != ed25519._ED25519_KEY_SIZE: raise ValueError("An Ed25519 public key is 32 bytes long") evp_pkey = self._lib.EVP_PKEY_new_raw_public_key( self._lib.NID_ED25519, self._ffi.NULL, data, len(data) ) self.openssl_assert(evp_pkey != self._ffi.NULL) evp_pkey = self._ffi.gc(evp_pkey, self._lib.EVP_PKEY_free) return _Ed25519PublicKey(self, evp_pkey) def ed25519_load_private_bytes(self, data): if len(data) != ed25519._ED25519_KEY_SIZE: raise ValueError("An Ed25519 private key is 32 bytes long") utils._check_byteslike("data", data) data_ptr = self._ffi.from_buffer(data) evp_pkey = self._lib.EVP_PKEY_new_raw_private_key( self._lib.NID_ED25519, self._ffi.NULL, data_ptr, len(data) ) self.openssl_assert(evp_pkey != self._ffi.NULL) evp_pkey = self._ffi.gc(evp_pkey, self._lib.EVP_PKEY_free) return _Ed25519PrivateKey(self, evp_pkey) def ed25519_generate_key(self): evp_pkey = self._evp_pkey_keygen_gc(self._lib.NID_ED25519) return _Ed25519PrivateKey(self, evp_pkey) def ed448_supported(self): return not self._lib.CRYPTOGRAPHY_OPENSSL_LESS_THAN_111B def ed448_load_public_bytes(self, data): utils._check_bytes("data", data) if len(data) != _ED448_KEY_SIZE: raise ValueError("An Ed448 public key is 57 bytes long") evp_pkey = self._lib.EVP_PKEY_new_raw_public_key( self._lib.NID_ED448, self._ffi.NULL, data, len(data) ) self.openssl_assert(evp_pkey != self._ffi.NULL) evp_pkey = self._ffi.gc(evp_pkey, self._lib.EVP_PKEY_free) return _Ed448PublicKey(self, evp_pkey) def ed448_load_private_bytes(self, data): utils._check_byteslike("data", data) if len(data) != _ED448_KEY_SIZE: raise ValueError("An Ed448 private key is 57 bytes long") data_ptr = self._ffi.from_buffer(data) evp_pkey = self._lib.EVP_PKEY_new_raw_private_key( self._lib.NID_ED448, self._ffi.NULL, data_ptr, len(data) ) self.openssl_assert(evp_pkey != self._ffi.NULL) evp_pkey = self._ffi.gc(evp_pkey, self._lib.EVP_PKEY_free) return _Ed448PrivateKey(self, evp_pkey) def ed448_generate_key(self): evp_pkey = self._evp_pkey_keygen_gc(self._lib.NID_ED448) return _Ed448PrivateKey(self, evp_pkey) def derive_scrypt(self, key_material, salt, length, n, r, p): buf = self._ffi.new("unsigned char[]", length) key_material_ptr = self._ffi.from_buffer(key_material) res = self._lib.EVP_PBE_scrypt( key_material_ptr, len(key_material), salt, len(salt), n, r, p, scrypt._MEM_LIMIT, buf, length ) if res != 1: errors = self._consume_errors() if not self._lib.CRYPTOGRAPHY_OPENSSL_LESS_THAN_111: # This error is only added to the stack in 1.1.1+ self.openssl_assert( errors[0]._lib_reason_match( self._lib.ERR_LIB_EVP, self._lib.ERR_R_MALLOC_FAILURE ) or errors[0]._lib_reason_match( self._lib.ERR_LIB_EVP, self._lib.EVP_R_MEMORY_LIMIT_EXCEEDED ) ) # memory required formula explained here: # https://blog.filippo.io/the-scrypt-parameters/ min_memory = 128 * n * r // (1024**2) raise MemoryError( "Not enough memory to derive key. These parameters require" " {} MB of memory.".format(min_memory) ) return self._ffi.buffer(buf)[:] def aead_cipher_supported(self, cipher): cipher_name = aead._aead_cipher_name(cipher) return ( self._lib.EVP_get_cipherbyname(cipher_name) != self._ffi.NULL ) @contextlib.contextmanager def _zeroed_bytearray(self, length): """ This method creates a bytearray, which we copy data into (hopefully also from a mutable buffer that can be dynamically erased!), and then zero when we're done. """ ba = bytearray(length) try: yield ba finally: self._zero_data(ba, length) def _zero_data(self, data, length): # We clear things this way because at the moment we're not # sure of a better way that can guarantee it overwrites the # memory of a bytearray and doesn't just replace the underlying char *. for i in range(length): data[i] = 0 @contextlib.contextmanager def _zeroed_null_terminated_buf(self, data): """ This method takes bytes, which can be a bytestring or a mutable buffer like a bytearray, and yields a null-terminated version of that data. This is required because PKCS12_parse doesn't take a length with its password char * and ffi.from_buffer doesn't provide null termination. So, to support zeroing the data via bytearray we need to build this ridiculous construct that copies the memory, but zeroes it after use. """ if data is None: yield self._ffi.NULL else: data_len = len(data) buf = self._ffi.new("char[]", data_len + 1) self._ffi.memmove(buf, data, data_len) try: yield buf finally: # Cast to a uint8_t * so we can assign by integer self._zero_data(self._ffi.cast("uint8_t *", buf), data_len) def load_key_and_certificates_from_pkcs12(self, data, password): if password is not None: utils._check_byteslike("password", password) bio = self._bytes_to_bio(data) p12 = self._lib.d2i_PKCS12_bio(bio.bio, self._ffi.NULL) if p12 == self._ffi.NULL: self._consume_errors() raise ValueError("Could not deserialize PKCS12 data") p12 = self._ffi.gc(p12, self._lib.PKCS12_free) evp_pkey_ptr = self._ffi.new("EVP_PKEY **") x509_ptr = self._ffi.new("X509 **") sk_x509_ptr = self._ffi.new("Cryptography_STACK_OF_X509 **") with self._zeroed_null_terminated_buf(password) as password_buf: res = self._lib.PKCS12_parse( p12, password_buf, evp_pkey_ptr, x509_ptr, sk_x509_ptr ) if res == 0: self._consume_errors() raise ValueError("Invalid password or PKCS12 data") cert = None key = None additional_certificates = [] if evp_pkey_ptr[0] != self._ffi.NULL: evp_pkey = self._ffi.gc(evp_pkey_ptr[0], self._lib.EVP_PKEY_free) key = self._evp_pkey_to_private_key(evp_pkey) if x509_ptr[0] != self._ffi.NULL: x509 = self._ffi.gc(x509_ptr[0], self._lib.X509_free) cert = _Certificate(self, x509) if sk_x509_ptr[0] != self._ffi.NULL: sk_x509 = self._ffi.gc(sk_x509_ptr[0], self._lib.sk_X509_free) num = self._lib.sk_X509_num(sk_x509_ptr[0]) for i in range(num): x509 = self._lib.sk_X509_value(sk_x509, i) x509 = self._ffi.gc(x509, self._lib.X509_free) self.openssl_assert(x509 != self._ffi.NULL) additional_certificates.append(_Certificate(self, x509)) return (key, cert, additional_certificates) def poly1305_supported(self): return self._lib.Cryptography_HAS_POLY1305 == 1 def create_poly1305_ctx(self, key): utils._check_byteslike("key", key) if len(key) != _POLY1305_KEY_SIZE: raise ValueError("A poly1305 key is 32 bytes long") return _Poly1305Context(self, key) class GetCipherByName(object): def __init__(self, fmt): self._fmt = fmt def __call__(self, backend, cipher, mode): cipher_name = self._fmt.format(cipher=cipher, mode=mode).lower() return backend._lib.EVP_get_cipherbyname(cipher_name.encode("ascii")) def _get_xts_cipher(backend, cipher, mode): cipher_name = "aes-{}-xts".format(cipher.key_size // 2) return backend._lib.EVP_get_cipherbyname(cipher_name.encode("ascii")) backend = Backend() ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/cryptography/hazmat/backends/openssl/ciphers.py ================================================ # This file is dual licensed under the terms of the Apache License, Version # 2.0, and the BSD License. See the LICENSE file in the root of this repository # for complete details. from __future__ import absolute_import, division, print_function from cryptography import utils from cryptography.exceptions import InvalidTag, UnsupportedAlgorithm, _Reasons from cryptography.hazmat.primitives import ciphers from cryptography.hazmat.primitives.ciphers import modes @utils.register_interface(ciphers.CipherContext) @utils.register_interface(ciphers.AEADCipherContext) @utils.register_interface(ciphers.AEADEncryptionContext) @utils.register_interface(ciphers.AEADDecryptionContext) class _CipherContext(object): _ENCRYPT = 1 _DECRYPT = 0 def __init__(self, backend, cipher, mode, operation): self._backend = backend self._cipher = cipher self._mode = mode self._operation = operation self._tag = None if isinstance(self._cipher, ciphers.BlockCipherAlgorithm): self._block_size_bytes = self._cipher.block_size // 8 else: self._block_size_bytes = 1 ctx = self._backend._lib.EVP_CIPHER_CTX_new() ctx = self._backend._ffi.gc( ctx, self._backend._lib.EVP_CIPHER_CTX_free ) registry = self._backend._cipher_registry try: adapter = registry[type(cipher), type(mode)] except KeyError: raise UnsupportedAlgorithm( "cipher {} in {} mode is not supported " "by this backend.".format( cipher.name, mode.name if mode else mode), _Reasons.UNSUPPORTED_CIPHER ) evp_cipher = adapter(self._backend, cipher, mode) if evp_cipher == self._backend._ffi.NULL: msg = "cipher {0.name} ".format(cipher) if mode is not None: msg += "in {0.name} mode ".format(mode) msg += ( "is not supported by this backend (Your version of OpenSSL " "may be too old. Current version: {}.)" ).format(self._backend.openssl_version_text()) raise UnsupportedAlgorithm(msg, _Reasons.UNSUPPORTED_CIPHER) if isinstance(mode, modes.ModeWithInitializationVector): iv_nonce = self._backend._ffi.from_buffer( mode.initialization_vector ) elif isinstance(mode, modes.ModeWithTweak): iv_nonce = self._backend._ffi.from_buffer(mode.tweak) elif isinstance(mode, modes.ModeWithNonce): iv_nonce = self._backend._ffi.from_buffer(mode.nonce) elif isinstance(cipher, modes.ModeWithNonce): iv_nonce = self._backend._ffi.from_buffer(cipher.nonce) else: iv_nonce = self._backend._ffi.NULL # begin init with cipher and operation type res = self._backend._lib.EVP_CipherInit_ex(ctx, evp_cipher, self._backend._ffi.NULL, self._backend._ffi.NULL, self._backend._ffi.NULL, operation) self._backend.openssl_assert(res != 0) # set the key length to handle variable key ciphers res = self._backend._lib.EVP_CIPHER_CTX_set_key_length( ctx, len(cipher.key) ) self._backend.openssl_assert(res != 0) if isinstance(mode, modes.GCM): res = self._backend._lib.EVP_CIPHER_CTX_ctrl( ctx, self._backend._lib.EVP_CTRL_AEAD_SET_IVLEN, len(iv_nonce), self._backend._ffi.NULL ) self._backend.openssl_assert(res != 0) if mode.tag is not None: res = self._backend._lib.EVP_CIPHER_CTX_ctrl( ctx, self._backend._lib.EVP_CTRL_AEAD_SET_TAG, len(mode.tag), mode.tag ) self._backend.openssl_assert(res != 0) self._tag = mode.tag elif ( self._operation == self._DECRYPT and self._backend._lib.CRYPTOGRAPHY_OPENSSL_LESS_THAN_102 and not self._backend._lib.CRYPTOGRAPHY_IS_LIBRESSL ): raise NotImplementedError( "delayed passing of GCM tag requires OpenSSL >= 1.0.2." " To use this feature please update OpenSSL" ) # pass key/iv res = self._backend._lib.EVP_CipherInit_ex( ctx, self._backend._ffi.NULL, self._backend._ffi.NULL, self._backend._ffi.from_buffer(cipher.key), iv_nonce, operation ) self._backend.openssl_assert(res != 0) # We purposely disable padding here as it's handled higher up in the # API. self._backend._lib.EVP_CIPHER_CTX_set_padding(ctx, 0) self._ctx = ctx def update(self, data): buf = bytearray(len(data) + self._block_size_bytes - 1) n = self.update_into(data, buf) return bytes(buf[:n]) def update_into(self, data, buf): if len(buf) < (len(data) + self._block_size_bytes - 1): raise ValueError( "buffer must be at least {} bytes for this " "payload".format(len(data) + self._block_size_bytes - 1) ) buf = self._backend._ffi.cast( "unsigned char *", self._backend._ffi.from_buffer(buf) ) outlen = self._backend._ffi.new("int *") res = self._backend._lib.EVP_CipherUpdate( self._ctx, buf, outlen, self._backend._ffi.from_buffer(data), len(data) ) self._backend.openssl_assert(res != 0) return outlen[0] def finalize(self): # OpenSSL 1.0.1 on Ubuntu 12.04 (and possibly other distributions) # appears to have a bug where you must make at least one call to update # even if you are only using authenticate_additional_data or the # GCM tag will be wrong. An (empty) call to update resolves this # and is harmless for all other versions of OpenSSL. if isinstance(self._mode, modes.GCM): self.update(b"") if ( self._operation == self._DECRYPT and isinstance(self._mode, modes.ModeWithAuthenticationTag) and self.tag is None ): raise ValueError( "Authentication tag must be provided when decrypting." ) buf = self._backend._ffi.new("unsigned char[]", self._block_size_bytes) outlen = self._backend._ffi.new("int *") res = self._backend._lib.EVP_CipherFinal_ex(self._ctx, buf, outlen) if res == 0: errors = self._backend._consume_errors() if not errors and isinstance(self._mode, modes.GCM): raise InvalidTag self._backend.openssl_assert( errors[0]._lib_reason_match( self._backend._lib.ERR_LIB_EVP, self._backend._lib.EVP_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH ) ) raise ValueError( "The length of the provided data is not a multiple of " "the block length." ) if (isinstance(self._mode, modes.GCM) and self._operation == self._ENCRYPT): tag_buf = self._backend._ffi.new( "unsigned char[]", self._block_size_bytes ) res = self._backend._lib.EVP_CIPHER_CTX_ctrl( self._ctx, self._backend._lib.EVP_CTRL_AEAD_GET_TAG, self._block_size_bytes, tag_buf ) self._backend.openssl_assert(res != 0) self._tag = self._backend._ffi.buffer(tag_buf)[:] res = self._backend._lib.EVP_CIPHER_CTX_cleanup(self._ctx) self._backend.openssl_assert(res == 1) return self._backend._ffi.buffer(buf)[:outlen[0]] def finalize_with_tag(self, tag): if ( self._backend._lib.CRYPTOGRAPHY_OPENSSL_LESS_THAN_102 and not self._backend._lib.CRYPTOGRAPHY_IS_LIBRESSL ): raise NotImplementedError( "finalize_with_tag requires OpenSSL >= 1.0.2. To use this " "method please update OpenSSL" ) if len(tag) < self._mode._min_tag_length: raise ValueError( "Authentication tag must be {} bytes or longer.".format( self._mode._min_tag_length) ) res = self._backend._lib.EVP_CIPHER_CTX_ctrl( self._ctx, self._backend._lib.EVP_CTRL_AEAD_SET_TAG, len(tag), tag ) self._backend.openssl_assert(res != 0) self._tag = tag return self.finalize() def authenticate_additional_data(self, data): outlen = self._backend._ffi.new("int *") res = self._backend._lib.EVP_CipherUpdate( self._ctx, self._backend._ffi.NULL, outlen, self._backend._ffi.from_buffer(data), len(data) ) self._backend.openssl_assert(res != 0) tag = utils.read_only_property("_tag") ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/cryptography/hazmat/backends/openssl/cmac.py ================================================ # This file is dual licensed under the terms of the Apache License, Version # 2.0, and the BSD License. See the LICENSE file in the root of this repository # for complete details. from __future__ import absolute_import, division, print_function from cryptography import utils from cryptography.exceptions import ( InvalidSignature, UnsupportedAlgorithm, _Reasons ) from cryptography.hazmat.primitives import constant_time from cryptography.hazmat.primitives.ciphers.modes import CBC class _CMACContext(object): def __init__(self, backend, algorithm, ctx=None): if not backend.cmac_algorithm_supported(algorithm): raise UnsupportedAlgorithm("This backend does not support CMAC.", _Reasons.UNSUPPORTED_CIPHER) self._backend = backend self._key = algorithm.key self._algorithm = algorithm self._output_length = algorithm.block_size // 8 if ctx is None: registry = self._backend._cipher_registry adapter = registry[type(algorithm), CBC] evp_cipher = adapter(self._backend, algorithm, CBC) ctx = self._backend._lib.CMAC_CTX_new() self._backend.openssl_assert(ctx != self._backend._ffi.NULL) ctx = self._backend._ffi.gc(ctx, self._backend._lib.CMAC_CTX_free) key_ptr = self._backend._ffi.from_buffer(self._key) res = self._backend._lib.CMAC_Init( ctx, key_ptr, len(self._key), evp_cipher, self._backend._ffi.NULL ) self._backend.openssl_assert(res == 1) self._ctx = ctx algorithm = utils.read_only_property("_algorithm") def update(self, data): res = self._backend._lib.CMAC_Update(self._ctx, data, len(data)) self._backend.openssl_assert(res == 1) def finalize(self): buf = self._backend._ffi.new("unsigned char[]", self._output_length) length = self._backend._ffi.new("size_t *", self._output_length) res = self._backend._lib.CMAC_Final( self._ctx, buf, length ) self._backend.openssl_assert(res == 1) self._ctx = None return self._backend._ffi.buffer(buf)[:] def copy(self): copied_ctx = self._backend._lib.CMAC_CTX_new() copied_ctx = self._backend._ffi.gc( copied_ctx, self._backend._lib.CMAC_CTX_free ) res = self._backend._lib.CMAC_CTX_copy( copied_ctx, self._ctx ) self._backend.openssl_assert(res == 1) return _CMACContext( self._backend, self._algorithm, ctx=copied_ctx ) def verify(self, signature): digest = self.finalize() if not constant_time.bytes_eq(digest, signature): raise InvalidSignature("Signature did not match digest.") ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/cryptography/hazmat/backends/openssl/decode_asn1.py ================================================ # This file is dual licensed under the terms of the Apache License, Version # 2.0, and the BSD License. See the LICENSE file in the root of this repository # for complete details. from __future__ import absolute_import, division, print_function import datetime import ipaddress import six from cryptography import x509 from cryptography.hazmat._der import DERReader, INTEGER, NULL, SEQUENCE from cryptography.x509.extensions import _TLS_FEATURE_TYPE_TO_ENUM from cryptography.x509.name import _ASN1_TYPE_TO_ENUM from cryptography.x509.oid import ( CRLEntryExtensionOID, CertificatePoliciesOID, ExtensionOID, OCSPExtensionOID, ) def _obj2txt(backend, obj): # Set to 80 on the recommendation of # https://www.openssl.org/docs/crypto/OBJ_nid2ln.html#return_values # # But OIDs longer than this occur in real life (e.g. Active # Directory makes some very long OIDs). So we need to detect # and properly handle the case where the default buffer is not # big enough. # buf_len = 80 buf = backend._ffi.new("char[]", buf_len) # 'res' is the number of bytes that *would* be written if the # buffer is large enough. If 'res' > buf_len - 1, we need to # alloc a big-enough buffer and go again. res = backend._lib.OBJ_obj2txt(buf, buf_len, obj, 1) if res > buf_len - 1: # account for terminating null byte buf_len = res + 1 buf = backend._ffi.new("char[]", buf_len) res = backend._lib.OBJ_obj2txt(buf, buf_len, obj, 1) backend.openssl_assert(res > 0) return backend._ffi.buffer(buf, res)[:].decode() def _decode_x509_name_entry(backend, x509_name_entry): obj = backend._lib.X509_NAME_ENTRY_get_object(x509_name_entry) backend.openssl_assert(obj != backend._ffi.NULL) data = backend._lib.X509_NAME_ENTRY_get_data(x509_name_entry) backend.openssl_assert(data != backend._ffi.NULL) value = _asn1_string_to_utf8(backend, data) oid = _obj2txt(backend, obj) type = _ASN1_TYPE_TO_ENUM[data.type] return x509.NameAttribute(x509.ObjectIdentifier(oid), value, type) def _decode_x509_name(backend, x509_name): count = backend._lib.X509_NAME_entry_count(x509_name) attributes = [] prev_set_id = -1 for x in range(count): entry = backend._lib.X509_NAME_get_entry(x509_name, x) attribute = _decode_x509_name_entry(backend, entry) set_id = backend._lib.Cryptography_X509_NAME_ENTRY_set(entry) if set_id != prev_set_id: attributes.append(set([attribute])) else: # is in the same RDN a previous entry attributes[-1].add(attribute) prev_set_id = set_id return x509.Name(x509.RelativeDistinguishedName(rdn) for rdn in attributes) def _decode_general_names(backend, gns): num = backend._lib.sk_GENERAL_NAME_num(gns) names = [] for i in range(num): gn = backend._lib.sk_GENERAL_NAME_value(gns, i) backend.openssl_assert(gn != backend._ffi.NULL) names.append(_decode_general_name(backend, gn)) return names def _decode_general_name(backend, gn): if gn.type == backend._lib.GEN_DNS: # Convert to bytes and then decode to utf8. We don't use # asn1_string_to_utf8 here because it doesn't properly convert # utf8 from ia5strings. data = _asn1_string_to_bytes(backend, gn.d.dNSName).decode("utf8") # We don't use the constructor for DNSName so we can bypass validation # This allows us to create DNSName objects that have unicode chars # when a certificate (against the RFC) contains them. return x509.DNSName._init_without_validation(data) elif gn.type == backend._lib.GEN_URI: # Convert to bytes and then decode to utf8. We don't use # asn1_string_to_utf8 here because it doesn't properly convert # utf8 from ia5strings. data = _asn1_string_to_bytes( backend, gn.d.uniformResourceIdentifier ).decode("utf8") # We don't use the constructor for URI so we can bypass validation # This allows us to create URI objects that have unicode chars # when a certificate (against the RFC) contains them. return x509.UniformResourceIdentifier._init_without_validation(data) elif gn.type == backend._lib.GEN_RID: oid = _obj2txt(backend, gn.d.registeredID) return x509.RegisteredID(x509.ObjectIdentifier(oid)) elif gn.type == backend._lib.GEN_IPADD: data = _asn1_string_to_bytes(backend, gn.d.iPAddress) data_len = len(data) if data_len == 8 or data_len == 32: # This is an IPv4 or IPv6 Network and not a single IP. This # type of data appears in Name Constraints. Unfortunately, # ipaddress doesn't support packed bytes + netmask. Additionally, # IPv6Network can only handle CIDR rather than the full 16 byte # netmask. To handle this we convert the netmask to integer, then # find the first 0 bit, which will be the prefix. If another 1 # bit is present after that the netmask is invalid. base = ipaddress.ip_address(data[:data_len // 2]) netmask = ipaddress.ip_address(data[data_len // 2:]) bits = bin(int(netmask))[2:] prefix = bits.find('0') # If no 0 bits are found it is a /32 or /128 if prefix == -1: prefix = len(bits) if "1" in bits[prefix:]: raise ValueError("Invalid netmask") ip = ipaddress.ip_network(base.exploded + u"/{}".format(prefix)) else: ip = ipaddress.ip_address(data) return x509.IPAddress(ip) elif gn.type == backend._lib.GEN_DIRNAME: return x509.DirectoryName( _decode_x509_name(backend, gn.d.directoryName) ) elif gn.type == backend._lib.GEN_EMAIL: # Convert to bytes and then decode to utf8. We don't use # asn1_string_to_utf8 here because it doesn't properly convert # utf8 from ia5strings. data = _asn1_string_to_bytes(backend, gn.d.rfc822Name).decode("utf8") # We don't use the constructor for RFC822Name so we can bypass # validation. This allows us to create RFC822Name objects that have # unicode chars when a certificate (against the RFC) contains them. return x509.RFC822Name._init_without_validation(data) elif gn.type == backend._lib.GEN_OTHERNAME: type_id = _obj2txt(backend, gn.d.otherName.type_id) value = _asn1_to_der(backend, gn.d.otherName.value) return x509.OtherName(x509.ObjectIdentifier(type_id), value) else: # x400Address or ediPartyName raise x509.UnsupportedGeneralNameType( "{} is not a supported type".format( x509._GENERAL_NAMES.get(gn.type, gn.type) ), gn.type ) def _decode_ocsp_no_check(backend, ext): return x509.OCSPNoCheck() def _decode_crl_number(backend, ext): asn1_int = backend._ffi.cast("ASN1_INTEGER *", ext) asn1_int = backend._ffi.gc(asn1_int, backend._lib.ASN1_INTEGER_free) return x509.CRLNumber(_asn1_integer_to_int(backend, asn1_int)) def _decode_delta_crl_indicator(backend, ext): asn1_int = backend._ffi.cast("ASN1_INTEGER *", ext) asn1_int = backend._ffi.gc(asn1_int, backend._lib.ASN1_INTEGER_free) return x509.DeltaCRLIndicator(_asn1_integer_to_int(backend, asn1_int)) class _X509ExtensionParser(object): def __init__(self, ext_count, get_ext, handlers): self.ext_count = ext_count self.get_ext = get_ext self.handlers = handlers def parse(self, backend, x509_obj): extensions = [] seen_oids = set() for i in range(self.ext_count(backend, x509_obj)): ext = self.get_ext(backend, x509_obj, i) backend.openssl_assert(ext != backend._ffi.NULL) crit = backend._lib.X509_EXTENSION_get_critical(ext) critical = crit == 1 oid = x509.ObjectIdentifier( _obj2txt(backend, backend._lib.X509_EXTENSION_get_object(ext)) ) if oid in seen_oids: raise x509.DuplicateExtension( "Duplicate {} extension found".format(oid), oid ) # These OIDs are only supported in OpenSSL 1.1.0+ but we want # to support them in all versions of OpenSSL so we decode them # ourselves. if oid == ExtensionOID.TLS_FEATURE: # The extension contents are a SEQUENCE OF INTEGERs. data = backend._lib.X509_EXTENSION_get_data(ext) data_bytes = _asn1_string_to_bytes(backend, data) features = DERReader(data_bytes).read_single_element(SEQUENCE) parsed = [] while not features.is_empty(): parsed.append(features.read_element(INTEGER).as_integer()) # Map the features to their enum value. value = x509.TLSFeature( [_TLS_FEATURE_TYPE_TO_ENUM[x] for x in parsed] ) extensions.append(x509.Extension(oid, critical, value)) seen_oids.add(oid) continue elif oid == ExtensionOID.PRECERT_POISON: data = backend._lib.X509_EXTENSION_get_data(ext) # The contents of the extension must be an ASN.1 NULL. reader = DERReader(_asn1_string_to_bytes(backend, data)) reader.read_single_element(NULL).check_empty() extensions.append(x509.Extension( oid, critical, x509.PrecertPoison() )) seen_oids.add(oid) continue try: handler = self.handlers[oid] except KeyError: # Dump the DER payload into an UnrecognizedExtension object data = backend._lib.X509_EXTENSION_get_data(ext) backend.openssl_assert(data != backend._ffi.NULL) der = backend._ffi.buffer(data.data, data.length)[:] unrecognized = x509.UnrecognizedExtension(oid, der) extensions.append( x509.Extension(oid, critical, unrecognized) ) else: ext_data = backend._lib.X509V3_EXT_d2i(ext) if ext_data == backend._ffi.NULL: backend._consume_errors() raise ValueError( "The {} extension is invalid and can't be " "parsed".format(oid) ) value = handler(backend, ext_data) extensions.append(x509.Extension(oid, critical, value)) seen_oids.add(oid) return x509.Extensions(extensions) def _decode_certificate_policies(backend, cp): cp = backend._ffi.cast("Cryptography_STACK_OF_POLICYINFO *", cp) cp = backend._ffi.gc(cp, backend._lib.CERTIFICATEPOLICIES_free) num = backend._lib.sk_POLICYINFO_num(cp) certificate_policies = [] for i in range(num): qualifiers = None pi = backend._lib.sk_POLICYINFO_value(cp, i) oid = x509.ObjectIdentifier(_obj2txt(backend, pi.policyid)) if pi.qualifiers != backend._ffi.NULL: qnum = backend._lib.sk_POLICYQUALINFO_num(pi.qualifiers) qualifiers = [] for j in range(qnum): pqi = backend._lib.sk_POLICYQUALINFO_value( pi.qualifiers, j ) pqualid = x509.ObjectIdentifier( _obj2txt(backend, pqi.pqualid) ) if pqualid == CertificatePoliciesOID.CPS_QUALIFIER: cpsuri = backend._ffi.buffer( pqi.d.cpsuri.data, pqi.d.cpsuri.length )[:].decode('ascii') qualifiers.append(cpsuri) else: assert pqualid == CertificatePoliciesOID.CPS_USER_NOTICE user_notice = _decode_user_notice( backend, pqi.d.usernotice ) qualifiers.append(user_notice) certificate_policies.append( x509.PolicyInformation(oid, qualifiers) ) return x509.CertificatePolicies(certificate_policies) def _decode_user_notice(backend, un): explicit_text = None notice_reference = None if un.exptext != backend._ffi.NULL: explicit_text = _asn1_string_to_utf8(backend, un.exptext) if un.noticeref != backend._ffi.NULL: organization = _asn1_string_to_utf8( backend, un.noticeref.organization ) num = backend._lib.sk_ASN1_INTEGER_num( un.noticeref.noticenos ) notice_numbers = [] for i in range(num): asn1_int = backend._lib.sk_ASN1_INTEGER_value( un.noticeref.noticenos, i ) notice_num = _asn1_integer_to_int(backend, asn1_int) notice_numbers.append(notice_num) notice_reference = x509.NoticeReference( organization, notice_numbers ) return x509.UserNotice(notice_reference, explicit_text) def _decode_basic_constraints(backend, bc_st): basic_constraints = backend._ffi.cast("BASIC_CONSTRAINTS *", bc_st) basic_constraints = backend._ffi.gc( basic_constraints, backend._lib.BASIC_CONSTRAINTS_free ) # The byte representation of an ASN.1 boolean true is \xff. OpenSSL # chooses to just map this to its ordinal value, so true is 255 and # false is 0. ca = basic_constraints.ca == 255 path_length = _asn1_integer_to_int_or_none( backend, basic_constraints.pathlen ) return x509.BasicConstraints(ca, path_length) def _decode_subject_key_identifier(backend, asn1_string): asn1_string = backend._ffi.cast("ASN1_OCTET_STRING *", asn1_string) asn1_string = backend._ffi.gc( asn1_string, backend._lib.ASN1_OCTET_STRING_free ) return x509.SubjectKeyIdentifier( backend._ffi.buffer(asn1_string.data, asn1_string.length)[:] ) def _decode_authority_key_identifier(backend, akid): akid = backend._ffi.cast("AUTHORITY_KEYID *", akid) akid = backend._ffi.gc(akid, backend._lib.AUTHORITY_KEYID_free) key_identifier = None authority_cert_issuer = None if akid.keyid != backend._ffi.NULL: key_identifier = backend._ffi.buffer( akid.keyid.data, akid.keyid.length )[:] if akid.issuer != backend._ffi.NULL: authority_cert_issuer = _decode_general_names( backend, akid.issuer ) authority_cert_serial_number = _asn1_integer_to_int_or_none( backend, akid.serial ) return x509.AuthorityKeyIdentifier( key_identifier, authority_cert_issuer, authority_cert_serial_number ) def _decode_authority_information_access(backend, aia): aia = backend._ffi.cast("Cryptography_STACK_OF_ACCESS_DESCRIPTION *", aia) aia = backend._ffi.gc( aia, lambda x: backend._lib.sk_ACCESS_DESCRIPTION_pop_free( x, backend._ffi.addressof( backend._lib._original_lib, "ACCESS_DESCRIPTION_free" ) ) ) num = backend._lib.sk_ACCESS_DESCRIPTION_num(aia) access_descriptions = [] for i in range(num): ad = backend._lib.sk_ACCESS_DESCRIPTION_value(aia, i) backend.openssl_assert(ad.method != backend._ffi.NULL) oid = x509.ObjectIdentifier(_obj2txt(backend, ad.method)) backend.openssl_assert(ad.location != backend._ffi.NULL) gn = _decode_general_name(backend, ad.location) access_descriptions.append(x509.AccessDescription(oid, gn)) return x509.AuthorityInformationAccess(access_descriptions) def _decode_key_usage(backend, bit_string): bit_string = backend._ffi.cast("ASN1_BIT_STRING *", bit_string) bit_string = backend._ffi.gc(bit_string, backend._lib.ASN1_BIT_STRING_free) get_bit = backend._lib.ASN1_BIT_STRING_get_bit digital_signature = get_bit(bit_string, 0) == 1 content_commitment = get_bit(bit_string, 1) == 1 key_encipherment = get_bit(bit_string, 2) == 1 data_encipherment = get_bit(bit_string, 3) == 1 key_agreement = get_bit(bit_string, 4) == 1 key_cert_sign = get_bit(bit_string, 5) == 1 crl_sign = get_bit(bit_string, 6) == 1 encipher_only = get_bit(bit_string, 7) == 1 decipher_only = get_bit(bit_string, 8) == 1 return x509.KeyUsage( digital_signature, content_commitment, key_encipherment, data_encipherment, key_agreement, key_cert_sign, crl_sign, encipher_only, decipher_only ) def _decode_general_names_extension(backend, gns): gns = backend._ffi.cast("GENERAL_NAMES *", gns) gns = backend._ffi.gc(gns, backend._lib.GENERAL_NAMES_free) general_names = _decode_general_names(backend, gns) return general_names def _decode_subject_alt_name(backend, ext): return x509.SubjectAlternativeName( _decode_general_names_extension(backend, ext) ) def _decode_issuer_alt_name(backend, ext): return x509.IssuerAlternativeName( _decode_general_names_extension(backend, ext) ) def _decode_name_constraints(backend, nc): nc = backend._ffi.cast("NAME_CONSTRAINTS *", nc) nc = backend._ffi.gc(nc, backend._lib.NAME_CONSTRAINTS_free) permitted = _decode_general_subtrees(backend, nc.permittedSubtrees) excluded = _decode_general_subtrees(backend, nc.excludedSubtrees) return x509.NameConstraints( permitted_subtrees=permitted, excluded_subtrees=excluded ) def _decode_general_subtrees(backend, stack_subtrees): if stack_subtrees == backend._ffi.NULL: return None num = backend._lib.sk_GENERAL_SUBTREE_num(stack_subtrees) subtrees = [] for i in range(num): obj = backend._lib.sk_GENERAL_SUBTREE_value(stack_subtrees, i) backend.openssl_assert(obj != backend._ffi.NULL) name = _decode_general_name(backend, obj.base) subtrees.append(name) return subtrees def _decode_issuing_dist_point(backend, idp): idp = backend._ffi.cast("ISSUING_DIST_POINT *", idp) idp = backend._ffi.gc(idp, backend._lib.ISSUING_DIST_POINT_free) if idp.distpoint != backend._ffi.NULL: full_name, relative_name = _decode_distpoint(backend, idp.distpoint) else: full_name = None relative_name = None only_user = idp.onlyuser == 255 only_ca = idp.onlyCA == 255 indirect_crl = idp.indirectCRL == 255 only_attr = idp.onlyattr == 255 if idp.onlysomereasons != backend._ffi.NULL: only_some_reasons = _decode_reasons(backend, idp.onlysomereasons) else: only_some_reasons = None return x509.IssuingDistributionPoint( full_name, relative_name, only_user, only_ca, only_some_reasons, indirect_crl, only_attr ) def _decode_policy_constraints(backend, pc): pc = backend._ffi.cast("POLICY_CONSTRAINTS *", pc) pc = backend._ffi.gc(pc, backend._lib.POLICY_CONSTRAINTS_free) require_explicit_policy = _asn1_integer_to_int_or_none( backend, pc.requireExplicitPolicy ) inhibit_policy_mapping = _asn1_integer_to_int_or_none( backend, pc.inhibitPolicyMapping ) return x509.PolicyConstraints( require_explicit_policy, inhibit_policy_mapping ) def _decode_extended_key_usage(backend, sk): sk = backend._ffi.cast("Cryptography_STACK_OF_ASN1_OBJECT *", sk) sk = backend._ffi.gc(sk, backend._lib.sk_ASN1_OBJECT_free) num = backend._lib.sk_ASN1_OBJECT_num(sk) ekus = [] for i in range(num): obj = backend._lib.sk_ASN1_OBJECT_value(sk, i) backend.openssl_assert(obj != backend._ffi.NULL) oid = x509.ObjectIdentifier(_obj2txt(backend, obj)) ekus.append(oid) return x509.ExtendedKeyUsage(ekus) _DISTPOINT_TYPE_FULLNAME = 0 _DISTPOINT_TYPE_RELATIVENAME = 1 def _decode_dist_points(backend, cdps): cdps = backend._ffi.cast("Cryptography_STACK_OF_DIST_POINT *", cdps) cdps = backend._ffi.gc(cdps, backend._lib.CRL_DIST_POINTS_free) num = backend._lib.sk_DIST_POINT_num(cdps) dist_points = [] for i in range(num): full_name = None relative_name = None crl_issuer = None reasons = None cdp = backend._lib.sk_DIST_POINT_value(cdps, i) if cdp.reasons != backend._ffi.NULL: reasons = _decode_reasons(backend, cdp.reasons) if cdp.CRLissuer != backend._ffi.NULL: crl_issuer = _decode_general_names(backend, cdp.CRLissuer) # Certificates may have a crl_issuer/reasons and no distribution # point so make sure it's not null. if cdp.distpoint != backend._ffi.NULL: full_name, relative_name = _decode_distpoint( backend, cdp.distpoint ) dist_points.append( x509.DistributionPoint( full_name, relative_name, reasons, crl_issuer ) ) return dist_points # ReasonFlags ::= BIT STRING { # unused (0), # keyCompromise (1), # cACompromise (2), # affiliationChanged (3), # superseded (4), # cessationOfOperation (5), # certificateHold (6), # privilegeWithdrawn (7), # aACompromise (8) } _REASON_BIT_MAPPING = { 1: x509.ReasonFlags.key_compromise, 2: x509.ReasonFlags.ca_compromise, 3: x509.ReasonFlags.affiliation_changed, 4: x509.ReasonFlags.superseded, 5: x509.ReasonFlags.cessation_of_operation, 6: x509.ReasonFlags.certificate_hold, 7: x509.ReasonFlags.privilege_withdrawn, 8: x509.ReasonFlags.aa_compromise, } def _decode_reasons(backend, reasons): # We will check each bit from RFC 5280 enum_reasons = [] for bit_position, reason in six.iteritems(_REASON_BIT_MAPPING): if backend._lib.ASN1_BIT_STRING_get_bit(reasons, bit_position): enum_reasons.append(reason) return frozenset(enum_reasons) def _decode_distpoint(backend, distpoint): if distpoint.type == _DISTPOINT_TYPE_FULLNAME: full_name = _decode_general_names(backend, distpoint.name.fullname) return full_name, None # OpenSSL code doesn't test for a specific type for # relativename, everything that isn't fullname is considered # relativename. Per RFC 5280: # # DistributionPointName ::= CHOICE { # fullName [0] GeneralNames, # nameRelativeToCRLIssuer [1] RelativeDistinguishedName } rns = distpoint.name.relativename rnum = backend._lib.sk_X509_NAME_ENTRY_num(rns) attributes = set() for i in range(rnum): rn = backend._lib.sk_X509_NAME_ENTRY_value( rns, i ) backend.openssl_assert(rn != backend._ffi.NULL) attributes.add( _decode_x509_name_entry(backend, rn) ) relative_name = x509.RelativeDistinguishedName(attributes) return None, relative_name def _decode_crl_distribution_points(backend, cdps): dist_points = _decode_dist_points(backend, cdps) return x509.CRLDistributionPoints(dist_points) def _decode_freshest_crl(backend, cdps): dist_points = _decode_dist_points(backend, cdps) return x509.FreshestCRL(dist_points) def _decode_inhibit_any_policy(backend, asn1_int): asn1_int = backend._ffi.cast("ASN1_INTEGER *", asn1_int) asn1_int = backend._ffi.gc(asn1_int, backend._lib.ASN1_INTEGER_free) skip_certs = _asn1_integer_to_int(backend, asn1_int) return x509.InhibitAnyPolicy(skip_certs) def _decode_precert_signed_certificate_timestamps(backend, asn1_scts): from cryptography.hazmat.backends.openssl.x509 import ( _SignedCertificateTimestamp ) asn1_scts = backend._ffi.cast("Cryptography_STACK_OF_SCT *", asn1_scts) asn1_scts = backend._ffi.gc(asn1_scts, backend._lib.SCT_LIST_free) scts = [] for i in range(backend._lib.sk_SCT_num(asn1_scts)): sct = backend._lib.sk_SCT_value(asn1_scts, i) scts.append(_SignedCertificateTimestamp(backend, asn1_scts, sct)) return x509.PrecertificateSignedCertificateTimestamps(scts) # CRLReason ::= ENUMERATED { # unspecified (0), # keyCompromise (1), # cACompromise (2), # affiliationChanged (3), # superseded (4), # cessationOfOperation (5), # certificateHold (6), # -- value 7 is not used # removeFromCRL (8), # privilegeWithdrawn (9), # aACompromise (10) } _CRL_ENTRY_REASON_CODE_TO_ENUM = { 0: x509.ReasonFlags.unspecified, 1: x509.ReasonFlags.key_compromise, 2: x509.ReasonFlags.ca_compromise, 3: x509.ReasonFlags.affiliation_changed, 4: x509.ReasonFlags.superseded, 5: x509.ReasonFlags.cessation_of_operation, 6: x509.ReasonFlags.certificate_hold, 8: x509.ReasonFlags.remove_from_crl, 9: x509.ReasonFlags.privilege_withdrawn, 10: x509.ReasonFlags.aa_compromise, } _CRL_ENTRY_REASON_ENUM_TO_CODE = { x509.ReasonFlags.unspecified: 0, x509.ReasonFlags.key_compromise: 1, x509.ReasonFlags.ca_compromise: 2, x509.ReasonFlags.affiliation_changed: 3, x509.ReasonFlags.superseded: 4, x509.ReasonFlags.cessation_of_operation: 5, x509.ReasonFlags.certificate_hold: 6, x509.ReasonFlags.remove_from_crl: 8, x509.ReasonFlags.privilege_withdrawn: 9, x509.ReasonFlags.aa_compromise: 10 } def _decode_crl_reason(backend, enum): enum = backend._ffi.cast("ASN1_ENUMERATED *", enum) enum = backend._ffi.gc(enum, backend._lib.ASN1_ENUMERATED_free) code = backend._lib.ASN1_ENUMERATED_get(enum) try: return x509.CRLReason(_CRL_ENTRY_REASON_CODE_TO_ENUM[code]) except KeyError: raise ValueError("Unsupported reason code: {}".format(code)) def _decode_invalidity_date(backend, inv_date): generalized_time = backend._ffi.cast( "ASN1_GENERALIZEDTIME *", inv_date ) generalized_time = backend._ffi.gc( generalized_time, backend._lib.ASN1_GENERALIZEDTIME_free ) return x509.InvalidityDate( _parse_asn1_generalized_time(backend, generalized_time) ) def _decode_cert_issuer(backend, gns): gns = backend._ffi.cast("GENERAL_NAMES *", gns) gns = backend._ffi.gc(gns, backend._lib.GENERAL_NAMES_free) general_names = _decode_general_names(backend, gns) return x509.CertificateIssuer(general_names) def _asn1_to_der(backend, asn1_type): buf = backend._ffi.new("unsigned char **") res = backend._lib.i2d_ASN1_TYPE(asn1_type, buf) backend.openssl_assert(res >= 0) backend.openssl_assert(buf[0] != backend._ffi.NULL) buf = backend._ffi.gc( buf, lambda buffer: backend._lib.OPENSSL_free(buffer[0]) ) return backend._ffi.buffer(buf[0], res)[:] def _asn1_integer_to_int(backend, asn1_int): bn = backend._lib.ASN1_INTEGER_to_BN(asn1_int, backend._ffi.NULL) backend.openssl_assert(bn != backend._ffi.NULL) bn = backend._ffi.gc(bn, backend._lib.BN_free) return backend._bn_to_int(bn) def _asn1_integer_to_int_or_none(backend, asn1_int): if asn1_int == backend._ffi.NULL: return None else: return _asn1_integer_to_int(backend, asn1_int) def _asn1_string_to_bytes(backend, asn1_string): return backend._ffi.buffer(asn1_string.data, asn1_string.length)[:] def _asn1_string_to_ascii(backend, asn1_string): return _asn1_string_to_bytes(backend, asn1_string).decode("ascii") def _asn1_string_to_utf8(backend, asn1_string): buf = backend._ffi.new("unsigned char **") res = backend._lib.ASN1_STRING_to_UTF8(buf, asn1_string) if res == -1: raise ValueError( "Unsupported ASN1 string type. Type: {}".format(asn1_string.type) ) backend.openssl_assert(buf[0] != backend._ffi.NULL) buf = backend._ffi.gc( buf, lambda buffer: backend._lib.OPENSSL_free(buffer[0]) ) return backend._ffi.buffer(buf[0], res)[:].decode('utf8') def _parse_asn1_time(backend, asn1_time): backend.openssl_assert(asn1_time != backend._ffi.NULL) generalized_time = backend._lib.ASN1_TIME_to_generalizedtime( asn1_time, backend._ffi.NULL ) if generalized_time == backend._ffi.NULL: raise ValueError( "Couldn't parse ASN.1 time as generalizedtime {!r}".format( _asn1_string_to_bytes(backend, asn1_time) ) ) generalized_time = backend._ffi.gc( generalized_time, backend._lib.ASN1_GENERALIZEDTIME_free ) return _parse_asn1_generalized_time(backend, generalized_time) def _parse_asn1_generalized_time(backend, generalized_time): time = _asn1_string_to_ascii( backend, backend._ffi.cast("ASN1_STRING *", generalized_time) ) return datetime.datetime.strptime(time, "%Y%m%d%H%M%SZ") def _decode_nonce(backend, nonce): nonce = backend._ffi.cast("ASN1_OCTET_STRING *", nonce) nonce = backend._ffi.gc(nonce, backend._lib.ASN1_OCTET_STRING_free) return x509.OCSPNonce(_asn1_string_to_bytes(backend, nonce)) _EXTENSION_HANDLERS_NO_SCT = { ExtensionOID.BASIC_CONSTRAINTS: _decode_basic_constraints, ExtensionOID.SUBJECT_KEY_IDENTIFIER: _decode_subject_key_identifier, ExtensionOID.KEY_USAGE: _decode_key_usage, ExtensionOID.SUBJECT_ALTERNATIVE_NAME: _decode_subject_alt_name, ExtensionOID.EXTENDED_KEY_USAGE: _decode_extended_key_usage, ExtensionOID.AUTHORITY_KEY_IDENTIFIER: _decode_authority_key_identifier, ExtensionOID.AUTHORITY_INFORMATION_ACCESS: ( _decode_authority_information_access ), ExtensionOID.CERTIFICATE_POLICIES: _decode_certificate_policies, ExtensionOID.CRL_DISTRIBUTION_POINTS: _decode_crl_distribution_points, ExtensionOID.FRESHEST_CRL: _decode_freshest_crl, ExtensionOID.OCSP_NO_CHECK: _decode_ocsp_no_check, ExtensionOID.INHIBIT_ANY_POLICY: _decode_inhibit_any_policy, ExtensionOID.ISSUER_ALTERNATIVE_NAME: _decode_issuer_alt_name, ExtensionOID.NAME_CONSTRAINTS: _decode_name_constraints, ExtensionOID.POLICY_CONSTRAINTS: _decode_policy_constraints, } _EXTENSION_HANDLERS = _EXTENSION_HANDLERS_NO_SCT.copy() _EXTENSION_HANDLERS[ ExtensionOID.PRECERT_SIGNED_CERTIFICATE_TIMESTAMPS ] = _decode_precert_signed_certificate_timestamps _REVOKED_EXTENSION_HANDLERS = { CRLEntryExtensionOID.CRL_REASON: _decode_crl_reason, CRLEntryExtensionOID.INVALIDITY_DATE: _decode_invalidity_date, CRLEntryExtensionOID.CERTIFICATE_ISSUER: _decode_cert_issuer, } _CRL_EXTENSION_HANDLERS = { ExtensionOID.CRL_NUMBER: _decode_crl_number, ExtensionOID.DELTA_CRL_INDICATOR: _decode_delta_crl_indicator, ExtensionOID.AUTHORITY_KEY_IDENTIFIER: _decode_authority_key_identifier, ExtensionOID.ISSUER_ALTERNATIVE_NAME: _decode_issuer_alt_name, ExtensionOID.AUTHORITY_INFORMATION_ACCESS: ( _decode_authority_information_access ), ExtensionOID.ISSUING_DISTRIBUTION_POINT: _decode_issuing_dist_point, ExtensionOID.FRESHEST_CRL: _decode_freshest_crl, } _OCSP_REQ_EXTENSION_HANDLERS = { OCSPExtensionOID.NONCE: _decode_nonce, } _OCSP_BASICRESP_EXTENSION_HANDLERS = { OCSPExtensionOID.NONCE: _decode_nonce, } _CERTIFICATE_EXTENSION_PARSER_NO_SCT = _X509ExtensionParser( ext_count=lambda backend, x: backend._lib.X509_get_ext_count(x), get_ext=lambda backend, x, i: backend._lib.X509_get_ext(x, i), handlers=_EXTENSION_HANDLERS_NO_SCT ) _CERTIFICATE_EXTENSION_PARSER = _X509ExtensionParser( ext_count=lambda backend, x: backend._lib.X509_get_ext_count(x), get_ext=lambda backend, x, i: backend._lib.X509_get_ext(x, i), handlers=_EXTENSION_HANDLERS ) _CSR_EXTENSION_PARSER = _X509ExtensionParser( ext_count=lambda backend, x: backend._lib.sk_X509_EXTENSION_num(x), get_ext=lambda backend, x, i: backend._lib.sk_X509_EXTENSION_value(x, i), handlers=_EXTENSION_HANDLERS ) _REVOKED_CERTIFICATE_EXTENSION_PARSER = _X509ExtensionParser( ext_count=lambda backend, x: backend._lib.X509_REVOKED_get_ext_count(x), get_ext=lambda backend, x, i: backend._lib.X509_REVOKED_get_ext(x, i), handlers=_REVOKED_EXTENSION_HANDLERS, ) _CRL_EXTENSION_PARSER = _X509ExtensionParser( ext_count=lambda backend, x: backend._lib.X509_CRL_get_ext_count(x), get_ext=lambda backend, x, i: backend._lib.X509_CRL_get_ext(x, i), handlers=_CRL_EXTENSION_HANDLERS, ) _OCSP_REQ_EXT_PARSER = _X509ExtensionParser( ext_count=lambda backend, x: backend._lib.OCSP_REQUEST_get_ext_count(x), get_ext=lambda backend, x, i: backend._lib.OCSP_REQUEST_get_ext(x, i), handlers=_OCSP_REQ_EXTENSION_HANDLERS, ) _OCSP_BASICRESP_EXT_PARSER = _X509ExtensionParser( ext_count=lambda backend, x: backend._lib.OCSP_BASICRESP_get_ext_count(x), get_ext=lambda backend, x, i: backend._lib.OCSP_BASICRESP_get_ext(x, i), handlers=_OCSP_BASICRESP_EXTENSION_HANDLERS, ) ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/cryptography/hazmat/backends/openssl/dh.py ================================================ # This file is dual licensed under the terms of the Apache License, Version # 2.0, and the BSD License. See the LICENSE file in the root of this repository # for complete details. from __future__ import absolute_import, division, print_function from cryptography import utils from cryptography.exceptions import UnsupportedAlgorithm, _Reasons from cryptography.hazmat.primitives import serialization from cryptography.hazmat.primitives.asymmetric import dh def _dh_params_dup(dh_cdata, backend): lib = backend._lib ffi = backend._ffi param_cdata = lib.DHparams_dup(dh_cdata) backend.openssl_assert(param_cdata != ffi.NULL) param_cdata = ffi.gc(param_cdata, lib.DH_free) if lib.CRYPTOGRAPHY_OPENSSL_LESS_THAN_102: # In OpenSSL versions < 1.0.2 or libressl DHparams_dup don't copy q q = ffi.new("BIGNUM **") lib.DH_get0_pqg(dh_cdata, ffi.NULL, q, ffi.NULL) q_dup = lib.BN_dup(q[0]) res = lib.DH_set0_pqg(param_cdata, ffi.NULL, q_dup, ffi.NULL) backend.openssl_assert(res == 1) return param_cdata def _dh_cdata_to_parameters(dh_cdata, backend): param_cdata = _dh_params_dup(dh_cdata, backend) return _DHParameters(backend, param_cdata) @utils.register_interface(dh.DHParametersWithSerialization) class _DHParameters(object): def __init__(self, backend, dh_cdata): self._backend = backend self._dh_cdata = dh_cdata def parameter_numbers(self): p = self._backend._ffi.new("BIGNUM **") g = self._backend._ffi.new("BIGNUM **") q = self._backend._ffi.new("BIGNUM **") self._backend._lib.DH_get0_pqg(self._dh_cdata, p, q, g) self._backend.openssl_assert(p[0] != self._backend._ffi.NULL) self._backend.openssl_assert(g[0] != self._backend._ffi.NULL) if q[0] == self._backend._ffi.NULL: q_val = None else: q_val = self._backend._bn_to_int(q[0]) return dh.DHParameterNumbers( p=self._backend._bn_to_int(p[0]), g=self._backend._bn_to_int(g[0]), q=q_val ) def generate_private_key(self): return self._backend.generate_dh_private_key(self) def parameter_bytes(self, encoding, format): if format is not serialization.ParameterFormat.PKCS3: raise ValueError( "Only PKCS3 serialization is supported" ) if not self._backend._lib.Cryptography_HAS_EVP_PKEY_DHX: q = self._backend._ffi.new("BIGNUM **") self._backend._lib.DH_get0_pqg(self._dh_cdata, self._backend._ffi.NULL, q, self._backend._ffi.NULL) if q[0] != self._backend._ffi.NULL: raise UnsupportedAlgorithm( "DH X9.42 serialization is not supported", _Reasons.UNSUPPORTED_SERIALIZATION) return self._backend._parameter_bytes( encoding, format, self._dh_cdata ) def _handle_dh_compute_key_error(errors, backend): lib = backend._lib backend.openssl_assert( errors[0]._lib_reason_match( lib.ERR_LIB_DH, lib.DH_R_INVALID_PUBKEY ) ) raise ValueError("Public key value is invalid for this exchange.") def _get_dh_num_bits(backend, dh_cdata): p = backend._ffi.new("BIGNUM **") backend._lib.DH_get0_pqg(dh_cdata, p, backend._ffi.NULL, backend._ffi.NULL) backend.openssl_assert(p[0] != backend._ffi.NULL) return backend._lib.BN_num_bits(p[0]) @utils.register_interface(dh.DHPrivateKeyWithSerialization) class _DHPrivateKey(object): def __init__(self, backend, dh_cdata, evp_pkey): self._backend = backend self._dh_cdata = dh_cdata self._evp_pkey = evp_pkey self._key_size_bytes = self._backend._lib.DH_size(dh_cdata) @property def key_size(self): return _get_dh_num_bits(self._backend, self._dh_cdata) def private_numbers(self): p = self._backend._ffi.new("BIGNUM **") g = self._backend._ffi.new("BIGNUM **") q = self._backend._ffi.new("BIGNUM **") self._backend._lib.DH_get0_pqg(self._dh_cdata, p, q, g) self._backend.openssl_assert(p[0] != self._backend._ffi.NULL) self._backend.openssl_assert(g[0] != self._backend._ffi.NULL) if q[0] == self._backend._ffi.NULL: q_val = None else: q_val = self._backend._bn_to_int(q[0]) pub_key = self._backend._ffi.new("BIGNUM **") priv_key = self._backend._ffi.new("BIGNUM **") self._backend._lib.DH_get0_key(self._dh_cdata, pub_key, priv_key) self._backend.openssl_assert(pub_key[0] != self._backend._ffi.NULL) self._backend.openssl_assert(priv_key[0] != self._backend._ffi.NULL) return dh.DHPrivateNumbers( public_numbers=dh.DHPublicNumbers( parameter_numbers=dh.DHParameterNumbers( p=self._backend._bn_to_int(p[0]), g=self._backend._bn_to_int(g[0]), q=q_val ), y=self._backend._bn_to_int(pub_key[0]) ), x=self._backend._bn_to_int(priv_key[0]) ) def exchange(self, peer_public_key): buf = self._backend._ffi.new("unsigned char[]", self._key_size_bytes) pub_key = self._backend._ffi.new("BIGNUM **") self._backend._lib.DH_get0_key(peer_public_key._dh_cdata, pub_key, self._backend._ffi.NULL) self._backend.openssl_assert(pub_key[0] != self._backend._ffi.NULL) res = self._backend._lib.DH_compute_key( buf, pub_key[0], self._dh_cdata ) if res == -1: errors = self._backend._consume_errors() return _handle_dh_compute_key_error(errors, self._backend) else: self._backend.openssl_assert(res >= 1) key = self._backend._ffi.buffer(buf)[:res] pad = self._key_size_bytes - len(key) if pad > 0: key = (b"\x00" * pad) + key return key def public_key(self): dh_cdata = _dh_params_dup(self._dh_cdata, self._backend) pub_key = self._backend._ffi.new("BIGNUM **") self._backend._lib.DH_get0_key(self._dh_cdata, pub_key, self._backend._ffi.NULL) self._backend.openssl_assert(pub_key[0] != self._backend._ffi.NULL) pub_key_dup = self._backend._lib.BN_dup(pub_key[0]) self._backend.openssl_assert(pub_key_dup != self._backend._ffi.NULL) res = self._backend._lib.DH_set0_key(dh_cdata, pub_key_dup, self._backend._ffi.NULL) self._backend.openssl_assert(res == 1) evp_pkey = self._backend._dh_cdata_to_evp_pkey(dh_cdata) return _DHPublicKey(self._backend, dh_cdata, evp_pkey) def parameters(self): return _dh_cdata_to_parameters(self._dh_cdata, self._backend) def private_bytes(self, encoding, format, encryption_algorithm): if format is not serialization.PrivateFormat.PKCS8: raise ValueError( "DH private keys support only PKCS8 serialization" ) if not self._backend._lib.Cryptography_HAS_EVP_PKEY_DHX: q = self._backend._ffi.new("BIGNUM **") self._backend._lib.DH_get0_pqg(self._dh_cdata, self._backend._ffi.NULL, q, self._backend._ffi.NULL) if q[0] != self._backend._ffi.NULL: raise UnsupportedAlgorithm( "DH X9.42 serialization is not supported", _Reasons.UNSUPPORTED_SERIALIZATION) return self._backend._private_key_bytes( encoding, format, encryption_algorithm, self._evp_pkey, self._dh_cdata ) @utils.register_interface(dh.DHPublicKeyWithSerialization) class _DHPublicKey(object): def __init__(self, backend, dh_cdata, evp_pkey): self._backend = backend self._dh_cdata = dh_cdata self._evp_pkey = evp_pkey self._key_size_bits = _get_dh_num_bits(self._backend, self._dh_cdata) @property def key_size(self): return self._key_size_bits def public_numbers(self): p = self._backend._ffi.new("BIGNUM **") g = self._backend._ffi.new("BIGNUM **") q = self._backend._ffi.new("BIGNUM **") self._backend._lib.DH_get0_pqg(self._dh_cdata, p, q, g) self._backend.openssl_assert(p[0] != self._backend._ffi.NULL) self._backend.openssl_assert(g[0] != self._backend._ffi.NULL) if q[0] == self._backend._ffi.NULL: q_val = None else: q_val = self._backend._bn_to_int(q[0]) pub_key = self._backend._ffi.new("BIGNUM **") self._backend._lib.DH_get0_key(self._dh_cdata, pub_key, self._backend._ffi.NULL) self._backend.openssl_assert(pub_key[0] != self._backend._ffi.NULL) return dh.DHPublicNumbers( parameter_numbers=dh.DHParameterNumbers( p=self._backend._bn_to_int(p[0]), g=self._backend._bn_to_int(g[0]), q=q_val ), y=self._backend._bn_to_int(pub_key[0]) ) def parameters(self): return _dh_cdata_to_parameters(self._dh_cdata, self._backend) def public_bytes(self, encoding, format): if format is not serialization.PublicFormat.SubjectPublicKeyInfo: raise ValueError( "DH public keys support only " "SubjectPublicKeyInfo serialization" ) if not self._backend._lib.Cryptography_HAS_EVP_PKEY_DHX: q = self._backend._ffi.new("BIGNUM **") self._backend._lib.DH_get0_pqg(self._dh_cdata, self._backend._ffi.NULL, q, self._backend._ffi.NULL) if q[0] != self._backend._ffi.NULL: raise UnsupportedAlgorithm( "DH X9.42 serialization is not supported", _Reasons.UNSUPPORTED_SERIALIZATION) return self._backend._public_key_bytes( encoding, format, self, self._evp_pkey, None ) ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/cryptography/hazmat/backends/openssl/dsa.py ================================================ # This file is dual licensed under the terms of the Apache License, Version # 2.0, and the BSD License. See the LICENSE file in the root of this repository # for complete details. from __future__ import absolute_import, division, print_function from cryptography import utils from cryptography.exceptions import InvalidSignature from cryptography.hazmat.backends.openssl.utils import ( _calculate_digest_and_algorithm, _check_not_prehashed, _warn_sign_verify_deprecated ) from cryptography.hazmat.primitives import hashes, serialization from cryptography.hazmat.primitives.asymmetric import ( AsymmetricSignatureContext, AsymmetricVerificationContext, dsa ) def _dsa_sig_sign(backend, private_key, data): sig_buf_len = backend._lib.DSA_size(private_key._dsa_cdata) sig_buf = backend._ffi.new("unsigned char[]", sig_buf_len) buflen = backend._ffi.new("unsigned int *") # The first parameter passed to DSA_sign is unused by OpenSSL but # must be an integer. res = backend._lib.DSA_sign( 0, data, len(data), sig_buf, buflen, private_key._dsa_cdata ) backend.openssl_assert(res == 1) backend.openssl_assert(buflen[0]) return backend._ffi.buffer(sig_buf)[:buflen[0]] def _dsa_sig_verify(backend, public_key, signature, data): # The first parameter passed to DSA_verify is unused by OpenSSL but # must be an integer. res = backend._lib.DSA_verify( 0, data, len(data), signature, len(signature), public_key._dsa_cdata ) if res != 1: backend._consume_errors() raise InvalidSignature @utils.register_interface(AsymmetricVerificationContext) class _DSAVerificationContext(object): def __init__(self, backend, public_key, signature, algorithm): self._backend = backend self._public_key = public_key self._signature = signature self._algorithm = algorithm self._hash_ctx = hashes.Hash(self._algorithm, self._backend) def update(self, data): self._hash_ctx.update(data) def verify(self): data_to_verify = self._hash_ctx.finalize() _dsa_sig_verify( self._backend, self._public_key, self._signature, data_to_verify ) @utils.register_interface(AsymmetricSignatureContext) class _DSASignatureContext(object): def __init__(self, backend, private_key, algorithm): self._backend = backend self._private_key = private_key self._algorithm = algorithm self._hash_ctx = hashes.Hash(self._algorithm, self._backend) def update(self, data): self._hash_ctx.update(data) def finalize(self): data_to_sign = self._hash_ctx.finalize() return _dsa_sig_sign(self._backend, self._private_key, data_to_sign) @utils.register_interface(dsa.DSAParametersWithNumbers) class _DSAParameters(object): def __init__(self, backend, dsa_cdata): self._backend = backend self._dsa_cdata = dsa_cdata def parameter_numbers(self): p = self._backend._ffi.new("BIGNUM **") q = self._backend._ffi.new("BIGNUM **") g = self._backend._ffi.new("BIGNUM **") self._backend._lib.DSA_get0_pqg(self._dsa_cdata, p, q, g) self._backend.openssl_assert(p[0] != self._backend._ffi.NULL) self._backend.openssl_assert(q[0] != self._backend._ffi.NULL) self._backend.openssl_assert(g[0] != self._backend._ffi.NULL) return dsa.DSAParameterNumbers( p=self._backend._bn_to_int(p[0]), q=self._backend._bn_to_int(q[0]), g=self._backend._bn_to_int(g[0]) ) def generate_private_key(self): return self._backend.generate_dsa_private_key(self) @utils.register_interface(dsa.DSAPrivateKeyWithSerialization) class _DSAPrivateKey(object): def __init__(self, backend, dsa_cdata, evp_pkey): self._backend = backend self._dsa_cdata = dsa_cdata self._evp_pkey = evp_pkey p = self._backend._ffi.new("BIGNUM **") self._backend._lib.DSA_get0_pqg( dsa_cdata, p, self._backend._ffi.NULL, self._backend._ffi.NULL ) self._backend.openssl_assert(p[0] != backend._ffi.NULL) self._key_size = self._backend._lib.BN_num_bits(p[0]) key_size = utils.read_only_property("_key_size") def signer(self, signature_algorithm): _warn_sign_verify_deprecated() _check_not_prehashed(signature_algorithm) return _DSASignatureContext(self._backend, self, signature_algorithm) def private_numbers(self): p = self._backend._ffi.new("BIGNUM **") q = self._backend._ffi.new("BIGNUM **") g = self._backend._ffi.new("BIGNUM **") pub_key = self._backend._ffi.new("BIGNUM **") priv_key = self._backend._ffi.new("BIGNUM **") self._backend._lib.DSA_get0_pqg(self._dsa_cdata, p, q, g) self._backend.openssl_assert(p[0] != self._backend._ffi.NULL) self._backend.openssl_assert(q[0] != self._backend._ffi.NULL) self._backend.openssl_assert(g[0] != self._backend._ffi.NULL) self._backend._lib.DSA_get0_key(self._dsa_cdata, pub_key, priv_key) self._backend.openssl_assert(pub_key[0] != self._backend._ffi.NULL) self._backend.openssl_assert(priv_key[0] != self._backend._ffi.NULL) return dsa.DSAPrivateNumbers( public_numbers=dsa.DSAPublicNumbers( parameter_numbers=dsa.DSAParameterNumbers( p=self._backend._bn_to_int(p[0]), q=self._backend._bn_to_int(q[0]), g=self._backend._bn_to_int(g[0]) ), y=self._backend._bn_to_int(pub_key[0]) ), x=self._backend._bn_to_int(priv_key[0]) ) def public_key(self): dsa_cdata = self._backend._lib.DSAparams_dup(self._dsa_cdata) self._backend.openssl_assert(dsa_cdata != self._backend._ffi.NULL) dsa_cdata = self._backend._ffi.gc( dsa_cdata, self._backend._lib.DSA_free ) pub_key = self._backend._ffi.new("BIGNUM **") self._backend._lib.DSA_get0_key( self._dsa_cdata, pub_key, self._backend._ffi.NULL ) self._backend.openssl_assert(pub_key[0] != self._backend._ffi.NULL) pub_key_dup = self._backend._lib.BN_dup(pub_key[0]) res = self._backend._lib.DSA_set0_key( dsa_cdata, pub_key_dup, self._backend._ffi.NULL ) self._backend.openssl_assert(res == 1) evp_pkey = self._backend._dsa_cdata_to_evp_pkey(dsa_cdata) return _DSAPublicKey(self._backend, dsa_cdata, evp_pkey) def parameters(self): dsa_cdata = self._backend._lib.DSAparams_dup(self._dsa_cdata) self._backend.openssl_assert(dsa_cdata != self._backend._ffi.NULL) dsa_cdata = self._backend._ffi.gc( dsa_cdata, self._backend._lib.DSA_free ) return _DSAParameters(self._backend, dsa_cdata) def private_bytes(self, encoding, format, encryption_algorithm): return self._backend._private_key_bytes( encoding, format, encryption_algorithm, self._evp_pkey, self._dsa_cdata ) def sign(self, data, algorithm): data, algorithm = _calculate_digest_and_algorithm( self._backend, data, algorithm ) return _dsa_sig_sign(self._backend, self, data) @utils.register_interface(dsa.DSAPublicKeyWithSerialization) class _DSAPublicKey(object): def __init__(self, backend, dsa_cdata, evp_pkey): self._backend = backend self._dsa_cdata = dsa_cdata self._evp_pkey = evp_pkey p = self._backend._ffi.new("BIGNUM **") self._backend._lib.DSA_get0_pqg( dsa_cdata, p, self._backend._ffi.NULL, self._backend._ffi.NULL ) self._backend.openssl_assert(p[0] != backend._ffi.NULL) self._key_size = self._backend._lib.BN_num_bits(p[0]) key_size = utils.read_only_property("_key_size") def verifier(self, signature, signature_algorithm): _warn_sign_verify_deprecated() utils._check_bytes("signature", signature) _check_not_prehashed(signature_algorithm) return _DSAVerificationContext( self._backend, self, signature, signature_algorithm ) def public_numbers(self): p = self._backend._ffi.new("BIGNUM **") q = self._backend._ffi.new("BIGNUM **") g = self._backend._ffi.new("BIGNUM **") pub_key = self._backend._ffi.new("BIGNUM **") self._backend._lib.DSA_get0_pqg(self._dsa_cdata, p, q, g) self._backend.openssl_assert(p[0] != self._backend._ffi.NULL) self._backend.openssl_assert(q[0] != self._backend._ffi.NULL) self._backend.openssl_assert(g[0] != self._backend._ffi.NULL) self._backend._lib.DSA_get0_key( self._dsa_cdata, pub_key, self._backend._ffi.NULL ) self._backend.openssl_assert(pub_key[0] != self._backend._ffi.NULL) return dsa.DSAPublicNumbers( parameter_numbers=dsa.DSAParameterNumbers( p=self._backend._bn_to_int(p[0]), q=self._backend._bn_to_int(q[0]), g=self._backend._bn_to_int(g[0]) ), y=self._backend._bn_to_int(pub_key[0]) ) def parameters(self): dsa_cdata = self._backend._lib.DSAparams_dup(self._dsa_cdata) dsa_cdata = self._backend._ffi.gc( dsa_cdata, self._backend._lib.DSA_free ) return _DSAParameters(self._backend, dsa_cdata) def public_bytes(self, encoding, format): if format is serialization.PublicFormat.PKCS1: raise ValueError( "DSA public keys do not support PKCS1 serialization" ) return self._backend._public_key_bytes( encoding, format, self, self._evp_pkey, None ) def verify(self, signature, data, algorithm): data, algorithm = _calculate_digest_and_algorithm( self._backend, data, algorithm ) return _dsa_sig_verify(self._backend, self, signature, data) ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/cryptography/hazmat/backends/openssl/ec.py ================================================ # This file is dual licensed under the terms of the Apache License, Version # 2.0, and the BSD License. See the LICENSE file in the root of this repository # for complete details. from __future__ import absolute_import, division, print_function from cryptography import utils from cryptography.exceptions import ( InvalidSignature, UnsupportedAlgorithm, _Reasons ) from cryptography.hazmat.backends.openssl.utils import ( _calculate_digest_and_algorithm, _check_not_prehashed, _warn_sign_verify_deprecated ) from cryptography.hazmat.primitives import hashes, serialization from cryptography.hazmat.primitives.asymmetric import ( AsymmetricSignatureContext, AsymmetricVerificationContext, ec ) def _check_signature_algorithm(signature_algorithm): if not isinstance(signature_algorithm, ec.ECDSA): raise UnsupportedAlgorithm( "Unsupported elliptic curve signature algorithm.", _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM) def _ec_key_curve_sn(backend, ec_key): group = backend._lib.EC_KEY_get0_group(ec_key) backend.openssl_assert(group != backend._ffi.NULL) nid = backend._lib.EC_GROUP_get_curve_name(group) # The following check is to find EC keys with unnamed curves and raise # an error for now. if nid == backend._lib.NID_undef: raise NotImplementedError( "ECDSA keys with unnamed curves are unsupported " "at this time" ) # This is like the above check, but it also catches the case where you # explicitly encoded a curve with the same parameters as a named curve. # Don't do that. if ( backend._lib.CRYPTOGRAPHY_OPENSSL_110_OR_GREATER and backend._lib.EC_GROUP_get_asn1_flag(group) == 0 ): raise NotImplementedError( "ECDSA keys with unnamed curves are unsupported " "at this time" ) curve_name = backend._lib.OBJ_nid2sn(nid) backend.openssl_assert(curve_name != backend._ffi.NULL) sn = backend._ffi.string(curve_name).decode('ascii') return sn def _mark_asn1_named_ec_curve(backend, ec_cdata): """ Set the named curve flag on the EC_KEY. This causes OpenSSL to serialize EC keys along with their curve OID which makes deserialization easier. """ backend._lib.EC_KEY_set_asn1_flag( ec_cdata, backend._lib.OPENSSL_EC_NAMED_CURVE ) def _sn_to_elliptic_curve(backend, sn): try: return ec._CURVE_TYPES[sn]() except KeyError: raise UnsupportedAlgorithm( "{} is not a supported elliptic curve".format(sn), _Reasons.UNSUPPORTED_ELLIPTIC_CURVE ) def _ecdsa_sig_sign(backend, private_key, data): max_size = backend._lib.ECDSA_size(private_key._ec_key) backend.openssl_assert(max_size > 0) sigbuf = backend._ffi.new("unsigned char[]", max_size) siglen_ptr = backend._ffi.new("unsigned int[]", 1) res = backend._lib.ECDSA_sign( 0, data, len(data), sigbuf, siglen_ptr, private_key._ec_key ) backend.openssl_assert(res == 1) return backend._ffi.buffer(sigbuf)[:siglen_ptr[0]] def _ecdsa_sig_verify(backend, public_key, signature, data): res = backend._lib.ECDSA_verify( 0, data, len(data), signature, len(signature), public_key._ec_key ) if res != 1: backend._consume_errors() raise InvalidSignature @utils.register_interface(AsymmetricSignatureContext) class _ECDSASignatureContext(object): def __init__(self, backend, private_key, algorithm): self._backend = backend self._private_key = private_key self._digest = hashes.Hash(algorithm, backend) def update(self, data): self._digest.update(data) def finalize(self): digest = self._digest.finalize() return _ecdsa_sig_sign(self._backend, self._private_key, digest) @utils.register_interface(AsymmetricVerificationContext) class _ECDSAVerificationContext(object): def __init__(self, backend, public_key, signature, algorithm): self._backend = backend self._public_key = public_key self._signature = signature self._digest = hashes.Hash(algorithm, backend) def update(self, data): self._digest.update(data) def verify(self): digest = self._digest.finalize() _ecdsa_sig_verify( self._backend, self._public_key, self._signature, digest ) @utils.register_interface(ec.EllipticCurvePrivateKeyWithSerialization) class _EllipticCurvePrivateKey(object): def __init__(self, backend, ec_key_cdata, evp_pkey): self._backend = backend self._ec_key = ec_key_cdata self._evp_pkey = evp_pkey sn = _ec_key_curve_sn(backend, ec_key_cdata) self._curve = _sn_to_elliptic_curve(backend, sn) _mark_asn1_named_ec_curve(backend, ec_key_cdata) curve = utils.read_only_property("_curve") @property def key_size(self): return self.curve.key_size def signer(self, signature_algorithm): _warn_sign_verify_deprecated() _check_signature_algorithm(signature_algorithm) _check_not_prehashed(signature_algorithm.algorithm) return _ECDSASignatureContext( self._backend, self, signature_algorithm.algorithm ) def exchange(self, algorithm, peer_public_key): if not ( self._backend.elliptic_curve_exchange_algorithm_supported( algorithm, self.curve ) ): raise UnsupportedAlgorithm( "This backend does not support the ECDH algorithm.", _Reasons.UNSUPPORTED_EXCHANGE_ALGORITHM ) if peer_public_key.curve.name != self.curve.name: raise ValueError( "peer_public_key and self are not on the same curve" ) group = self._backend._lib.EC_KEY_get0_group(self._ec_key) z_len = (self._backend._lib.EC_GROUP_get_degree(group) + 7) // 8 self._backend.openssl_assert(z_len > 0) z_buf = self._backend._ffi.new("uint8_t[]", z_len) peer_key = self._backend._lib.EC_KEY_get0_public_key( peer_public_key._ec_key ) r = self._backend._lib.ECDH_compute_key( z_buf, z_len, peer_key, self._ec_key, self._backend._ffi.NULL ) self._backend.openssl_assert(r > 0) return self._backend._ffi.buffer(z_buf)[:z_len] def public_key(self): group = self._backend._lib.EC_KEY_get0_group(self._ec_key) self._backend.openssl_assert(group != self._backend._ffi.NULL) curve_nid = self._backend._lib.EC_GROUP_get_curve_name(group) public_ec_key = self._backend._lib.EC_KEY_new_by_curve_name(curve_nid) self._backend.openssl_assert(public_ec_key != self._backend._ffi.NULL) public_ec_key = self._backend._ffi.gc( public_ec_key, self._backend._lib.EC_KEY_free ) point = self._backend._lib.EC_KEY_get0_public_key(self._ec_key) self._backend.openssl_assert(point != self._backend._ffi.NULL) res = self._backend._lib.EC_KEY_set_public_key(public_ec_key, point) self._backend.openssl_assert(res == 1) evp_pkey = self._backend._ec_cdata_to_evp_pkey(public_ec_key) return _EllipticCurvePublicKey(self._backend, public_ec_key, evp_pkey) def private_numbers(self): bn = self._backend._lib.EC_KEY_get0_private_key(self._ec_key) private_value = self._backend._bn_to_int(bn) return ec.EllipticCurvePrivateNumbers( private_value=private_value, public_numbers=self.public_key().public_numbers() ) def private_bytes(self, encoding, format, encryption_algorithm): return self._backend._private_key_bytes( encoding, format, encryption_algorithm, self._evp_pkey, self._ec_key ) def sign(self, data, signature_algorithm): _check_signature_algorithm(signature_algorithm) data, algorithm = _calculate_digest_and_algorithm( self._backend, data, signature_algorithm._algorithm ) return _ecdsa_sig_sign(self._backend, self, data) @utils.register_interface(ec.EllipticCurvePublicKeyWithSerialization) class _EllipticCurvePublicKey(object): def __init__(self, backend, ec_key_cdata, evp_pkey): self._backend = backend self._ec_key = ec_key_cdata self._evp_pkey = evp_pkey sn = _ec_key_curve_sn(backend, ec_key_cdata) self._curve = _sn_to_elliptic_curve(backend, sn) _mark_asn1_named_ec_curve(backend, ec_key_cdata) curve = utils.read_only_property("_curve") @property def key_size(self): return self.curve.key_size def verifier(self, signature, signature_algorithm): _warn_sign_verify_deprecated() utils._check_bytes("signature", signature) _check_signature_algorithm(signature_algorithm) _check_not_prehashed(signature_algorithm.algorithm) return _ECDSAVerificationContext( self._backend, self, signature, signature_algorithm.algorithm ) def public_numbers(self): get_func, group = ( self._backend._ec_key_determine_group_get_func(self._ec_key) ) point = self._backend._lib.EC_KEY_get0_public_key(self._ec_key) self._backend.openssl_assert(point != self._backend._ffi.NULL) with self._backend._tmp_bn_ctx() as bn_ctx: bn_x = self._backend._lib.BN_CTX_get(bn_ctx) bn_y = self._backend._lib.BN_CTX_get(bn_ctx) res = get_func(group, point, bn_x, bn_y, bn_ctx) self._backend.openssl_assert(res == 1) x = self._backend._bn_to_int(bn_x) y = self._backend._bn_to_int(bn_y) return ec.EllipticCurvePublicNumbers( x=x, y=y, curve=self._curve ) def _encode_point(self, format): if format is serialization.PublicFormat.CompressedPoint: conversion = self._backend._lib.POINT_CONVERSION_COMPRESSED else: assert format is serialization.PublicFormat.UncompressedPoint conversion = self._backend._lib.POINT_CONVERSION_UNCOMPRESSED group = self._backend._lib.EC_KEY_get0_group(self._ec_key) self._backend.openssl_assert(group != self._backend._ffi.NULL) point = self._backend._lib.EC_KEY_get0_public_key(self._ec_key) self._backend.openssl_assert(point != self._backend._ffi.NULL) with self._backend._tmp_bn_ctx() as bn_ctx: buflen = self._backend._lib.EC_POINT_point2oct( group, point, conversion, self._backend._ffi.NULL, 0, bn_ctx ) self._backend.openssl_assert(buflen > 0) buf = self._backend._ffi.new("char[]", buflen) res = self._backend._lib.EC_POINT_point2oct( group, point, conversion, buf, buflen, bn_ctx ) self._backend.openssl_assert(buflen == res) return self._backend._ffi.buffer(buf)[:] def public_bytes(self, encoding, format): if format is serialization.PublicFormat.PKCS1: raise ValueError( "EC public keys do not support PKCS1 serialization" ) if ( encoding is serialization.Encoding.X962 or format is serialization.PublicFormat.CompressedPoint or format is serialization.PublicFormat.UncompressedPoint ): if ( encoding is not serialization.Encoding.X962 or format not in ( serialization.PublicFormat.CompressedPoint, serialization.PublicFormat.UncompressedPoint ) ): raise ValueError( "X962 encoding must be used with CompressedPoint or " "UncompressedPoint format" ) return self._encode_point(format) else: return self._backend._public_key_bytes( encoding, format, self, self._evp_pkey, None ) def verify(self, signature, data, signature_algorithm): _check_signature_algorithm(signature_algorithm) data, algorithm = _calculate_digest_and_algorithm( self._backend, data, signature_algorithm._algorithm ) _ecdsa_sig_verify(self._backend, self, signature, data) ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/cryptography/hazmat/backends/openssl/ed25519.py ================================================ # This file is dual licensed under the terms of the Apache License, Version # 2.0, and the BSD License. See the LICENSE file in the root of this repository # for complete details. from __future__ import absolute_import, division, print_function from cryptography import exceptions, utils from cryptography.hazmat.primitives import serialization from cryptography.hazmat.primitives.asymmetric.ed25519 import ( Ed25519PrivateKey, Ed25519PublicKey, _ED25519_KEY_SIZE, _ED25519_SIG_SIZE ) @utils.register_interface(Ed25519PublicKey) class _Ed25519PublicKey(object): def __init__(self, backend, evp_pkey): self._backend = backend self._evp_pkey = evp_pkey def public_bytes(self, encoding, format): if ( encoding is serialization.Encoding.Raw or format is serialization.PublicFormat.Raw ): if ( encoding is not serialization.Encoding.Raw or format is not serialization.PublicFormat.Raw ): raise ValueError( "When using Raw both encoding and format must be Raw" ) return self._raw_public_bytes() if ( encoding in serialization._PEM_DER and format is not serialization.PublicFormat.SubjectPublicKeyInfo ): raise ValueError( "format must be SubjectPublicKeyInfo when encoding is PEM or " "DER" ) return self._backend._public_key_bytes( encoding, format, self, self._evp_pkey, None ) def _raw_public_bytes(self): buf = self._backend._ffi.new("unsigned char []", _ED25519_KEY_SIZE) buflen = self._backend._ffi.new("size_t *", _ED25519_KEY_SIZE) res = self._backend._lib.EVP_PKEY_get_raw_public_key( self._evp_pkey, buf, buflen ) self._backend.openssl_assert(res == 1) self._backend.openssl_assert(buflen[0] == _ED25519_KEY_SIZE) return self._backend._ffi.buffer(buf, _ED25519_KEY_SIZE)[:] def verify(self, signature, data): evp_md_ctx = self._backend._lib.Cryptography_EVP_MD_CTX_new() self._backend.openssl_assert(evp_md_ctx != self._backend._ffi.NULL) evp_md_ctx = self._backend._ffi.gc( evp_md_ctx, self._backend._lib.Cryptography_EVP_MD_CTX_free ) res = self._backend._lib.EVP_DigestVerifyInit( evp_md_ctx, self._backend._ffi.NULL, self._backend._ffi.NULL, self._backend._ffi.NULL, self._evp_pkey ) self._backend.openssl_assert(res == 1) res = self._backend._lib.EVP_DigestVerify( evp_md_ctx, signature, len(signature), data, len(data) ) if res != 1: self._backend._consume_errors() raise exceptions.InvalidSignature @utils.register_interface(Ed25519PrivateKey) class _Ed25519PrivateKey(object): def __init__(self, backend, evp_pkey): self._backend = backend self._evp_pkey = evp_pkey def public_key(self): buf = self._backend._ffi.new("unsigned char []", _ED25519_KEY_SIZE) buflen = self._backend._ffi.new("size_t *", _ED25519_KEY_SIZE) res = self._backend._lib.EVP_PKEY_get_raw_public_key( self._evp_pkey, buf, buflen ) self._backend.openssl_assert(res == 1) self._backend.openssl_assert(buflen[0] == _ED25519_KEY_SIZE) public_bytes = self._backend._ffi.buffer(buf)[:] return self._backend.ed25519_load_public_bytes(public_bytes) def sign(self, data): evp_md_ctx = self._backend._lib.Cryptography_EVP_MD_CTX_new() self._backend.openssl_assert(evp_md_ctx != self._backend._ffi.NULL) evp_md_ctx = self._backend._ffi.gc( evp_md_ctx, self._backend._lib.Cryptography_EVP_MD_CTX_free ) res = self._backend._lib.EVP_DigestSignInit( evp_md_ctx, self._backend._ffi.NULL, self._backend._ffi.NULL, self._backend._ffi.NULL, self._evp_pkey ) self._backend.openssl_assert(res == 1) buf = self._backend._ffi.new("unsigned char[]", _ED25519_SIG_SIZE) buflen = self._backend._ffi.new("size_t *", len(buf)) res = self._backend._lib.EVP_DigestSign( evp_md_ctx, buf, buflen, data, len(data) ) self._backend.openssl_assert(res == 1) self._backend.openssl_assert(buflen[0] == _ED25519_SIG_SIZE) return self._backend._ffi.buffer(buf, buflen[0])[:] def private_bytes(self, encoding, format, encryption_algorithm): if ( encoding is serialization.Encoding.Raw or format is serialization.PublicFormat.Raw ): if ( format is not serialization.PrivateFormat.Raw or encoding is not serialization.Encoding.Raw or not isinstance(encryption_algorithm, serialization.NoEncryption) ): raise ValueError( "When using Raw both encoding and format must be Raw " "and encryption_algorithm must be NoEncryption()" ) return self._raw_private_bytes() if ( encoding in serialization._PEM_DER and format is not serialization.PrivateFormat.PKCS8 ): raise ValueError( "format must be PKCS8 when encoding is PEM or DER" ) return self._backend._private_key_bytes( encoding, format, encryption_algorithm, self._evp_pkey, None ) def _raw_private_bytes(self): buf = self._backend._ffi.new("unsigned char []", _ED25519_KEY_SIZE) buflen = self._backend._ffi.new("size_t *", _ED25519_KEY_SIZE) res = self._backend._lib.EVP_PKEY_get_raw_private_key( self._evp_pkey, buf, buflen ) self._backend.openssl_assert(res == 1) self._backend.openssl_assert(buflen[0] == _ED25519_KEY_SIZE) return self._backend._ffi.buffer(buf, _ED25519_KEY_SIZE)[:] ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/cryptography/hazmat/backends/openssl/ed448.py ================================================ # This file is dual licensed under the terms of the Apache License, Version # 2.0, and the BSD License. See the LICENSE file in the root of this repository # for complete details. from __future__ import absolute_import, division, print_function from cryptography import exceptions, utils from cryptography.hazmat.primitives import serialization from cryptography.hazmat.primitives.asymmetric.ed448 import ( Ed448PrivateKey, Ed448PublicKey ) _ED448_KEY_SIZE = 57 _ED448_SIG_SIZE = 114 @utils.register_interface(Ed448PublicKey) class _Ed448PublicKey(object): def __init__(self, backend, evp_pkey): self._backend = backend self._evp_pkey = evp_pkey def public_bytes(self, encoding, format): if ( encoding is serialization.Encoding.Raw or format is serialization.PublicFormat.Raw ): if ( encoding is not serialization.Encoding.Raw or format is not serialization.PublicFormat.Raw ): raise ValueError( "When using Raw both encoding and format must be Raw" ) return self._raw_public_bytes() if ( encoding in serialization._PEM_DER and format is not serialization.PublicFormat.SubjectPublicKeyInfo ): raise ValueError( "format must be SubjectPublicKeyInfo when encoding is PEM or " "DER" ) return self._backend._public_key_bytes( encoding, format, self, self._evp_pkey, None ) def _raw_public_bytes(self): buf = self._backend._ffi.new("unsigned char []", _ED448_KEY_SIZE) buflen = self._backend._ffi.new("size_t *", _ED448_KEY_SIZE) res = self._backend._lib.EVP_PKEY_get_raw_public_key( self._evp_pkey, buf, buflen ) self._backend.openssl_assert(res == 1) self._backend.openssl_assert(buflen[0] == _ED448_KEY_SIZE) return self._backend._ffi.buffer(buf, _ED448_KEY_SIZE)[:] def verify(self, signature, data): evp_md_ctx = self._backend._lib.Cryptography_EVP_MD_CTX_new() self._backend.openssl_assert(evp_md_ctx != self._backend._ffi.NULL) evp_md_ctx = self._backend._ffi.gc( evp_md_ctx, self._backend._lib.Cryptography_EVP_MD_CTX_free ) res = self._backend._lib.EVP_DigestVerifyInit( evp_md_ctx, self._backend._ffi.NULL, self._backend._ffi.NULL, self._backend._ffi.NULL, self._evp_pkey ) self._backend.openssl_assert(res == 1) res = self._backend._lib.EVP_DigestVerify( evp_md_ctx, signature, len(signature), data, len(data) ) if res != 1: self._backend._consume_errors() raise exceptions.InvalidSignature @utils.register_interface(Ed448PrivateKey) class _Ed448PrivateKey(object): def __init__(self, backend, evp_pkey): self._backend = backend self._evp_pkey = evp_pkey def public_key(self): buf = self._backend._ffi.new("unsigned char []", _ED448_KEY_SIZE) buflen = self._backend._ffi.new("size_t *", _ED448_KEY_SIZE) res = self._backend._lib.EVP_PKEY_get_raw_public_key( self._evp_pkey, buf, buflen ) self._backend.openssl_assert(res == 1) self._backend.openssl_assert(buflen[0] == _ED448_KEY_SIZE) public_bytes = self._backend._ffi.buffer(buf)[:] return self._backend.ed448_load_public_bytes(public_bytes) def sign(self, data): evp_md_ctx = self._backend._lib.Cryptography_EVP_MD_CTX_new() self._backend.openssl_assert(evp_md_ctx != self._backend._ffi.NULL) evp_md_ctx = self._backend._ffi.gc( evp_md_ctx, self._backend._lib.Cryptography_EVP_MD_CTX_free ) res = self._backend._lib.EVP_DigestSignInit( evp_md_ctx, self._backend._ffi.NULL, self._backend._ffi.NULL, self._backend._ffi.NULL, self._evp_pkey ) self._backend.openssl_assert(res == 1) buf = self._backend._ffi.new("unsigned char[]", _ED448_SIG_SIZE) buflen = self._backend._ffi.new("size_t *", len(buf)) res = self._backend._lib.EVP_DigestSign( evp_md_ctx, buf, buflen, data, len(data) ) self._backend.openssl_assert(res == 1) self._backend.openssl_assert(buflen[0] == _ED448_SIG_SIZE) return self._backend._ffi.buffer(buf, buflen[0])[:] def private_bytes(self, encoding, format, encryption_algorithm): if ( encoding is serialization.Encoding.Raw or format is serialization.PublicFormat.Raw ): if ( format is not serialization.PrivateFormat.Raw or encoding is not serialization.Encoding.Raw or not isinstance(encryption_algorithm, serialization.NoEncryption) ): raise ValueError( "When using Raw both encoding and format must be Raw " "and encryption_algorithm must be NoEncryption()" ) return self._raw_private_bytes() if ( encoding in serialization._PEM_DER and format is not serialization.PrivateFormat.PKCS8 ): raise ValueError( "format must be PKCS8 when encoding is PEM or DER" ) return self._backend._private_key_bytes( encoding, format, encryption_algorithm, self._evp_pkey, None ) def _raw_private_bytes(self): buf = self._backend._ffi.new("unsigned char []", _ED448_KEY_SIZE) buflen = self._backend._ffi.new("size_t *", _ED448_KEY_SIZE) res = self._backend._lib.EVP_PKEY_get_raw_private_key( self._evp_pkey, buf, buflen ) self._backend.openssl_assert(res == 1) self._backend.openssl_assert(buflen[0] == _ED448_KEY_SIZE) return self._backend._ffi.buffer(buf, _ED448_KEY_SIZE)[:] ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/cryptography/hazmat/backends/openssl/encode_asn1.py ================================================ # This file is dual licensed under the terms of the Apache License, Version # 2.0, and the BSD License. See the LICENSE file in the root of this repository # for complete details. from __future__ import absolute_import, division, print_function import calendar import ipaddress import six from cryptography import utils, x509 from cryptography.hazmat.backends.openssl.decode_asn1 import ( _CRL_ENTRY_REASON_ENUM_TO_CODE, _DISTPOINT_TYPE_FULLNAME, _DISTPOINT_TYPE_RELATIVENAME ) from cryptography.x509.name import _ASN1Type from cryptography.x509.oid import ( CRLEntryExtensionOID, ExtensionOID, OCSPExtensionOID, ) def _encode_asn1_int(backend, x): """ Converts a python integer to an ASN1_INTEGER. The returned ASN1_INTEGER will not be garbage collected (to support adding them to structs that take ownership of the object). Be sure to register it for GC if it will be discarded after use. """ # Convert Python integer to OpenSSL "bignum" in case value exceeds # machine's native integer limits (note: `int_to_bn` doesn't automatically # GC). i = backend._int_to_bn(x) i = backend._ffi.gc(i, backend._lib.BN_free) # Wrap in an ASN.1 integer. Don't GC -- as documented. i = backend._lib.BN_to_ASN1_INTEGER(i, backend._ffi.NULL) backend.openssl_assert(i != backend._ffi.NULL) return i def _encode_asn1_int_gc(backend, x): i = _encode_asn1_int(backend, x) i = backend._ffi.gc(i, backend._lib.ASN1_INTEGER_free) return i def _encode_asn1_str(backend, data): """ Create an ASN1_OCTET_STRING from a Python byte string. """ s = backend._lib.ASN1_OCTET_STRING_new() res = backend._lib.ASN1_OCTET_STRING_set(s, data, len(data)) backend.openssl_assert(res == 1) return s def _encode_asn1_utf8_str(backend, string): """ Create an ASN1_UTF8STRING from a Python unicode string. This object will be an ASN1_STRING with UTF8 type in OpenSSL and can be decoded with ASN1_STRING_to_UTF8. """ s = backend._lib.ASN1_UTF8STRING_new() res = backend._lib.ASN1_STRING_set( s, string.encode("utf8"), len(string.encode("utf8")) ) backend.openssl_assert(res == 1) return s def _encode_asn1_str_gc(backend, data): s = _encode_asn1_str(backend, data) s = backend._ffi.gc(s, backend._lib.ASN1_OCTET_STRING_free) return s def _encode_inhibit_any_policy(backend, inhibit_any_policy): return _encode_asn1_int_gc(backend, inhibit_any_policy.skip_certs) def _encode_name(backend, name): """ The X509_NAME created will not be gc'd. Use _encode_name_gc if needed. """ subject = backend._lib.X509_NAME_new() for rdn in name.rdns: set_flag = 0 # indicate whether to add to last RDN or create new RDN for attribute in rdn: name_entry = _encode_name_entry(backend, attribute) # X509_NAME_add_entry dups the object so we need to gc this copy name_entry = backend._ffi.gc( name_entry, backend._lib.X509_NAME_ENTRY_free ) res = backend._lib.X509_NAME_add_entry( subject, name_entry, -1, set_flag) backend.openssl_assert(res == 1) set_flag = -1 return subject def _encode_name_gc(backend, attributes): subject = _encode_name(backend, attributes) subject = backend._ffi.gc(subject, backend._lib.X509_NAME_free) return subject def _encode_sk_name_entry(backend, attributes): """ The sk_X509_NAME_ENTRY created will not be gc'd. """ stack = backend._lib.sk_X509_NAME_ENTRY_new_null() for attribute in attributes: name_entry = _encode_name_entry(backend, attribute) res = backend._lib.sk_X509_NAME_ENTRY_push(stack, name_entry) backend.openssl_assert(res >= 1) return stack def _encode_name_entry(backend, attribute): if attribute._type is _ASN1Type.BMPString: value = attribute.value.encode('utf_16_be') elif attribute._type is _ASN1Type.UniversalString: value = attribute.value.encode('utf_32_be') else: value = attribute.value.encode('utf8') obj = _txt2obj_gc(backend, attribute.oid.dotted_string) name_entry = backend._lib.X509_NAME_ENTRY_create_by_OBJ( backend._ffi.NULL, obj, attribute._type.value, value, len(value) ) return name_entry def _encode_crl_number_delta_crl_indicator(backend, ext): return _encode_asn1_int_gc(backend, ext.crl_number) def _encode_issuing_dist_point(backend, ext): idp = backend._lib.ISSUING_DIST_POINT_new() backend.openssl_assert(idp != backend._ffi.NULL) idp = backend._ffi.gc(idp, backend._lib.ISSUING_DIST_POINT_free) idp.onlyuser = 255 if ext.only_contains_user_certs else 0 idp.onlyCA = 255 if ext.only_contains_ca_certs else 0 idp.indirectCRL = 255 if ext.indirect_crl else 0 idp.onlyattr = 255 if ext.only_contains_attribute_certs else 0 if ext.only_some_reasons: idp.onlysomereasons = _encode_reasonflags( backend, ext.only_some_reasons ) if ext.full_name: idp.distpoint = _encode_full_name(backend, ext.full_name) if ext.relative_name: idp.distpoint = _encode_relative_name(backend, ext.relative_name) return idp def _encode_crl_reason(backend, crl_reason): asn1enum = backend._lib.ASN1_ENUMERATED_new() backend.openssl_assert(asn1enum != backend._ffi.NULL) asn1enum = backend._ffi.gc(asn1enum, backend._lib.ASN1_ENUMERATED_free) res = backend._lib.ASN1_ENUMERATED_set( asn1enum, _CRL_ENTRY_REASON_ENUM_TO_CODE[crl_reason.reason] ) backend.openssl_assert(res == 1) return asn1enum def _encode_invalidity_date(backend, invalidity_date): time = backend._lib.ASN1_GENERALIZEDTIME_set( backend._ffi.NULL, calendar.timegm( invalidity_date.invalidity_date.timetuple() ) ) backend.openssl_assert(time != backend._ffi.NULL) time = backend._ffi.gc(time, backend._lib.ASN1_GENERALIZEDTIME_free) return time def _encode_certificate_policies(backend, certificate_policies): cp = backend._lib.sk_POLICYINFO_new_null() backend.openssl_assert(cp != backend._ffi.NULL) cp = backend._ffi.gc(cp, backend._lib.sk_POLICYINFO_free) for policy_info in certificate_policies: pi = backend._lib.POLICYINFO_new() backend.openssl_assert(pi != backend._ffi.NULL) res = backend._lib.sk_POLICYINFO_push(cp, pi) backend.openssl_assert(res >= 1) oid = _txt2obj(backend, policy_info.policy_identifier.dotted_string) pi.policyid = oid if policy_info.policy_qualifiers: pqis = backend._lib.sk_POLICYQUALINFO_new_null() backend.openssl_assert(pqis != backend._ffi.NULL) for qualifier in policy_info.policy_qualifiers: pqi = backend._lib.POLICYQUALINFO_new() backend.openssl_assert(pqi != backend._ffi.NULL) res = backend._lib.sk_POLICYQUALINFO_push(pqis, pqi) backend.openssl_assert(res >= 1) if isinstance(qualifier, six.text_type): pqi.pqualid = _txt2obj( backend, x509.OID_CPS_QUALIFIER.dotted_string ) pqi.d.cpsuri = _encode_asn1_str( backend, qualifier.encode("ascii"), ) else: assert isinstance(qualifier, x509.UserNotice) pqi.pqualid = _txt2obj( backend, x509.OID_CPS_USER_NOTICE.dotted_string ) un = backend._lib.USERNOTICE_new() backend.openssl_assert(un != backend._ffi.NULL) pqi.d.usernotice = un if qualifier.explicit_text: un.exptext = _encode_asn1_utf8_str( backend, qualifier.explicit_text ) un.noticeref = _encode_notice_reference( backend, qualifier.notice_reference ) pi.qualifiers = pqis return cp def _encode_notice_reference(backend, notice): if notice is None: return backend._ffi.NULL else: nr = backend._lib.NOTICEREF_new() backend.openssl_assert(nr != backend._ffi.NULL) # organization is a required field nr.organization = _encode_asn1_utf8_str(backend, notice.organization) notice_stack = backend._lib.sk_ASN1_INTEGER_new_null() nr.noticenos = notice_stack for number in notice.notice_numbers: num = _encode_asn1_int(backend, number) res = backend._lib.sk_ASN1_INTEGER_push(notice_stack, num) backend.openssl_assert(res >= 1) return nr def _txt2obj(backend, name): """ Converts a Python string with an ASN.1 object ID in dotted form to a ASN1_OBJECT. """ name = name.encode('ascii') obj = backend._lib.OBJ_txt2obj(name, 1) backend.openssl_assert(obj != backend._ffi.NULL) return obj def _txt2obj_gc(backend, name): obj = _txt2obj(backend, name) obj = backend._ffi.gc(obj, backend._lib.ASN1_OBJECT_free) return obj def _encode_ocsp_nocheck(backend, ext): # Doesn't need to be GC'd return backend._lib.ASN1_NULL_new() def _encode_key_usage(backend, key_usage): set_bit = backend._lib.ASN1_BIT_STRING_set_bit ku = backend._lib.ASN1_BIT_STRING_new() ku = backend._ffi.gc(ku, backend._lib.ASN1_BIT_STRING_free) res = set_bit(ku, 0, key_usage.digital_signature) backend.openssl_assert(res == 1) res = set_bit(ku, 1, key_usage.content_commitment) backend.openssl_assert(res == 1) res = set_bit(ku, 2, key_usage.key_encipherment) backend.openssl_assert(res == 1) res = set_bit(ku, 3, key_usage.data_encipherment) backend.openssl_assert(res == 1) res = set_bit(ku, 4, key_usage.key_agreement) backend.openssl_assert(res == 1) res = set_bit(ku, 5, key_usage.key_cert_sign) backend.openssl_assert(res == 1) res = set_bit(ku, 6, key_usage.crl_sign) backend.openssl_assert(res == 1) if key_usage.key_agreement: res = set_bit(ku, 7, key_usage.encipher_only) backend.openssl_assert(res == 1) res = set_bit(ku, 8, key_usage.decipher_only) backend.openssl_assert(res == 1) else: res = set_bit(ku, 7, 0) backend.openssl_assert(res == 1) res = set_bit(ku, 8, 0) backend.openssl_assert(res == 1) return ku def _encode_authority_key_identifier(backend, authority_keyid): akid = backend._lib.AUTHORITY_KEYID_new() backend.openssl_assert(akid != backend._ffi.NULL) akid = backend._ffi.gc(akid, backend._lib.AUTHORITY_KEYID_free) if authority_keyid.key_identifier is not None: akid.keyid = _encode_asn1_str( backend, authority_keyid.key_identifier, ) if authority_keyid.authority_cert_issuer is not None: akid.issuer = _encode_general_names( backend, authority_keyid.authority_cert_issuer ) if authority_keyid.authority_cert_serial_number is not None: akid.serial = _encode_asn1_int( backend, authority_keyid.authority_cert_serial_number ) return akid def _encode_basic_constraints(backend, basic_constraints): constraints = backend._lib.BASIC_CONSTRAINTS_new() constraints = backend._ffi.gc( constraints, backend._lib.BASIC_CONSTRAINTS_free ) constraints.ca = 255 if basic_constraints.ca else 0 if basic_constraints.ca and basic_constraints.path_length is not None: constraints.pathlen = _encode_asn1_int( backend, basic_constraints.path_length ) return constraints def _encode_authority_information_access(backend, authority_info_access): aia = backend._lib.sk_ACCESS_DESCRIPTION_new_null() backend.openssl_assert(aia != backend._ffi.NULL) aia = backend._ffi.gc( aia, lambda x: backend._lib.sk_ACCESS_DESCRIPTION_pop_free( x, backend._ffi.addressof( backend._lib._original_lib, "ACCESS_DESCRIPTION_free" ) ) ) for access_description in authority_info_access: ad = backend._lib.ACCESS_DESCRIPTION_new() method = _txt2obj( backend, access_description.access_method.dotted_string ) _encode_general_name_preallocated( backend, access_description.access_location, ad.location ) ad.method = method res = backend._lib.sk_ACCESS_DESCRIPTION_push(aia, ad) backend.openssl_assert(res >= 1) return aia def _encode_general_names(backend, names): general_names = backend._lib.GENERAL_NAMES_new() backend.openssl_assert(general_names != backend._ffi.NULL) for name in names: gn = _encode_general_name(backend, name) res = backend._lib.sk_GENERAL_NAME_push(general_names, gn) backend.openssl_assert(res != 0) return general_names def _encode_alt_name(backend, san): general_names = _encode_general_names(backend, san) general_names = backend._ffi.gc( general_names, backend._lib.GENERAL_NAMES_free ) return general_names def _encode_subject_key_identifier(backend, ski): return _encode_asn1_str_gc(backend, ski.digest) def _encode_general_name(backend, name): gn = backend._lib.GENERAL_NAME_new() _encode_general_name_preallocated(backend, name, gn) return gn def _encode_general_name_preallocated(backend, name, gn): if isinstance(name, x509.DNSName): backend.openssl_assert(gn != backend._ffi.NULL) gn.type = backend._lib.GEN_DNS ia5 = backend._lib.ASN1_IA5STRING_new() backend.openssl_assert(ia5 != backend._ffi.NULL) # ia5strings are supposed to be ITU T.50 but to allow round-tripping # of broken certs that encode utf8 we'll encode utf8 here too. value = name.value.encode("utf8") res = backend._lib.ASN1_STRING_set(ia5, value, len(value)) backend.openssl_assert(res == 1) gn.d.dNSName = ia5 elif isinstance(name, x509.RegisteredID): backend.openssl_assert(gn != backend._ffi.NULL) gn.type = backend._lib.GEN_RID obj = backend._lib.OBJ_txt2obj( name.value.dotted_string.encode('ascii'), 1 ) backend.openssl_assert(obj != backend._ffi.NULL) gn.d.registeredID = obj elif isinstance(name, x509.DirectoryName): backend.openssl_assert(gn != backend._ffi.NULL) dir_name = _encode_name(backend, name.value) gn.type = backend._lib.GEN_DIRNAME gn.d.directoryName = dir_name elif isinstance(name, x509.IPAddress): backend.openssl_assert(gn != backend._ffi.NULL) if isinstance(name.value, ipaddress.IPv4Network): packed = ( name.value.network_address.packed + utils.int_to_bytes(((1 << 32) - name.value.num_addresses), 4) ) elif isinstance(name.value, ipaddress.IPv6Network): packed = ( name.value.network_address.packed + utils.int_to_bytes((1 << 128) - name.value.num_addresses, 16) ) else: packed = name.value.packed ipaddr = _encode_asn1_str(backend, packed) gn.type = backend._lib.GEN_IPADD gn.d.iPAddress = ipaddr elif isinstance(name, x509.OtherName): backend.openssl_assert(gn != backend._ffi.NULL) other_name = backend._lib.OTHERNAME_new() backend.openssl_assert(other_name != backend._ffi.NULL) type_id = backend._lib.OBJ_txt2obj( name.type_id.dotted_string.encode('ascii'), 1 ) backend.openssl_assert(type_id != backend._ffi.NULL) data = backend._ffi.new("unsigned char[]", name.value) data_ptr_ptr = backend._ffi.new("unsigned char **") data_ptr_ptr[0] = data value = backend._lib.d2i_ASN1_TYPE( backend._ffi.NULL, data_ptr_ptr, len(name.value) ) if value == backend._ffi.NULL: backend._consume_errors() raise ValueError("Invalid ASN.1 data") other_name.type_id = type_id other_name.value = value gn.type = backend._lib.GEN_OTHERNAME gn.d.otherName = other_name elif isinstance(name, x509.RFC822Name): backend.openssl_assert(gn != backend._ffi.NULL) # ia5strings are supposed to be ITU T.50 but to allow round-tripping # of broken certs that encode utf8 we'll encode utf8 here too. data = name.value.encode("utf8") asn1_str = _encode_asn1_str(backend, data) gn.type = backend._lib.GEN_EMAIL gn.d.rfc822Name = asn1_str elif isinstance(name, x509.UniformResourceIdentifier): backend.openssl_assert(gn != backend._ffi.NULL) # ia5strings are supposed to be ITU T.50 but to allow round-tripping # of broken certs that encode utf8 we'll encode utf8 here too. data = name.value.encode("utf8") asn1_str = _encode_asn1_str(backend, data) gn.type = backend._lib.GEN_URI gn.d.uniformResourceIdentifier = asn1_str else: raise ValueError( "{} is an unknown GeneralName type".format(name) ) def _encode_extended_key_usage(backend, extended_key_usage): eku = backend._lib.sk_ASN1_OBJECT_new_null() eku = backend._ffi.gc(eku, backend._lib.sk_ASN1_OBJECT_free) for oid in extended_key_usage: obj = _txt2obj(backend, oid.dotted_string) res = backend._lib.sk_ASN1_OBJECT_push(eku, obj) backend.openssl_assert(res >= 1) return eku _CRLREASONFLAGS = { x509.ReasonFlags.key_compromise: 1, x509.ReasonFlags.ca_compromise: 2, x509.ReasonFlags.affiliation_changed: 3, x509.ReasonFlags.superseded: 4, x509.ReasonFlags.cessation_of_operation: 5, x509.ReasonFlags.certificate_hold: 6, x509.ReasonFlags.privilege_withdrawn: 7, x509.ReasonFlags.aa_compromise: 8, } def _encode_reasonflags(backend, reasons): bitmask = backend._lib.ASN1_BIT_STRING_new() backend.openssl_assert(bitmask != backend._ffi.NULL) for reason in reasons: res = backend._lib.ASN1_BIT_STRING_set_bit( bitmask, _CRLREASONFLAGS[reason], 1 ) backend.openssl_assert(res == 1) return bitmask def _encode_full_name(backend, full_name): dpn = backend._lib.DIST_POINT_NAME_new() backend.openssl_assert(dpn != backend._ffi.NULL) dpn.type = _DISTPOINT_TYPE_FULLNAME dpn.name.fullname = _encode_general_names(backend, full_name) return dpn def _encode_relative_name(backend, relative_name): dpn = backend._lib.DIST_POINT_NAME_new() backend.openssl_assert(dpn != backend._ffi.NULL) dpn.type = _DISTPOINT_TYPE_RELATIVENAME dpn.name.relativename = _encode_sk_name_entry(backend, relative_name) return dpn def _encode_cdps_freshest_crl(backend, cdps): cdp = backend._lib.sk_DIST_POINT_new_null() cdp = backend._ffi.gc(cdp, backend._lib.sk_DIST_POINT_free) for point in cdps: dp = backend._lib.DIST_POINT_new() backend.openssl_assert(dp != backend._ffi.NULL) if point.reasons: dp.reasons = _encode_reasonflags(backend, point.reasons) if point.full_name: dp.distpoint = _encode_full_name(backend, point.full_name) if point.relative_name: dp.distpoint = _encode_relative_name(backend, point.relative_name) if point.crl_issuer: dp.CRLissuer = _encode_general_names(backend, point.crl_issuer) res = backend._lib.sk_DIST_POINT_push(cdp, dp) backend.openssl_assert(res >= 1) return cdp def _encode_name_constraints(backend, name_constraints): nc = backend._lib.NAME_CONSTRAINTS_new() backend.openssl_assert(nc != backend._ffi.NULL) nc = backend._ffi.gc(nc, backend._lib.NAME_CONSTRAINTS_free) permitted = _encode_general_subtree( backend, name_constraints.permitted_subtrees ) nc.permittedSubtrees = permitted excluded = _encode_general_subtree( backend, name_constraints.excluded_subtrees ) nc.excludedSubtrees = excluded return nc def _encode_policy_constraints(backend, policy_constraints): pc = backend._lib.POLICY_CONSTRAINTS_new() backend.openssl_assert(pc != backend._ffi.NULL) pc = backend._ffi.gc(pc, backend._lib.POLICY_CONSTRAINTS_free) if policy_constraints.require_explicit_policy is not None: pc.requireExplicitPolicy = _encode_asn1_int( backend, policy_constraints.require_explicit_policy ) if policy_constraints.inhibit_policy_mapping is not None: pc.inhibitPolicyMapping = _encode_asn1_int( backend, policy_constraints.inhibit_policy_mapping ) return pc def _encode_general_subtree(backend, subtrees): if subtrees is None: return backend._ffi.NULL else: general_subtrees = backend._lib.sk_GENERAL_SUBTREE_new_null() for name in subtrees: gs = backend._lib.GENERAL_SUBTREE_new() gs.base = _encode_general_name(backend, name) res = backend._lib.sk_GENERAL_SUBTREE_push(general_subtrees, gs) assert res >= 1 return general_subtrees def _encode_nonce(backend, nonce): return _encode_asn1_str_gc(backend, nonce.nonce) _EXTENSION_ENCODE_HANDLERS = { ExtensionOID.BASIC_CONSTRAINTS: _encode_basic_constraints, ExtensionOID.SUBJECT_KEY_IDENTIFIER: _encode_subject_key_identifier, ExtensionOID.KEY_USAGE: _encode_key_usage, ExtensionOID.SUBJECT_ALTERNATIVE_NAME: _encode_alt_name, ExtensionOID.ISSUER_ALTERNATIVE_NAME: _encode_alt_name, ExtensionOID.EXTENDED_KEY_USAGE: _encode_extended_key_usage, ExtensionOID.AUTHORITY_KEY_IDENTIFIER: _encode_authority_key_identifier, ExtensionOID.CERTIFICATE_POLICIES: _encode_certificate_policies, ExtensionOID.AUTHORITY_INFORMATION_ACCESS: ( _encode_authority_information_access ), ExtensionOID.CRL_DISTRIBUTION_POINTS: _encode_cdps_freshest_crl, ExtensionOID.FRESHEST_CRL: _encode_cdps_freshest_crl, ExtensionOID.INHIBIT_ANY_POLICY: _encode_inhibit_any_policy, ExtensionOID.OCSP_NO_CHECK: _encode_ocsp_nocheck, ExtensionOID.NAME_CONSTRAINTS: _encode_name_constraints, ExtensionOID.POLICY_CONSTRAINTS: _encode_policy_constraints, } _CRL_EXTENSION_ENCODE_HANDLERS = { ExtensionOID.ISSUER_ALTERNATIVE_NAME: _encode_alt_name, ExtensionOID.AUTHORITY_KEY_IDENTIFIER: _encode_authority_key_identifier, ExtensionOID.AUTHORITY_INFORMATION_ACCESS: ( _encode_authority_information_access ), ExtensionOID.CRL_NUMBER: _encode_crl_number_delta_crl_indicator, ExtensionOID.DELTA_CRL_INDICATOR: _encode_crl_number_delta_crl_indicator, ExtensionOID.ISSUING_DISTRIBUTION_POINT: _encode_issuing_dist_point, ExtensionOID.FRESHEST_CRL: _encode_cdps_freshest_crl, } _CRL_ENTRY_EXTENSION_ENCODE_HANDLERS = { CRLEntryExtensionOID.CERTIFICATE_ISSUER: _encode_alt_name, CRLEntryExtensionOID.CRL_REASON: _encode_crl_reason, CRLEntryExtensionOID.INVALIDITY_DATE: _encode_invalidity_date, } _OCSP_REQUEST_EXTENSION_ENCODE_HANDLERS = { OCSPExtensionOID.NONCE: _encode_nonce, } _OCSP_BASICRESP_EXTENSION_ENCODE_HANDLERS = { OCSPExtensionOID.NONCE: _encode_nonce, } ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/cryptography/hazmat/backends/openssl/hashes.py ================================================ # This file is dual licensed under the terms of the Apache License, Version # 2.0, and the BSD License. See the LICENSE file in the root of this repository # for complete details. from __future__ import absolute_import, division, print_function from cryptography import utils from cryptography.exceptions import UnsupportedAlgorithm, _Reasons from cryptography.hazmat.primitives import hashes @utils.register_interface(hashes.HashContext) class _HashContext(object): def __init__(self, backend, algorithm, ctx=None): self._algorithm = algorithm self._backend = backend if ctx is None: ctx = self._backend._lib.Cryptography_EVP_MD_CTX_new() ctx = self._backend._ffi.gc( ctx, self._backend._lib.Cryptography_EVP_MD_CTX_free ) evp_md = self._backend._evp_md_from_algorithm(algorithm) if evp_md == self._backend._ffi.NULL: raise UnsupportedAlgorithm( "{} is not a supported hash on this backend.".format( algorithm.name), _Reasons.UNSUPPORTED_HASH ) res = self._backend._lib.EVP_DigestInit_ex(ctx, evp_md, self._backend._ffi.NULL) self._backend.openssl_assert(res != 0) self._ctx = ctx algorithm = utils.read_only_property("_algorithm") def copy(self): copied_ctx = self._backend._lib.Cryptography_EVP_MD_CTX_new() copied_ctx = self._backend._ffi.gc( copied_ctx, self._backend._lib.Cryptography_EVP_MD_CTX_free ) res = self._backend._lib.EVP_MD_CTX_copy_ex(copied_ctx, self._ctx) self._backend.openssl_assert(res != 0) return _HashContext(self._backend, self.algorithm, ctx=copied_ctx) def update(self, data): data_ptr = self._backend._ffi.from_buffer(data) res = self._backend._lib.EVP_DigestUpdate( self._ctx, data_ptr, len(data) ) self._backend.openssl_assert(res != 0) def finalize(self): if isinstance(self.algorithm, hashes.ExtendableOutputFunction): # extendable output functions use a different finalize return self._finalize_xof() else: buf = self._backend._ffi.new("unsigned char[]", self._backend._lib.EVP_MAX_MD_SIZE) outlen = self._backend._ffi.new("unsigned int *") res = self._backend._lib.EVP_DigestFinal_ex(self._ctx, buf, outlen) self._backend.openssl_assert(res != 0) self._backend.openssl_assert( outlen[0] == self.algorithm.digest_size ) return self._backend._ffi.buffer(buf)[:outlen[0]] def _finalize_xof(self): buf = self._backend._ffi.new("unsigned char[]", self.algorithm.digest_size) res = self._backend._lib.EVP_DigestFinalXOF( self._ctx, buf, self.algorithm.digest_size ) self._backend.openssl_assert(res != 0) return self._backend._ffi.buffer(buf)[:self.algorithm.digest_size] ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/cryptography/hazmat/backends/openssl/hmac.py ================================================ # This file is dual licensed under the terms of the Apache License, Version # 2.0, and the BSD License. See the LICENSE file in the root of this repository # for complete details. from __future__ import absolute_import, division, print_function from cryptography import utils from cryptography.exceptions import ( InvalidSignature, UnsupportedAlgorithm, _Reasons ) from cryptography.hazmat.primitives import constant_time, hashes @utils.register_interface(hashes.HashContext) class _HMACContext(object): def __init__(self, backend, key, algorithm, ctx=None): self._algorithm = algorithm self._backend = backend if ctx is None: ctx = self._backend._lib.Cryptography_HMAC_CTX_new() self._backend.openssl_assert(ctx != self._backend._ffi.NULL) ctx = self._backend._ffi.gc( ctx, self._backend._lib.Cryptography_HMAC_CTX_free ) evp_md = self._backend._evp_md_from_algorithm(algorithm) if evp_md == self._backend._ffi.NULL: raise UnsupportedAlgorithm( "{} is not a supported hash on this backend".format( algorithm.name), _Reasons.UNSUPPORTED_HASH ) key_ptr = self._backend._ffi.from_buffer(key) res = self._backend._lib.HMAC_Init_ex( ctx, key_ptr, len(key), evp_md, self._backend._ffi.NULL ) self._backend.openssl_assert(res != 0) self._ctx = ctx self._key = key algorithm = utils.read_only_property("_algorithm") def copy(self): copied_ctx = self._backend._lib.Cryptography_HMAC_CTX_new() self._backend.openssl_assert(copied_ctx != self._backend._ffi.NULL) copied_ctx = self._backend._ffi.gc( copied_ctx, self._backend._lib.Cryptography_HMAC_CTX_free ) res = self._backend._lib.HMAC_CTX_copy(copied_ctx, self._ctx) self._backend.openssl_assert(res != 0) return _HMACContext( self._backend, self._key, self.algorithm, ctx=copied_ctx ) def update(self, data): data_ptr = self._backend._ffi.from_buffer(data) res = self._backend._lib.HMAC_Update(self._ctx, data_ptr, len(data)) self._backend.openssl_assert(res != 0) def finalize(self): buf = self._backend._ffi.new("unsigned char[]", self._backend._lib.EVP_MAX_MD_SIZE) outlen = self._backend._ffi.new("unsigned int *") res = self._backend._lib.HMAC_Final(self._ctx, buf, outlen) self._backend.openssl_assert(res != 0) self._backend.openssl_assert(outlen[0] == self.algorithm.digest_size) return self._backend._ffi.buffer(buf)[:outlen[0]] def verify(self, signature): digest = self.finalize() if not constant_time.bytes_eq(digest, signature): raise InvalidSignature("Signature did not match digest.") ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/cryptography/hazmat/backends/openssl/ocsp.py ================================================ # This file is dual licensed under the terms of the Apache License, Version # 2.0, and the BSD License. See the LICENSE file in the root of this repository # for complete details. from __future__ import absolute_import, division, print_function import functools from cryptography import utils, x509 from cryptography.exceptions import UnsupportedAlgorithm from cryptography.hazmat.backends.openssl.decode_asn1 import ( _CRL_ENTRY_REASON_CODE_TO_ENUM, _OCSP_BASICRESP_EXT_PARSER, _OCSP_REQ_EXT_PARSER, _asn1_integer_to_int, _asn1_string_to_bytes, _decode_x509_name, _obj2txt, _parse_asn1_generalized_time, ) from cryptography.hazmat.backends.openssl.x509 import _Certificate from cryptography.hazmat.primitives import serialization from cryptography.x509.ocsp import ( OCSPCertStatus, OCSPRequest, OCSPResponse, OCSPResponseStatus, _CERT_STATUS_TO_ENUM, _OIDS_TO_HASH, _RESPONSE_STATUS_TO_ENUM, ) def _requires_successful_response(func): @functools.wraps(func) def wrapper(self, *args): if self.response_status != OCSPResponseStatus.SUCCESSFUL: raise ValueError( "OCSP response status is not successful so the property " "has no value" ) else: return func(self, *args) return wrapper def _issuer_key_hash(backend, cert_id): key_hash = backend._ffi.new("ASN1_OCTET_STRING **") res = backend._lib.OCSP_id_get0_info( backend._ffi.NULL, backend._ffi.NULL, key_hash, backend._ffi.NULL, cert_id ) backend.openssl_assert(res == 1) backend.openssl_assert(key_hash[0] != backend._ffi.NULL) return _asn1_string_to_bytes(backend, key_hash[0]) def _issuer_name_hash(backend, cert_id): name_hash = backend._ffi.new("ASN1_OCTET_STRING **") res = backend._lib.OCSP_id_get0_info( name_hash, backend._ffi.NULL, backend._ffi.NULL, backend._ffi.NULL, cert_id ) backend.openssl_assert(res == 1) backend.openssl_assert(name_hash[0] != backend._ffi.NULL) return _asn1_string_to_bytes(backend, name_hash[0]) def _serial_number(backend, cert_id): num = backend._ffi.new("ASN1_INTEGER **") res = backend._lib.OCSP_id_get0_info( backend._ffi.NULL, backend._ffi.NULL, backend._ffi.NULL, num, cert_id ) backend.openssl_assert(res == 1) backend.openssl_assert(num[0] != backend._ffi.NULL) return _asn1_integer_to_int(backend, num[0]) def _hash_algorithm(backend, cert_id): asn1obj = backend._ffi.new("ASN1_OBJECT **") res = backend._lib.OCSP_id_get0_info( backend._ffi.NULL, asn1obj, backend._ffi.NULL, backend._ffi.NULL, cert_id ) backend.openssl_assert(res == 1) backend.openssl_assert(asn1obj[0] != backend._ffi.NULL) oid = _obj2txt(backend, asn1obj[0]) try: return _OIDS_TO_HASH[oid] except KeyError: raise UnsupportedAlgorithm( "Signature algorithm OID: {} not recognized".format(oid) ) @utils.register_interface(OCSPResponse) class _OCSPResponse(object): def __init__(self, backend, ocsp_response): self._backend = backend self._ocsp_response = ocsp_response status = self._backend._lib.OCSP_response_status(self._ocsp_response) self._backend.openssl_assert(status in _RESPONSE_STATUS_TO_ENUM) self._status = _RESPONSE_STATUS_TO_ENUM[status] if self._status is OCSPResponseStatus.SUCCESSFUL: basic = self._backend._lib.OCSP_response_get1_basic( self._ocsp_response ) self._backend.openssl_assert(basic != self._backend._ffi.NULL) self._basic = self._backend._ffi.gc( basic, self._backend._lib.OCSP_BASICRESP_free ) self._backend.openssl_assert( self._backend._lib.OCSP_resp_count(self._basic) == 1 ) self._single = self._backend._lib.OCSP_resp_get0(self._basic, 0) self._backend.openssl_assert( self._single != self._backend._ffi.NULL ) self._cert_id = self._backend._lib.OCSP_SINGLERESP_get0_id( self._single ) self._backend.openssl_assert( self._cert_id != self._backend._ffi.NULL ) response_status = utils.read_only_property("_status") @property @_requires_successful_response def signature_algorithm_oid(self): alg = self._backend._lib.OCSP_resp_get0_tbs_sigalg(self._basic) self._backend.openssl_assert(alg != self._backend._ffi.NULL) oid = _obj2txt(self._backend, alg.algorithm) return x509.ObjectIdentifier(oid) @property @_requires_successful_response def signature_hash_algorithm(self): oid = self.signature_algorithm_oid try: return x509._SIG_OIDS_TO_HASH[oid] except KeyError: raise UnsupportedAlgorithm( "Signature algorithm OID:{} not recognized".format(oid) ) @property @_requires_successful_response def signature(self): sig = self._backend._lib.OCSP_resp_get0_signature(self._basic) self._backend.openssl_assert(sig != self._backend._ffi.NULL) return _asn1_string_to_bytes(self._backend, sig) @property @_requires_successful_response def tbs_response_bytes(self): respdata = self._backend._lib.OCSP_resp_get0_respdata(self._basic) self._backend.openssl_assert(respdata != self._backend._ffi.NULL) pp = self._backend._ffi.new("unsigned char **") res = self._backend._lib.i2d_OCSP_RESPDATA(respdata, pp) self._backend.openssl_assert(pp[0] != self._backend._ffi.NULL) pp = self._backend._ffi.gc( pp, lambda pointer: self._backend._lib.OPENSSL_free(pointer[0]) ) self._backend.openssl_assert(res > 0) return self._backend._ffi.buffer(pp[0], res)[:] @property @_requires_successful_response def certificates(self): sk_x509 = self._backend._lib.OCSP_resp_get0_certs(self._basic) num = self._backend._lib.sk_X509_num(sk_x509) certs = [] for i in range(num): x509 = self._backend._lib.sk_X509_value(sk_x509, i) self._backend.openssl_assert(x509 != self._backend._ffi.NULL) cert = _Certificate(self._backend, x509) # We need to keep the OCSP response that the certificate came from # alive until the Certificate object itself goes out of scope, so # we give it a private reference. cert._ocsp_resp = self certs.append(cert) return certs @property @_requires_successful_response def responder_key_hash(self): _, asn1_string = self._responder_key_name() if asn1_string == self._backend._ffi.NULL: return None else: return _asn1_string_to_bytes(self._backend, asn1_string) @property @_requires_successful_response def responder_name(self): x509_name, _ = self._responder_key_name() if x509_name == self._backend._ffi.NULL: return None else: return _decode_x509_name(self._backend, x509_name) def _responder_key_name(self): asn1_string = self._backend._ffi.new("ASN1_OCTET_STRING **") x509_name = self._backend._ffi.new("X509_NAME **") res = self._backend._lib.OCSP_resp_get0_id( self._basic, asn1_string, x509_name ) self._backend.openssl_assert(res == 1) return x509_name[0], asn1_string[0] @property @_requires_successful_response def produced_at(self): produced_at = self._backend._lib.OCSP_resp_get0_produced_at( self._basic ) return _parse_asn1_generalized_time(self._backend, produced_at) @property @_requires_successful_response def certificate_status(self): status = self._backend._lib.OCSP_single_get0_status( self._single, self._backend._ffi.NULL, self._backend._ffi.NULL, self._backend._ffi.NULL, self._backend._ffi.NULL, ) self._backend.openssl_assert(status in _CERT_STATUS_TO_ENUM) return _CERT_STATUS_TO_ENUM[status] @property @_requires_successful_response def revocation_time(self): if self.certificate_status is not OCSPCertStatus.REVOKED: return None asn1_time = self._backend._ffi.new("ASN1_GENERALIZEDTIME **") self._backend._lib.OCSP_single_get0_status( self._single, self._backend._ffi.NULL, asn1_time, self._backend._ffi.NULL, self._backend._ffi.NULL, ) self._backend.openssl_assert(asn1_time[0] != self._backend._ffi.NULL) return _parse_asn1_generalized_time(self._backend, asn1_time[0]) @property @_requires_successful_response def revocation_reason(self): if self.certificate_status is not OCSPCertStatus.REVOKED: return None reason_ptr = self._backend._ffi.new("int *") self._backend._lib.OCSP_single_get0_status( self._single, reason_ptr, self._backend._ffi.NULL, self._backend._ffi.NULL, self._backend._ffi.NULL, ) # If no reason is encoded OpenSSL returns -1 if reason_ptr[0] == -1: return None else: self._backend.openssl_assert( reason_ptr[0] in _CRL_ENTRY_REASON_CODE_TO_ENUM ) return _CRL_ENTRY_REASON_CODE_TO_ENUM[reason_ptr[0]] @property @_requires_successful_response def this_update(self): asn1_time = self._backend._ffi.new("ASN1_GENERALIZEDTIME **") self._backend._lib.OCSP_single_get0_status( self._single, self._backend._ffi.NULL, self._backend._ffi.NULL, asn1_time, self._backend._ffi.NULL, ) self._backend.openssl_assert(asn1_time[0] != self._backend._ffi.NULL) return _parse_asn1_generalized_time(self._backend, asn1_time[0]) @property @_requires_successful_response def next_update(self): asn1_time = self._backend._ffi.new("ASN1_GENERALIZEDTIME **") self._backend._lib.OCSP_single_get0_status( self._single, self._backend._ffi.NULL, self._backend._ffi.NULL, self._backend._ffi.NULL, asn1_time, ) if asn1_time[0] != self._backend._ffi.NULL: return _parse_asn1_generalized_time(self._backend, asn1_time[0]) else: return None @property @_requires_successful_response def issuer_key_hash(self): return _issuer_key_hash(self._backend, self._cert_id) @property @_requires_successful_response def issuer_name_hash(self): return _issuer_name_hash(self._backend, self._cert_id) @property @_requires_successful_response def hash_algorithm(self): return _hash_algorithm(self._backend, self._cert_id) @property @_requires_successful_response def serial_number(self): return _serial_number(self._backend, self._cert_id) @utils.cached_property @_requires_successful_response def extensions(self): return _OCSP_BASICRESP_EXT_PARSER.parse(self._backend, self._basic) def public_bytes(self, encoding): if encoding is not serialization.Encoding.DER: raise ValueError( "The only allowed encoding value is Encoding.DER" ) bio = self._backend._create_mem_bio_gc() res = self._backend._lib.i2d_OCSP_RESPONSE_bio( bio, self._ocsp_response ) self._backend.openssl_assert(res > 0) return self._backend._read_mem_bio(bio) @utils.register_interface(OCSPRequest) class _OCSPRequest(object): def __init__(self, backend, ocsp_request): if backend._lib.OCSP_request_onereq_count(ocsp_request) > 1: raise NotImplementedError( 'OCSP request contains more than one request' ) self._backend = backend self._ocsp_request = ocsp_request self._request = self._backend._lib.OCSP_request_onereq_get0( self._ocsp_request, 0 ) self._backend.openssl_assert(self._request != self._backend._ffi.NULL) self._cert_id = self._backend._lib.OCSP_onereq_get0_id(self._request) self._backend.openssl_assert(self._cert_id != self._backend._ffi.NULL) @property def issuer_key_hash(self): return _issuer_key_hash(self._backend, self._cert_id) @property def issuer_name_hash(self): return _issuer_name_hash(self._backend, self._cert_id) @property def serial_number(self): return _serial_number(self._backend, self._cert_id) @property def hash_algorithm(self): return _hash_algorithm(self._backend, self._cert_id) @utils.cached_property def extensions(self): return _OCSP_REQ_EXT_PARSER.parse(self._backend, self._ocsp_request) def public_bytes(self, encoding): if encoding is not serialization.Encoding.DER: raise ValueError( "The only allowed encoding value is Encoding.DER" ) bio = self._backend._create_mem_bio_gc() res = self._backend._lib.i2d_OCSP_REQUEST_bio(bio, self._ocsp_request) self._backend.openssl_assert(res > 0) return self._backend._read_mem_bio(bio) ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/cryptography/hazmat/backends/openssl/poly1305.py ================================================ # This file is dual licensed under the terms of the Apache License, Version # 2.0, and the BSD License. See the LICENSE file in the root of this repository # for complete details. from __future__ import absolute_import, division, print_function from cryptography.exceptions import InvalidSignature from cryptography.hazmat.primitives import constant_time _POLY1305_TAG_SIZE = 16 _POLY1305_KEY_SIZE = 32 class _Poly1305Context(object): def __init__(self, backend, key): self._backend = backend key_ptr = self._backend._ffi.from_buffer(key) # This function copies the key into OpenSSL-owned memory so we don't # need to retain it ourselves evp_pkey = self._backend._lib.EVP_PKEY_new_raw_private_key( self._backend._lib.NID_poly1305, self._backend._ffi.NULL, key_ptr, len(key) ) self._backend.openssl_assert(evp_pkey != self._backend._ffi.NULL) self._evp_pkey = self._backend._ffi.gc( evp_pkey, self._backend._lib.EVP_PKEY_free ) ctx = self._backend._lib.Cryptography_EVP_MD_CTX_new() self._backend.openssl_assert(ctx != self._backend._ffi.NULL) self._ctx = self._backend._ffi.gc( ctx, self._backend._lib.Cryptography_EVP_MD_CTX_free ) res = self._backend._lib.EVP_DigestSignInit( self._ctx, self._backend._ffi.NULL, self._backend._ffi.NULL, self._backend._ffi.NULL, self._evp_pkey ) self._backend.openssl_assert(res == 1) def update(self, data): data_ptr = self._backend._ffi.from_buffer(data) res = self._backend._lib.EVP_DigestSignUpdate( self._ctx, data_ptr, len(data) ) self._backend.openssl_assert(res != 0) def finalize(self): buf = self._backend._ffi.new("unsigned char[]", _POLY1305_TAG_SIZE) outlen = self._backend._ffi.new("size_t *") res = self._backend._lib.EVP_DigestSignFinal(self._ctx, buf, outlen) self._backend.openssl_assert(res != 0) self._backend.openssl_assert(outlen[0] == _POLY1305_TAG_SIZE) return self._backend._ffi.buffer(buf)[:outlen[0]] def verify(self, tag): mac = self.finalize() if not constant_time.bytes_eq(mac, tag): raise InvalidSignature("Value did not match computed tag.") ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/cryptography/hazmat/backends/openssl/rsa.py ================================================ # This file is dual licensed under the terms of the Apache License, Version # 2.0, and the BSD License. See the LICENSE file in the root of this repository # for complete details. from __future__ import absolute_import, division, print_function import math from cryptography import utils from cryptography.exceptions import ( InvalidSignature, UnsupportedAlgorithm, _Reasons ) from cryptography.hazmat.backends.openssl.utils import ( _calculate_digest_and_algorithm, _check_not_prehashed, _warn_sign_verify_deprecated ) from cryptography.hazmat.primitives import hashes from cryptography.hazmat.primitives.asymmetric import ( AsymmetricSignatureContext, AsymmetricVerificationContext, rsa ) from cryptography.hazmat.primitives.asymmetric.padding import ( AsymmetricPadding, MGF1, OAEP, PKCS1v15, PSS, calculate_max_pss_salt_length ) from cryptography.hazmat.primitives.asymmetric.rsa import ( RSAPrivateKeyWithSerialization, RSAPublicKeyWithSerialization ) def _get_rsa_pss_salt_length(pss, key, hash_algorithm): salt = pss._salt_length if salt is MGF1.MAX_LENGTH or salt is PSS.MAX_LENGTH: return calculate_max_pss_salt_length(key, hash_algorithm) else: return salt def _enc_dec_rsa(backend, key, data, padding): if not isinstance(padding, AsymmetricPadding): raise TypeError("Padding must be an instance of AsymmetricPadding.") if isinstance(padding, PKCS1v15): padding_enum = backend._lib.RSA_PKCS1_PADDING elif isinstance(padding, OAEP): padding_enum = backend._lib.RSA_PKCS1_OAEP_PADDING if not isinstance(padding._mgf, MGF1): raise UnsupportedAlgorithm( "Only MGF1 is supported by this backend.", _Reasons.UNSUPPORTED_MGF ) if not backend.rsa_padding_supported(padding): raise UnsupportedAlgorithm( "This combination of padding and hash algorithm is not " "supported by this backend.", _Reasons.UNSUPPORTED_PADDING ) else: raise UnsupportedAlgorithm( "{} is not supported by this backend.".format( padding.name ), _Reasons.UNSUPPORTED_PADDING ) return _enc_dec_rsa_pkey_ctx(backend, key, data, padding_enum, padding) def _enc_dec_rsa_pkey_ctx(backend, key, data, padding_enum, padding): if isinstance(key, _RSAPublicKey): init = backend._lib.EVP_PKEY_encrypt_init crypt = backend._lib.EVP_PKEY_encrypt else: init = backend._lib.EVP_PKEY_decrypt_init crypt = backend._lib.EVP_PKEY_decrypt pkey_ctx = backend._lib.EVP_PKEY_CTX_new( key._evp_pkey, backend._ffi.NULL ) backend.openssl_assert(pkey_ctx != backend._ffi.NULL) pkey_ctx = backend._ffi.gc(pkey_ctx, backend._lib.EVP_PKEY_CTX_free) res = init(pkey_ctx) backend.openssl_assert(res == 1) res = backend._lib.EVP_PKEY_CTX_set_rsa_padding( pkey_ctx, padding_enum) backend.openssl_assert(res > 0) buf_size = backend._lib.EVP_PKEY_size(key._evp_pkey) backend.openssl_assert(buf_size > 0) if ( isinstance(padding, OAEP) and backend._lib.Cryptography_HAS_RSA_OAEP_MD ): mgf1_md = backend._evp_md_non_null_from_algorithm( padding._mgf._algorithm) res = backend._lib.EVP_PKEY_CTX_set_rsa_mgf1_md(pkey_ctx, mgf1_md) backend.openssl_assert(res > 0) oaep_md = backend._evp_md_non_null_from_algorithm(padding._algorithm) res = backend._lib.EVP_PKEY_CTX_set_rsa_oaep_md(pkey_ctx, oaep_md) backend.openssl_assert(res > 0) if ( isinstance(padding, OAEP) and padding._label is not None and len(padding._label) > 0 ): # set0_rsa_oaep_label takes ownership of the char * so we need to # copy it into some new memory labelptr = backend._lib.OPENSSL_malloc(len(padding._label)) backend.openssl_assert(labelptr != backend._ffi.NULL) backend._ffi.memmove(labelptr, padding._label, len(padding._label)) res = backend._lib.EVP_PKEY_CTX_set0_rsa_oaep_label( pkey_ctx, labelptr, len(padding._label) ) backend.openssl_assert(res == 1) outlen = backend._ffi.new("size_t *", buf_size) buf = backend._ffi.new("unsigned char[]", buf_size) res = crypt(pkey_ctx, buf, outlen, data, len(data)) if res <= 0: _handle_rsa_enc_dec_error(backend, key) return backend._ffi.buffer(buf)[:outlen[0]] def _handle_rsa_enc_dec_error(backend, key): errors = backend._consume_errors() backend.openssl_assert(errors) backend.openssl_assert(errors[0].lib == backend._lib.ERR_LIB_RSA) if isinstance(key, _RSAPublicKey): backend.openssl_assert( errors[0].reason == backend._lib.RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE ) raise ValueError( "Data too long for key size. Encrypt less data or use a " "larger key size." ) else: decoding_errors = [ backend._lib.RSA_R_BLOCK_TYPE_IS_NOT_01, backend._lib.RSA_R_BLOCK_TYPE_IS_NOT_02, backend._lib.RSA_R_OAEP_DECODING_ERROR, # Though this error looks similar to the # RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE, this occurs on decrypts, # rather than on encrypts backend._lib.RSA_R_DATA_TOO_LARGE_FOR_MODULUS, ] if backend._lib.Cryptography_HAS_RSA_R_PKCS_DECODING_ERROR: decoding_errors.append(backend._lib.RSA_R_PKCS_DECODING_ERROR) backend.openssl_assert(errors[0].reason in decoding_errors) raise ValueError("Decryption failed.") def _rsa_sig_determine_padding(backend, key, padding, algorithm): if not isinstance(padding, AsymmetricPadding): raise TypeError("Expected provider of AsymmetricPadding.") pkey_size = backend._lib.EVP_PKEY_size(key._evp_pkey) backend.openssl_assert(pkey_size > 0) if isinstance(padding, PKCS1v15): padding_enum = backend._lib.RSA_PKCS1_PADDING elif isinstance(padding, PSS): if not isinstance(padding._mgf, MGF1): raise UnsupportedAlgorithm( "Only MGF1 is supported by this backend.", _Reasons.UNSUPPORTED_MGF ) # Size of key in bytes - 2 is the maximum # PSS signature length (salt length is checked later) if pkey_size - algorithm.digest_size - 2 < 0: raise ValueError("Digest too large for key size. Use a larger " "key or different digest.") padding_enum = backend._lib.RSA_PKCS1_PSS_PADDING else: raise UnsupportedAlgorithm( "{} is not supported by this backend.".format(padding.name), _Reasons.UNSUPPORTED_PADDING ) return padding_enum def _rsa_sig_setup(backend, padding, algorithm, key, data, init_func): padding_enum = _rsa_sig_determine_padding(backend, key, padding, algorithm) evp_md = backend._evp_md_non_null_from_algorithm(algorithm) pkey_ctx = backend._lib.EVP_PKEY_CTX_new(key._evp_pkey, backend._ffi.NULL) backend.openssl_assert(pkey_ctx != backend._ffi.NULL) pkey_ctx = backend._ffi.gc(pkey_ctx, backend._lib.EVP_PKEY_CTX_free) res = init_func(pkey_ctx) backend.openssl_assert(res == 1) res = backend._lib.EVP_PKEY_CTX_set_signature_md(pkey_ctx, evp_md) if res == 0: backend._consume_errors() raise UnsupportedAlgorithm( "{} is not supported by this backend for RSA signing.".format( algorithm.name ), _Reasons.UNSUPPORTED_HASH ) res = backend._lib.EVP_PKEY_CTX_set_rsa_padding(pkey_ctx, padding_enum) backend.openssl_assert(res > 0) if isinstance(padding, PSS): res = backend._lib.EVP_PKEY_CTX_set_rsa_pss_saltlen( pkey_ctx, _get_rsa_pss_salt_length(padding, key, algorithm) ) backend.openssl_assert(res > 0) mgf1_md = backend._evp_md_non_null_from_algorithm( padding._mgf._algorithm) res = backend._lib.EVP_PKEY_CTX_set_rsa_mgf1_md(pkey_ctx, mgf1_md) backend.openssl_assert(res > 0) return pkey_ctx def _rsa_sig_sign(backend, padding, algorithm, private_key, data): pkey_ctx = _rsa_sig_setup( backend, padding, algorithm, private_key, data, backend._lib.EVP_PKEY_sign_init ) buflen = backend._ffi.new("size_t *") res = backend._lib.EVP_PKEY_sign( pkey_ctx, backend._ffi.NULL, buflen, data, len(data) ) backend.openssl_assert(res == 1) buf = backend._ffi.new("unsigned char[]", buflen[0]) res = backend._lib.EVP_PKEY_sign( pkey_ctx, buf, buflen, data, len(data)) if res != 1: errors = backend._consume_errors() backend.openssl_assert(errors[0].lib == backend._lib.ERR_LIB_RSA) if ( errors[0].reason == backend._lib.RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE ): reason = ("Salt length too long for key size. Try using " "MAX_LENGTH instead.") else: backend.openssl_assert( errors[0].reason == backend._lib.RSA_R_DIGEST_TOO_BIG_FOR_RSA_KEY ) reason = "Digest too large for key size. Use a larger key." raise ValueError(reason) return backend._ffi.buffer(buf)[:] def _rsa_sig_verify(backend, padding, algorithm, public_key, signature, data): pkey_ctx = _rsa_sig_setup( backend, padding, algorithm, public_key, data, backend._lib.EVP_PKEY_verify_init ) res = backend._lib.EVP_PKEY_verify( pkey_ctx, signature, len(signature), data, len(data) ) # The previous call can return negative numbers in the event of an # error. This is not a signature failure but we need to fail if it # occurs. backend.openssl_assert(res >= 0) if res == 0: backend._consume_errors() raise InvalidSignature @utils.register_interface(AsymmetricSignatureContext) class _RSASignatureContext(object): def __init__(self, backend, private_key, padding, algorithm): self._backend = backend self._private_key = private_key # We now call _rsa_sig_determine_padding in _rsa_sig_setup. However # we need to make a pointless call to it here so we maintain the # API of erroring on init with this context if the values are invalid. _rsa_sig_determine_padding(backend, private_key, padding, algorithm) self._padding = padding self._algorithm = algorithm self._hash_ctx = hashes.Hash(self._algorithm, self._backend) def update(self, data): self._hash_ctx.update(data) def finalize(self): return _rsa_sig_sign( self._backend, self._padding, self._algorithm, self._private_key, self._hash_ctx.finalize() ) @utils.register_interface(AsymmetricVerificationContext) class _RSAVerificationContext(object): def __init__(self, backend, public_key, signature, padding, algorithm): self._backend = backend self._public_key = public_key self._signature = signature self._padding = padding # We now call _rsa_sig_determine_padding in _rsa_sig_setup. However # we need to make a pointless call to it here so we maintain the # API of erroring on init with this context if the values are invalid. _rsa_sig_determine_padding(backend, public_key, padding, algorithm) padding = padding self._algorithm = algorithm self._hash_ctx = hashes.Hash(self._algorithm, self._backend) def update(self, data): self._hash_ctx.update(data) def verify(self): return _rsa_sig_verify( self._backend, self._padding, self._algorithm, self._public_key, self._signature, self._hash_ctx.finalize() ) @utils.register_interface(RSAPrivateKeyWithSerialization) class _RSAPrivateKey(object): def __init__(self, backend, rsa_cdata, evp_pkey): self._backend = backend self._rsa_cdata = rsa_cdata self._evp_pkey = evp_pkey n = self._backend._ffi.new("BIGNUM **") self._backend._lib.RSA_get0_key( self._rsa_cdata, n, self._backend._ffi.NULL, self._backend._ffi.NULL ) self._backend.openssl_assert(n[0] != self._backend._ffi.NULL) self._key_size = self._backend._lib.BN_num_bits(n[0]) key_size = utils.read_only_property("_key_size") def signer(self, padding, algorithm): _warn_sign_verify_deprecated() _check_not_prehashed(algorithm) return _RSASignatureContext(self._backend, self, padding, algorithm) def decrypt(self, ciphertext, padding): key_size_bytes = int(math.ceil(self.key_size / 8.0)) if key_size_bytes != len(ciphertext): raise ValueError("Ciphertext length must be equal to key size.") return _enc_dec_rsa(self._backend, self, ciphertext, padding) def public_key(self): ctx = self._backend._lib.RSAPublicKey_dup(self._rsa_cdata) self._backend.openssl_assert(ctx != self._backend._ffi.NULL) ctx = self._backend._ffi.gc(ctx, self._backend._lib.RSA_free) res = self._backend._lib.RSA_blinding_on(ctx, self._backend._ffi.NULL) self._backend.openssl_assert(res == 1) evp_pkey = self._backend._rsa_cdata_to_evp_pkey(ctx) return _RSAPublicKey(self._backend, ctx, evp_pkey) def private_numbers(self): n = self._backend._ffi.new("BIGNUM **") e = self._backend._ffi.new("BIGNUM **") d = self._backend._ffi.new("BIGNUM **") p = self._backend._ffi.new("BIGNUM **") q = self._backend._ffi.new("BIGNUM **") dmp1 = self._backend._ffi.new("BIGNUM **") dmq1 = self._backend._ffi.new("BIGNUM **") iqmp = self._backend._ffi.new("BIGNUM **") self._backend._lib.RSA_get0_key(self._rsa_cdata, n, e, d) self._backend.openssl_assert(n[0] != self._backend._ffi.NULL) self._backend.openssl_assert(e[0] != self._backend._ffi.NULL) self._backend.openssl_assert(d[0] != self._backend._ffi.NULL) self._backend._lib.RSA_get0_factors(self._rsa_cdata, p, q) self._backend.openssl_assert(p[0] != self._backend._ffi.NULL) self._backend.openssl_assert(q[0] != self._backend._ffi.NULL) self._backend._lib.RSA_get0_crt_params( self._rsa_cdata, dmp1, dmq1, iqmp ) self._backend.openssl_assert(dmp1[0] != self._backend._ffi.NULL) self._backend.openssl_assert(dmq1[0] != self._backend._ffi.NULL) self._backend.openssl_assert(iqmp[0] != self._backend._ffi.NULL) return rsa.RSAPrivateNumbers( p=self._backend._bn_to_int(p[0]), q=self._backend._bn_to_int(q[0]), d=self._backend._bn_to_int(d[0]), dmp1=self._backend._bn_to_int(dmp1[0]), dmq1=self._backend._bn_to_int(dmq1[0]), iqmp=self._backend._bn_to_int(iqmp[0]), public_numbers=rsa.RSAPublicNumbers( e=self._backend._bn_to_int(e[0]), n=self._backend._bn_to_int(n[0]), ) ) def private_bytes(self, encoding, format, encryption_algorithm): return self._backend._private_key_bytes( encoding, format, encryption_algorithm, self._evp_pkey, self._rsa_cdata ) def sign(self, data, padding, algorithm): data, algorithm = _calculate_digest_and_algorithm( self._backend, data, algorithm ) return _rsa_sig_sign(self._backend, padding, algorithm, self, data) @utils.register_interface(RSAPublicKeyWithSerialization) class _RSAPublicKey(object): def __init__(self, backend, rsa_cdata, evp_pkey): self._backend = backend self._rsa_cdata = rsa_cdata self._evp_pkey = evp_pkey n = self._backend._ffi.new("BIGNUM **") self._backend._lib.RSA_get0_key( self._rsa_cdata, n, self._backend._ffi.NULL, self._backend._ffi.NULL ) self._backend.openssl_assert(n[0] != self._backend._ffi.NULL) self._key_size = self._backend._lib.BN_num_bits(n[0]) key_size = utils.read_only_property("_key_size") def verifier(self, signature, padding, algorithm): _warn_sign_verify_deprecated() utils._check_bytes("signature", signature) _check_not_prehashed(algorithm) return _RSAVerificationContext( self._backend, self, signature, padding, algorithm ) def encrypt(self, plaintext, padding): return _enc_dec_rsa(self._backend, self, plaintext, padding) def public_numbers(self): n = self._backend._ffi.new("BIGNUM **") e = self._backend._ffi.new("BIGNUM **") self._backend._lib.RSA_get0_key( self._rsa_cdata, n, e, self._backend._ffi.NULL ) self._backend.openssl_assert(n[0] != self._backend._ffi.NULL) self._backend.openssl_assert(e[0] != self._backend._ffi.NULL) return rsa.RSAPublicNumbers( e=self._backend._bn_to_int(e[0]), n=self._backend._bn_to_int(n[0]), ) def public_bytes(self, encoding, format): return self._backend._public_key_bytes( encoding, format, self, self._evp_pkey, self._rsa_cdata ) def verify(self, signature, data, padding, algorithm): data, algorithm = _calculate_digest_and_algorithm( self._backend, data, algorithm ) return _rsa_sig_verify( self._backend, padding, algorithm, self, signature, data ) ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/cryptography/hazmat/backends/openssl/utils.py ================================================ # This file is dual licensed under the terms of the Apache License, Version # 2.0, and the BSD License. See the LICENSE file in the root of this repository # for complete details. from __future__ import absolute_import, division, print_function import warnings from cryptography import utils from cryptography.hazmat.primitives import hashes from cryptography.hazmat.primitives.asymmetric.utils import Prehashed def _evp_pkey_derive(backend, evp_pkey, peer_public_key): ctx = backend._lib.EVP_PKEY_CTX_new(evp_pkey, backend._ffi.NULL) backend.openssl_assert(ctx != backend._ffi.NULL) ctx = backend._ffi.gc(ctx, backend._lib.EVP_PKEY_CTX_free) res = backend._lib.EVP_PKEY_derive_init(ctx) backend.openssl_assert(res == 1) res = backend._lib.EVP_PKEY_derive_set_peer( ctx, peer_public_key._evp_pkey ) backend.openssl_assert(res == 1) keylen = backend._ffi.new("size_t *") res = backend._lib.EVP_PKEY_derive(ctx, backend._ffi.NULL, keylen) backend.openssl_assert(res == 1) backend.openssl_assert(keylen[0] > 0) buf = backend._ffi.new("unsigned char[]", keylen[0]) res = backend._lib.EVP_PKEY_derive(ctx, buf, keylen) if res != 1: raise ValueError( "Null shared key derived from public/private pair." ) return backend._ffi.buffer(buf, keylen[0])[:] def _calculate_digest_and_algorithm(backend, data, algorithm): if not isinstance(algorithm, Prehashed): hash_ctx = hashes.Hash(algorithm, backend) hash_ctx.update(data) data = hash_ctx.finalize() else: algorithm = algorithm._algorithm if len(data) != algorithm.digest_size: raise ValueError( "The provided data must be the same length as the hash " "algorithm's digest size." ) return (data, algorithm) def _check_not_prehashed(signature_algorithm): if isinstance(signature_algorithm, Prehashed): raise TypeError( "Prehashed is only supported in the sign and verify methods. " "It cannot be used with signer or verifier." ) def _warn_sign_verify_deprecated(): warnings.warn( "signer and verifier have been deprecated. Please use sign " "and verify instead.", utils.PersistentlyDeprecated2017, stacklevel=3 ) ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/cryptography/hazmat/backends/openssl/x25519.py ================================================ # This file is dual licensed under the terms of the Apache License, Version # 2.0, and the BSD License. See the LICENSE file in the root of this repository # for complete details. from __future__ import absolute_import, division, print_function import warnings from cryptography import utils from cryptography.hazmat.backends.openssl.utils import _evp_pkey_derive from cryptography.hazmat.primitives import serialization from cryptography.hazmat.primitives.asymmetric.x25519 import ( X25519PrivateKey, X25519PublicKey ) _X25519_KEY_SIZE = 32 @utils.register_interface(X25519PublicKey) class _X25519PublicKey(object): def __init__(self, backend, evp_pkey): self._backend = backend self._evp_pkey = evp_pkey def public_bytes(self, encoding=None, format=None): if encoding is None or format is None: if encoding is not None or format is not None: raise ValueError("Both encoding and format are required") else: warnings.warn( "public_bytes now requires encoding and format arguments. " "Support for calling without arguments will be removed in " "cryptography 2.7", utils.DeprecatedIn25, ) encoding = serialization.Encoding.Raw format = serialization.PublicFormat.Raw if ( encoding is serialization.Encoding.Raw or format is serialization.PublicFormat.Raw ): if ( encoding is not serialization.Encoding.Raw or format is not serialization.PublicFormat.Raw ): raise ValueError( "When using Raw both encoding and format must be Raw" ) return self._raw_public_bytes() if ( encoding in serialization._PEM_DER and format is not serialization.PublicFormat.SubjectPublicKeyInfo ): raise ValueError( "format must be SubjectPublicKeyInfo when encoding is PEM or " "DER" ) return self._backend._public_key_bytes( encoding, format, self, self._evp_pkey, None ) def _raw_public_bytes(self): ucharpp = self._backend._ffi.new("unsigned char **") res = self._backend._lib.EVP_PKEY_get1_tls_encodedpoint( self._evp_pkey, ucharpp ) self._backend.openssl_assert(res == 32) self._backend.openssl_assert(ucharpp[0] != self._backend._ffi.NULL) data = self._backend._ffi.gc( ucharpp[0], self._backend._lib.OPENSSL_free ) return self._backend._ffi.buffer(data, res)[:] @utils.register_interface(X25519PrivateKey) class _X25519PrivateKey(object): def __init__(self, backend, evp_pkey): self._backend = backend self._evp_pkey = evp_pkey def public_key(self): bio = self._backend._create_mem_bio_gc() res = self._backend._lib.i2d_PUBKEY_bio(bio, self._evp_pkey) self._backend.openssl_assert(res == 1) evp_pkey = self._backend._lib.d2i_PUBKEY_bio( bio, self._backend._ffi.NULL ) self._backend.openssl_assert(evp_pkey != self._backend._ffi.NULL) evp_pkey = self._backend._ffi.gc( evp_pkey, self._backend._lib.EVP_PKEY_free ) return _X25519PublicKey(self._backend, evp_pkey) def exchange(self, peer_public_key): if not isinstance(peer_public_key, X25519PublicKey): raise TypeError("peer_public_key must be X25519PublicKey.") return _evp_pkey_derive( self._backend, self._evp_pkey, peer_public_key ) def private_bytes(self, encoding, format, encryption_algorithm): if ( encoding is serialization.Encoding.Raw or format is serialization.PublicFormat.Raw ): if ( format is not serialization.PrivateFormat.Raw or encoding is not serialization.Encoding.Raw or not isinstance(encryption_algorithm, serialization.NoEncryption) ): raise ValueError( "When using Raw both encoding and format must be Raw " "and encryption_algorithm must be NoEncryption()" ) return self._raw_private_bytes() if ( encoding in serialization._PEM_DER and format is not serialization.PrivateFormat.PKCS8 ): raise ValueError( "format must be PKCS8 when encoding is PEM or DER" ) return self._backend._private_key_bytes( encoding, format, encryption_algorithm, self._evp_pkey, None ) def _raw_private_bytes(self): # When we drop support for CRYPTOGRAPHY_OPENSSL_LESS_THAN_111 we can # switch this to EVP_PKEY_new_raw_private_key # The trick we use here is serializing to a PKCS8 key and just # using the last 32 bytes, which is the key itself. bio = self._backend._create_mem_bio_gc() res = self._backend._lib.i2d_PKCS8PrivateKey_bio( bio, self._evp_pkey, self._backend._ffi.NULL, self._backend._ffi.NULL, 0, self._backend._ffi.NULL, self._backend._ffi.NULL ) self._backend.openssl_assert(res == 1) pkcs8 = self._backend._read_mem_bio(bio) self._backend.openssl_assert(len(pkcs8) == 48) return pkcs8[-_X25519_KEY_SIZE:] ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/cryptography/hazmat/backends/openssl/x448.py ================================================ # This file is dual licensed under the terms of the Apache License, Version # 2.0, and the BSD License. See the LICENSE file in the root of this repository # for complete details. from __future__ import absolute_import, division, print_function from cryptography import utils from cryptography.hazmat.backends.openssl.utils import _evp_pkey_derive from cryptography.hazmat.primitives import serialization from cryptography.hazmat.primitives.asymmetric.x448 import ( X448PrivateKey, X448PublicKey ) _X448_KEY_SIZE = 56 @utils.register_interface(X448PublicKey) class _X448PublicKey(object): def __init__(self, backend, evp_pkey): self._backend = backend self._evp_pkey = evp_pkey def public_bytes(self, encoding, format): if ( encoding is serialization.Encoding.Raw or format is serialization.PublicFormat.Raw ): if ( encoding is not serialization.Encoding.Raw or format is not serialization.PublicFormat.Raw ): raise ValueError( "When using Raw both encoding and format must be Raw" ) return self._raw_public_bytes() if ( encoding in serialization._PEM_DER and format is not serialization.PublicFormat.SubjectPublicKeyInfo ): raise ValueError( "format must be SubjectPublicKeyInfo when encoding is PEM or " "DER" ) return self._backend._public_key_bytes( encoding, format, self, self._evp_pkey, None ) def _raw_public_bytes(self): buf = self._backend._ffi.new("unsigned char []", _X448_KEY_SIZE) buflen = self._backend._ffi.new("size_t *", _X448_KEY_SIZE) res = self._backend._lib.EVP_PKEY_get_raw_public_key( self._evp_pkey, buf, buflen ) self._backend.openssl_assert(res == 1) self._backend.openssl_assert(buflen[0] == _X448_KEY_SIZE) return self._backend._ffi.buffer(buf, _X448_KEY_SIZE)[:] @utils.register_interface(X448PrivateKey) class _X448PrivateKey(object): def __init__(self, backend, evp_pkey): self._backend = backend self._evp_pkey = evp_pkey def public_key(self): buf = self._backend._ffi.new("unsigned char []", _X448_KEY_SIZE) buflen = self._backend._ffi.new("size_t *", _X448_KEY_SIZE) res = self._backend._lib.EVP_PKEY_get_raw_public_key( self._evp_pkey, buf, buflen ) self._backend.openssl_assert(res == 1) self._backend.openssl_assert(buflen[0] == _X448_KEY_SIZE) return self._backend.x448_load_public_bytes(buf) def exchange(self, peer_public_key): if not isinstance(peer_public_key, X448PublicKey): raise TypeError("peer_public_key must be X448PublicKey.") return _evp_pkey_derive( self._backend, self._evp_pkey, peer_public_key ) def private_bytes(self, encoding, format, encryption_algorithm): if ( encoding is serialization.Encoding.Raw or format is serialization.PublicFormat.Raw ): if ( format is not serialization.PrivateFormat.Raw or encoding is not serialization.Encoding.Raw or not isinstance(encryption_algorithm, serialization.NoEncryption) ): raise ValueError( "When using Raw both encoding and format must be Raw " "and encryption_algorithm must be NoEncryption()" ) return self._raw_private_bytes() if ( encoding in serialization._PEM_DER and format is not serialization.PrivateFormat.PKCS8 ): raise ValueError( "format must be PKCS8 when encoding is PEM or DER" ) return self._backend._private_key_bytes( encoding, format, encryption_algorithm, self._evp_pkey, None ) def _raw_private_bytes(self): buf = self._backend._ffi.new("unsigned char []", _X448_KEY_SIZE) buflen = self._backend._ffi.new("size_t *", _X448_KEY_SIZE) res = self._backend._lib.EVP_PKEY_get_raw_private_key( self._evp_pkey, buf, buflen ) self._backend.openssl_assert(res == 1) self._backend.openssl_assert(buflen[0] == _X448_KEY_SIZE) return self._backend._ffi.buffer(buf, _X448_KEY_SIZE)[:] ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/cryptography/hazmat/backends/openssl/x509.py ================================================ # This file is dual licensed under the terms of the Apache License, Version # 2.0, and the BSD License. See the LICENSE file in the root of this repository # for complete details. from __future__ import absolute_import, division, print_function import datetime import operator from cryptography import utils, x509 from cryptography.exceptions import UnsupportedAlgorithm from cryptography.hazmat.backends.openssl.decode_asn1 import ( _CERTIFICATE_EXTENSION_PARSER, _CERTIFICATE_EXTENSION_PARSER_NO_SCT, _CRL_EXTENSION_PARSER, _CSR_EXTENSION_PARSER, _REVOKED_CERTIFICATE_EXTENSION_PARSER, _asn1_integer_to_int, _asn1_string_to_bytes, _decode_x509_name, _obj2txt, _parse_asn1_time ) from cryptography.hazmat.backends.openssl.encode_asn1 import ( _encode_asn1_int_gc ) from cryptography.hazmat.primitives import hashes, serialization from cryptography.hazmat.primitives.asymmetric import dsa, ec, rsa @utils.register_interface(x509.Certificate) class _Certificate(object): def __init__(self, backend, x509): self._backend = backend self._x509 = x509 def __repr__(self): return "".format(self.subject) def __eq__(self, other): if not isinstance(other, x509.Certificate): return NotImplemented res = self._backend._lib.X509_cmp(self._x509, other._x509) return res == 0 def __ne__(self, other): return not self == other def __hash__(self): return hash(self.public_bytes(serialization.Encoding.DER)) def fingerprint(self, algorithm): h = hashes.Hash(algorithm, self._backend) h.update(self.public_bytes(serialization.Encoding.DER)) return h.finalize() @property def version(self): version = self._backend._lib.X509_get_version(self._x509) if version == 0: return x509.Version.v1 elif version == 2: return x509.Version.v3 else: raise x509.InvalidVersion( "{} is not a valid X509 version".format(version), version ) @property def serial_number(self): asn1_int = self._backend._lib.X509_get_serialNumber(self._x509) self._backend.openssl_assert(asn1_int != self._backend._ffi.NULL) return _asn1_integer_to_int(self._backend, asn1_int) def public_key(self): pkey = self._backend._lib.X509_get_pubkey(self._x509) if pkey == self._backend._ffi.NULL: # Remove errors from the stack. self._backend._consume_errors() raise ValueError("Certificate public key is of an unknown type") pkey = self._backend._ffi.gc(pkey, self._backend._lib.EVP_PKEY_free) return self._backend._evp_pkey_to_public_key(pkey) @property def not_valid_before(self): asn1_time = self._backend._lib.X509_getm_notBefore(self._x509) return _parse_asn1_time(self._backend, asn1_time) @property def not_valid_after(self): asn1_time = self._backend._lib.X509_getm_notAfter(self._x509) return _parse_asn1_time(self._backend, asn1_time) @property def issuer(self): issuer = self._backend._lib.X509_get_issuer_name(self._x509) self._backend.openssl_assert(issuer != self._backend._ffi.NULL) return _decode_x509_name(self._backend, issuer) @property def subject(self): subject = self._backend._lib.X509_get_subject_name(self._x509) self._backend.openssl_assert(subject != self._backend._ffi.NULL) return _decode_x509_name(self._backend, subject) @property def signature_hash_algorithm(self): oid = self.signature_algorithm_oid try: return x509._SIG_OIDS_TO_HASH[oid] except KeyError: raise UnsupportedAlgorithm( "Signature algorithm OID:{} not recognized".format(oid) ) @property def signature_algorithm_oid(self): alg = self._backend._ffi.new("X509_ALGOR **") self._backend._lib.X509_get0_signature( self._backend._ffi.NULL, alg, self._x509 ) self._backend.openssl_assert(alg[0] != self._backend._ffi.NULL) oid = _obj2txt(self._backend, alg[0].algorithm) return x509.ObjectIdentifier(oid) @utils.cached_property def extensions(self): if self._backend._lib.CRYPTOGRAPHY_OPENSSL_110_OR_GREATER: return _CERTIFICATE_EXTENSION_PARSER.parse( self._backend, self._x509 ) else: return _CERTIFICATE_EXTENSION_PARSER_NO_SCT.parse( self._backend, self._x509 ) @property def signature(self): sig = self._backend._ffi.new("ASN1_BIT_STRING **") self._backend._lib.X509_get0_signature( sig, self._backend._ffi.NULL, self._x509 ) self._backend.openssl_assert(sig[0] != self._backend._ffi.NULL) return _asn1_string_to_bytes(self._backend, sig[0]) @property def tbs_certificate_bytes(self): pp = self._backend._ffi.new("unsigned char **") res = self._backend._lib.i2d_re_X509_tbs(self._x509, pp) self._backend.openssl_assert(res > 0) pp = self._backend._ffi.gc( pp, lambda pointer: self._backend._lib.OPENSSL_free(pointer[0]) ) return self._backend._ffi.buffer(pp[0], res)[:] def public_bytes(self, encoding): bio = self._backend._create_mem_bio_gc() if encoding is serialization.Encoding.PEM: res = self._backend._lib.PEM_write_bio_X509(bio, self._x509) elif encoding is serialization.Encoding.DER: res = self._backend._lib.i2d_X509_bio(bio, self._x509) else: raise TypeError("encoding must be an item from the Encoding enum") self._backend.openssl_assert(res == 1) return self._backend._read_mem_bio(bio) @utils.register_interface(x509.RevokedCertificate) class _RevokedCertificate(object): def __init__(self, backend, crl, x509_revoked): self._backend = backend # The X509_REVOKED_value is a X509_REVOKED * that has # no reference counting. This means when X509_CRL_free is # called then the CRL and all X509_REVOKED * are freed. Since # you can retain a reference to a single revoked certificate # and let the CRL fall out of scope we need to retain a # private reference to the CRL inside the RevokedCertificate # object to prevent the gc from being called inappropriately. self._crl = crl self._x509_revoked = x509_revoked @property def serial_number(self): asn1_int = self._backend._lib.X509_REVOKED_get0_serialNumber( self._x509_revoked ) self._backend.openssl_assert(asn1_int != self._backend._ffi.NULL) return _asn1_integer_to_int(self._backend, asn1_int) @property def revocation_date(self): return _parse_asn1_time( self._backend, self._backend._lib.X509_REVOKED_get0_revocationDate( self._x509_revoked ) ) @utils.cached_property def extensions(self): return _REVOKED_CERTIFICATE_EXTENSION_PARSER.parse( self._backend, self._x509_revoked ) @utils.register_interface(x509.CertificateRevocationList) class _CertificateRevocationList(object): def __init__(self, backend, x509_crl): self._backend = backend self._x509_crl = x509_crl def __eq__(self, other): if not isinstance(other, x509.CertificateRevocationList): return NotImplemented res = self._backend._lib.X509_CRL_cmp(self._x509_crl, other._x509_crl) return res == 0 def __ne__(self, other): return not self == other def fingerprint(self, algorithm): h = hashes.Hash(algorithm, self._backend) bio = self._backend._create_mem_bio_gc() res = self._backend._lib.i2d_X509_CRL_bio( bio, self._x509_crl ) self._backend.openssl_assert(res == 1) der = self._backend._read_mem_bio(bio) h.update(der) return h.finalize() @utils.cached_property def _sorted_crl(self): # X509_CRL_get0_by_serial sorts in place, which breaks a variety of # things we don't want to break (like iteration and the signature). # Let's dupe it and sort that instead. dup = self._backend._lib.X509_CRL_dup(self._x509_crl) self._backend.openssl_assert(dup != self._backend._ffi.NULL) dup = self._backend._ffi.gc(dup, self._backend._lib.X509_CRL_free) return dup def get_revoked_certificate_by_serial_number(self, serial_number): revoked = self._backend._ffi.new("X509_REVOKED **") asn1_int = _encode_asn1_int_gc(self._backend, serial_number) res = self._backend._lib.X509_CRL_get0_by_serial( self._sorted_crl, revoked, asn1_int ) if res == 0: return None else: self._backend.openssl_assert( revoked[0] != self._backend._ffi.NULL ) return _RevokedCertificate( self._backend, self._sorted_crl, revoked[0] ) @property def signature_hash_algorithm(self): oid = self.signature_algorithm_oid try: return x509._SIG_OIDS_TO_HASH[oid] except KeyError: raise UnsupportedAlgorithm( "Signature algorithm OID:{} not recognized".format(oid) ) @property def signature_algorithm_oid(self): alg = self._backend._ffi.new("X509_ALGOR **") self._backend._lib.X509_CRL_get0_signature( self._x509_crl, self._backend._ffi.NULL, alg ) self._backend.openssl_assert(alg[0] != self._backend._ffi.NULL) oid = _obj2txt(self._backend, alg[0].algorithm) return x509.ObjectIdentifier(oid) @property def issuer(self): issuer = self._backend._lib.X509_CRL_get_issuer(self._x509_crl) self._backend.openssl_assert(issuer != self._backend._ffi.NULL) return _decode_x509_name(self._backend, issuer) @property def next_update(self): nu = self._backend._lib.X509_CRL_get_nextUpdate(self._x509_crl) self._backend.openssl_assert(nu != self._backend._ffi.NULL) return _parse_asn1_time(self._backend, nu) @property def last_update(self): lu = self._backend._lib.X509_CRL_get_lastUpdate(self._x509_crl) self._backend.openssl_assert(lu != self._backend._ffi.NULL) return _parse_asn1_time(self._backend, lu) @property def signature(self): sig = self._backend._ffi.new("ASN1_BIT_STRING **") self._backend._lib.X509_CRL_get0_signature( self._x509_crl, sig, self._backend._ffi.NULL ) self._backend.openssl_assert(sig[0] != self._backend._ffi.NULL) return _asn1_string_to_bytes(self._backend, sig[0]) @property def tbs_certlist_bytes(self): pp = self._backend._ffi.new("unsigned char **") res = self._backend._lib.i2d_re_X509_CRL_tbs(self._x509_crl, pp) self._backend.openssl_assert(res > 0) pp = self._backend._ffi.gc( pp, lambda pointer: self._backend._lib.OPENSSL_free(pointer[0]) ) return self._backend._ffi.buffer(pp[0], res)[:] def public_bytes(self, encoding): bio = self._backend._create_mem_bio_gc() if encoding is serialization.Encoding.PEM: res = self._backend._lib.PEM_write_bio_X509_CRL( bio, self._x509_crl ) elif encoding is serialization.Encoding.DER: res = self._backend._lib.i2d_X509_CRL_bio(bio, self._x509_crl) else: raise TypeError("encoding must be an item from the Encoding enum") self._backend.openssl_assert(res == 1) return self._backend._read_mem_bio(bio) def _revoked_cert(self, idx): revoked = self._backend._lib.X509_CRL_get_REVOKED(self._x509_crl) r = self._backend._lib.sk_X509_REVOKED_value(revoked, idx) self._backend.openssl_assert(r != self._backend._ffi.NULL) return _RevokedCertificate(self._backend, self, r) def __iter__(self): for i in range(len(self)): yield self._revoked_cert(i) def __getitem__(self, idx): if isinstance(idx, slice): start, stop, step = idx.indices(len(self)) return [self._revoked_cert(i) for i in range(start, stop, step)] else: idx = operator.index(idx) if idx < 0: idx += len(self) if not 0 <= idx < len(self): raise IndexError return self._revoked_cert(idx) def __len__(self): revoked = self._backend._lib.X509_CRL_get_REVOKED(self._x509_crl) if revoked == self._backend._ffi.NULL: return 0 else: return self._backend._lib.sk_X509_REVOKED_num(revoked) @utils.cached_property def extensions(self): return _CRL_EXTENSION_PARSER.parse(self._backend, self._x509_crl) def is_signature_valid(self, public_key): if not isinstance(public_key, (dsa.DSAPublicKey, rsa.RSAPublicKey, ec.EllipticCurvePublicKey)): raise TypeError('Expecting one of DSAPublicKey, RSAPublicKey,' ' or EllipticCurvePublicKey.') res = self._backend._lib.X509_CRL_verify( self._x509_crl, public_key._evp_pkey ) if res != 1: self._backend._consume_errors() return False return True @utils.register_interface(x509.CertificateSigningRequest) class _CertificateSigningRequest(object): def __init__(self, backend, x509_req): self._backend = backend self._x509_req = x509_req def __eq__(self, other): if not isinstance(other, _CertificateSigningRequest): return NotImplemented self_bytes = self.public_bytes(serialization.Encoding.DER) other_bytes = other.public_bytes(serialization.Encoding.DER) return self_bytes == other_bytes def __ne__(self, other): return not self == other def __hash__(self): return hash(self.public_bytes(serialization.Encoding.DER)) def public_key(self): pkey = self._backend._lib.X509_REQ_get_pubkey(self._x509_req) self._backend.openssl_assert(pkey != self._backend._ffi.NULL) pkey = self._backend._ffi.gc(pkey, self._backend._lib.EVP_PKEY_free) return self._backend._evp_pkey_to_public_key(pkey) @property def subject(self): subject = self._backend._lib.X509_REQ_get_subject_name(self._x509_req) self._backend.openssl_assert(subject != self._backend._ffi.NULL) return _decode_x509_name(self._backend, subject) @property def signature_hash_algorithm(self): oid = self.signature_algorithm_oid try: return x509._SIG_OIDS_TO_HASH[oid] except KeyError: raise UnsupportedAlgorithm( "Signature algorithm OID:{} not recognized".format(oid) ) @property def signature_algorithm_oid(self): alg = self._backend._ffi.new("X509_ALGOR **") self._backend._lib.X509_REQ_get0_signature( self._x509_req, self._backend._ffi.NULL, alg ) self._backend.openssl_assert(alg[0] != self._backend._ffi.NULL) oid = _obj2txt(self._backend, alg[0].algorithm) return x509.ObjectIdentifier(oid) @utils.cached_property def extensions(self): x509_exts = self._backend._lib.X509_REQ_get_extensions(self._x509_req) x509_exts = self._backend._ffi.gc( x509_exts, lambda x: self._backend._lib.sk_X509_EXTENSION_pop_free( x, self._backend._ffi.addressof( self._backend._lib._original_lib, "X509_EXTENSION_free" ) ) ) return _CSR_EXTENSION_PARSER.parse(self._backend, x509_exts) def public_bytes(self, encoding): bio = self._backend._create_mem_bio_gc() if encoding is serialization.Encoding.PEM: res = self._backend._lib.PEM_write_bio_X509_REQ( bio, self._x509_req ) elif encoding is serialization.Encoding.DER: res = self._backend._lib.i2d_X509_REQ_bio(bio, self._x509_req) else: raise TypeError("encoding must be an item from the Encoding enum") self._backend.openssl_assert(res == 1) return self._backend._read_mem_bio(bio) @property def tbs_certrequest_bytes(self): pp = self._backend._ffi.new("unsigned char **") res = self._backend._lib.i2d_re_X509_REQ_tbs(self._x509_req, pp) self._backend.openssl_assert(res > 0) pp = self._backend._ffi.gc( pp, lambda pointer: self._backend._lib.OPENSSL_free(pointer[0]) ) return self._backend._ffi.buffer(pp[0], res)[:] @property def signature(self): sig = self._backend._ffi.new("ASN1_BIT_STRING **") self._backend._lib.X509_REQ_get0_signature( self._x509_req, sig, self._backend._ffi.NULL ) self._backend.openssl_assert(sig[0] != self._backend._ffi.NULL) return _asn1_string_to_bytes(self._backend, sig[0]) @property def is_signature_valid(self): pkey = self._backend._lib.X509_REQ_get_pubkey(self._x509_req) self._backend.openssl_assert(pkey != self._backend._ffi.NULL) pkey = self._backend._ffi.gc(pkey, self._backend._lib.EVP_PKEY_free) res = self._backend._lib.X509_REQ_verify(self._x509_req, pkey) if res != 1: self._backend._consume_errors() return False return True @utils.register_interface( x509.certificate_transparency.SignedCertificateTimestamp ) class _SignedCertificateTimestamp(object): def __init__(self, backend, sct_list, sct): self._backend = backend # Keep the SCT_LIST that this SCT came from alive. self._sct_list = sct_list self._sct = sct @property def version(self): version = self._backend._lib.SCT_get_version(self._sct) assert version == self._backend._lib.SCT_VERSION_V1 return x509.certificate_transparency.Version.v1 @property def log_id(self): out = self._backend._ffi.new("unsigned char **") log_id_length = self._backend._lib.SCT_get0_log_id(self._sct, out) assert log_id_length >= 0 return self._backend._ffi.buffer(out[0], log_id_length)[:] @property def timestamp(self): timestamp = self._backend._lib.SCT_get_timestamp(self._sct) milliseconds = timestamp % 1000 return datetime.datetime.utcfromtimestamp( timestamp // 1000 ).replace(microsecond=milliseconds * 1000) @property def entry_type(self): entry_type = self._backend._lib.SCT_get_log_entry_type(self._sct) # We currently only support loading SCTs from the X.509 extension, so # we only have precerts. assert entry_type == self._backend._lib.CT_LOG_ENTRY_TYPE_PRECERT return x509.certificate_transparency.LogEntryType.PRE_CERTIFICATE @property def _signature(self): ptrptr = self._backend._ffi.new("unsigned char **") res = self._backend._lib.SCT_get0_signature(self._sct, ptrptr) self._backend.openssl_assert(res > 0) self._backend.openssl_assert(ptrptr[0] != self._backend._ffi.NULL) return self._backend._ffi.buffer(ptrptr[0], res)[:] def __hash__(self): return hash(self._signature) def __eq__(self, other): if not isinstance(other, _SignedCertificateTimestamp): return NotImplemented return self._signature == other._signature def __ne__(self, other): return not self == other ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/cryptography/hazmat/bindings/__init__.py ================================================ # This file is dual licensed under the terms of the Apache License, Version # 2.0, and the BSD License. See the LICENSE file in the root of this repository # for complete details. from __future__ import absolute_import, division, print_function ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/cryptography/hazmat/bindings/openssl/__init__.py ================================================ # This file is dual licensed under the terms of the Apache License, Version # 2.0, and the BSD License. See the LICENSE file in the root of this repository # for complete details. from __future__ import absolute_import, division, print_function ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/cryptography/hazmat/bindings/openssl/_conditional.py ================================================ # This file is dual licensed under the terms of the Apache License, Version # 2.0, and the BSD License. See the LICENSE file in the root of this repository # for complete details. from __future__ import absolute_import, division, print_function def cryptography_has_ec2m(): return [ "EC_POINT_set_affine_coordinates_GF2m", "EC_POINT_get_affine_coordinates_GF2m", "EC_POINT_set_compressed_coordinates_GF2m", ] def cryptography_has_ec_1_0_2(): return [ "EC_curve_nid2nist", ] def cryptography_has_set_ecdh_auto(): return [ "SSL_CTX_set_ecdh_auto", ] def cryptography_has_rsa_r_pkcs_decoding_error(): return [ "RSA_R_PKCS_DECODING_ERROR" ] def cryptography_has_rsa_oaep_md(): return [ "EVP_PKEY_CTX_set_rsa_oaep_md", ] def cryptography_has_rsa_oaep_label(): return [ "EVP_PKEY_CTX_set0_rsa_oaep_label", ] def cryptography_has_ssl3_method(): return [ "SSLv3_method", "SSLv3_client_method", "SSLv3_server_method", ] def cryptography_has_alpn(): return [ "SSL_CTX_set_alpn_protos", "SSL_set_alpn_protos", "SSL_CTX_set_alpn_select_cb", "SSL_get0_alpn_selected", ] def cryptography_has_compression(): return [ "SSL_get_current_compression", "SSL_get_current_expansion", "SSL_COMP_get_name", ] def cryptography_has_get_server_tmp_key(): return [ "SSL_get_server_tmp_key", ] def cryptography_has_102_verification_error_codes(): return [ 'X509_V_ERR_SUITE_B_INVALID_VERSION', 'X509_V_ERR_SUITE_B_INVALID_ALGORITHM', 'X509_V_ERR_SUITE_B_INVALID_CURVE', 'X509_V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM', 'X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED', 'X509_V_ERR_SUITE_B_CANNOT_SIGN_P_384_WITH_P_256', 'X509_V_ERR_HOSTNAME_MISMATCH', 'X509_V_ERR_EMAIL_MISMATCH', 'X509_V_ERR_IP_ADDRESS_MISMATCH' ] def cryptography_has_102_verification_params(): return [ "X509_V_FLAG_SUITEB_128_LOS_ONLY", "X509_V_FLAG_SUITEB_192_LOS", "X509_V_FLAG_SUITEB_128_LOS", "X509_VERIFY_PARAM_set1_host", "X509_VERIFY_PARAM_set1_email", "X509_VERIFY_PARAM_set1_ip", "X509_VERIFY_PARAM_set1_ip_asc", "X509_VERIFY_PARAM_set_hostflags", "SSL_get0_param", "X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT", "X509_CHECK_FLAG_NO_WILDCARDS", "X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS", "X509_CHECK_FLAG_MULTI_LABEL_WILDCARDS", "X509_CHECK_FLAG_SINGLE_LABEL_SUBDOMAINS" ] def cryptography_has_110_verification_params(): return [ "X509_CHECK_FLAG_NEVER_CHECK_SUBJECT" ] def cryptography_has_x509_v_flag_trusted_first(): return [ "X509_V_FLAG_TRUSTED_FIRST", ] def cryptography_has_x509_v_flag_partial_chain(): return [ "X509_V_FLAG_PARTIAL_CHAIN", ] def cryptography_has_set_cert_cb(): return [ "SSL_CTX_set_cert_cb", "SSL_set_cert_cb", ] def cryptography_has_ssl_st(): return [ "SSL_ST_BEFORE", "SSL_ST_OK", "SSL_ST_INIT", "SSL_ST_RENEGOTIATE", ] def cryptography_has_tls_st(): return [ "TLS_ST_BEFORE", "TLS_ST_OK", ] def cryptography_has_locking_callbacks(): return [ "Cryptography_setup_ssl_threads", ] def cryptography_has_scrypt(): return [ "EVP_PBE_scrypt", ] def cryptography_has_generic_dtls_method(): return [ "DTLS_method", "DTLS_server_method", "DTLS_client_method", "SSL_OP_NO_DTLSv1", "SSL_OP_NO_DTLSv1_2", "DTLS_set_link_mtu", "DTLS_get_link_min_mtu", ] def cryptography_has_evp_pkey_dhx(): return [ "EVP_PKEY_DHX", ] def cryptography_has_mem_functions(): return [ "Cryptography_CRYPTO_set_mem_functions", ] def cryptography_has_sct(): return [ "SCT_get_version", "SCT_get_log_entry_type", "SCT_get0_log_id", "SCT_get0_signature", "SCT_get_timestamp", "SCT_set_source", "sk_SCT_num", "sk_SCT_value", "SCT_LIST_free", "sk_SCT_push", "sk_SCT_new_null", "SCT_new", "SCT_set1_log_id", "SCT_set_timestamp", "SCT_set_version", "SCT_set_log_entry_type", ] def cryptography_has_x509_store_ctx_get_issuer(): return [ "X509_STORE_get_get_issuer", "X509_STORE_set_get_issuer", ] def cryptography_has_x25519(): return [ "EVP_PKEY_X25519", "NID_X25519", ] def cryptography_has_x448(): return [ "EVP_PKEY_X448", "NID_X448", ] def cryptography_has_ed448(): return [ "EVP_PKEY_ED448", "NID_ED448", ] def cryptography_has_ed25519(): return [ "NID_ED25519", "EVP_PKEY_ED25519", ] def cryptography_has_poly1305(): return [ "NID_poly1305", "EVP_PKEY_POLY1305", ] def cryptography_has_oneshot_evp_digest_sign_verify(): return [ "EVP_DigestSign", "EVP_DigestVerify", ] def cryptography_has_evp_digestfinal_xof(): return [ "EVP_DigestFinalXOF", ] def cryptography_has_evp_pkey_get_set_tls_encodedpoint(): return [ "EVP_PKEY_get1_tls_encodedpoint", "EVP_PKEY_set1_tls_encodedpoint", ] def cryptography_has_fips(): return [ "FIPS_mode_set", "FIPS_mode", ] def cryptography_has_ssl_sigalgs(): return [ "SSL_CTX_set1_sigalgs_list", "SSL_get_sigalgs", ] def cryptography_has_psk(): return [ "SSL_CTX_use_psk_identity_hint", "SSL_CTX_set_psk_server_callback", "SSL_CTX_set_psk_client_callback", ] def cryptography_has_custom_ext(): return [ "SSL_CTX_add_client_custom_ext", "SSL_CTX_add_server_custom_ext", "SSL_extension_supported", ] def cryptography_has_openssl_cleanup(): return [ "OPENSSL_cleanup", ] def cryptography_has_cipher_details(): return [ "SSL_CIPHER_is_aead", "SSL_CIPHER_get_cipher_nid", "SSL_CIPHER_get_digest_nid", "SSL_CIPHER_get_kx_nid", "SSL_CIPHER_get_auth_nid", ] def cryptography_has_tlsv13(): return [ "SSL_OP_NO_TLSv1_3", "SSL_VERIFY_POST_HANDSHAKE", "SSL_CTX_set_ciphersuites", "SSL_verify_client_post_handshake", "SSL_CTX_set_post_handshake_auth", "SSL_set_post_handshake_auth", "SSL_SESSION_get_max_early_data", "SSL_write_early_data", "SSL_read_early_data", "SSL_CTX_set_max_early_data", ] def cryptography_has_raw_key(): return [ "EVP_PKEY_new_raw_private_key", "EVP_PKEY_new_raw_public_key", "EVP_PKEY_get_raw_private_key", "EVP_PKEY_get_raw_public_key", ] def cryptography_has_evp_r_memory_limit_exceeded(): return [ "EVP_R_MEMORY_LIMIT_EXCEEDED", ] def cryptography_has_engine(): return [ "ENGINE_by_id", "ENGINE_init", "ENGINE_finish", "ENGINE_get_default_RAND", "ENGINE_set_default_RAND", "ENGINE_unregister_RAND", "ENGINE_ctrl_cmd", "ENGINE_free", "ENGINE_get_name", "Cryptography_add_osrandom_engine", ] def cryptography_has_verified_chain(): return [ "SSL_get0_verified_chain", ] # This is a mapping of # {condition: function-returning-names-dependent-on-that-condition} so we can # loop over them and delete unsupported names at runtime. It will be removed # when cffi supports #if in cdef. We use functions instead of just a dict of # lists so we can use coverage to measure which are used. CONDITIONAL_NAMES = { "Cryptography_HAS_EC2M": cryptography_has_ec2m, "Cryptography_HAS_EC_1_0_2": cryptography_has_ec_1_0_2, "Cryptography_HAS_SET_ECDH_AUTO": cryptography_has_set_ecdh_auto, "Cryptography_HAS_RSA_R_PKCS_DECODING_ERROR": ( cryptography_has_rsa_r_pkcs_decoding_error ), "Cryptography_HAS_RSA_OAEP_MD": cryptography_has_rsa_oaep_md, "Cryptography_HAS_RSA_OAEP_LABEL": cryptography_has_rsa_oaep_label, "Cryptography_HAS_SSL3_METHOD": cryptography_has_ssl3_method, "Cryptography_HAS_ALPN": cryptography_has_alpn, "Cryptography_HAS_COMPRESSION": cryptography_has_compression, "Cryptography_HAS_GET_SERVER_TMP_KEY": cryptography_has_get_server_tmp_key, "Cryptography_HAS_102_VERIFICATION_ERROR_CODES": ( cryptography_has_102_verification_error_codes ), "Cryptography_HAS_102_VERIFICATION_PARAMS": ( cryptography_has_102_verification_params ), "Cryptography_HAS_110_VERIFICATION_PARAMS": ( cryptography_has_110_verification_params ), "Cryptography_HAS_X509_V_FLAG_TRUSTED_FIRST": ( cryptography_has_x509_v_flag_trusted_first ), "Cryptography_HAS_X509_V_FLAG_PARTIAL_CHAIN": ( cryptography_has_x509_v_flag_partial_chain ), "Cryptography_HAS_SET_CERT_CB": cryptography_has_set_cert_cb, "Cryptography_HAS_SSL_ST": cryptography_has_ssl_st, "Cryptography_HAS_TLS_ST": cryptography_has_tls_st, "Cryptography_HAS_LOCKING_CALLBACKS": cryptography_has_locking_callbacks, "Cryptography_HAS_SCRYPT": cryptography_has_scrypt, "Cryptography_HAS_GENERIC_DTLS_METHOD": ( cryptography_has_generic_dtls_method ), "Cryptography_HAS_EVP_PKEY_DHX": cryptography_has_evp_pkey_dhx, "Cryptography_HAS_MEM_FUNCTIONS": cryptography_has_mem_functions, "Cryptography_HAS_SCT": cryptography_has_sct, "Cryptography_HAS_X509_STORE_CTX_GET_ISSUER": ( cryptography_has_x509_store_ctx_get_issuer ), "Cryptography_HAS_X25519": cryptography_has_x25519, "Cryptography_HAS_X448": cryptography_has_x448, "Cryptography_HAS_ED448": cryptography_has_ed448, "Cryptography_HAS_ED25519": cryptography_has_ed25519, "Cryptography_HAS_POLY1305": cryptography_has_poly1305, "Cryptography_HAS_ONESHOT_EVP_DIGEST_SIGN_VERIFY": ( cryptography_has_oneshot_evp_digest_sign_verify ), "Cryptography_HAS_EVP_PKEY_get_set_tls_encodedpoint": ( cryptography_has_evp_pkey_get_set_tls_encodedpoint ), "Cryptography_HAS_FIPS": cryptography_has_fips, "Cryptography_HAS_SIGALGS": cryptography_has_ssl_sigalgs, "Cryptography_HAS_PSK": cryptography_has_psk, "Cryptography_HAS_CUSTOM_EXT": cryptography_has_custom_ext, "Cryptography_HAS_OPENSSL_CLEANUP": cryptography_has_openssl_cleanup, "Cryptography_HAS_CIPHER_DETAILS": cryptography_has_cipher_details, "Cryptography_HAS_TLSv1_3": cryptography_has_tlsv13, "Cryptography_HAS_RAW_KEY": cryptography_has_raw_key, "Cryptography_HAS_EVP_DIGESTFINAL_XOF": ( cryptography_has_evp_digestfinal_xof ), "Cryptography_HAS_EVP_R_MEMORY_LIMIT_EXCEEDED": ( cryptography_has_evp_r_memory_limit_exceeded ), "Cryptography_HAS_ENGINE": cryptography_has_engine, "Cryptography_HAS_VERIFIED_CHAIN": cryptography_has_verified_chain, } ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/cryptography/hazmat/bindings/openssl/binding.py ================================================ # This file is dual licensed under the terms of the Apache License, Version # 2.0, and the BSD License. See the LICENSE file in the root of this repository # for complete details. from __future__ import absolute_import, division, print_function import collections import threading import types import warnings import cryptography from cryptography import utils from cryptography.exceptions import InternalError from cryptography.hazmat.bindings._openssl import ffi, lib from cryptography.hazmat.bindings.openssl._conditional import CONDITIONAL_NAMES _OpenSSLErrorWithText = collections.namedtuple( "_OpenSSLErrorWithText", ["code", "lib", "func", "reason", "reason_text"] ) class _OpenSSLError(object): def __init__(self, code, lib, func, reason): self._code = code self._lib = lib self._func = func self._reason = reason def _lib_reason_match(self, lib, reason): return lib == self.lib and reason == self.reason code = utils.read_only_property("_code") lib = utils.read_only_property("_lib") func = utils.read_only_property("_func") reason = utils.read_only_property("_reason") def _consume_errors(lib): errors = [] while True: code = lib.ERR_get_error() if code == 0: break err_lib = lib.ERR_GET_LIB(code) err_func = lib.ERR_GET_FUNC(code) err_reason = lib.ERR_GET_REASON(code) errors.append(_OpenSSLError(code, err_lib, err_func, err_reason)) return errors def _openssl_assert(lib, ok): if not ok: errors = _consume_errors(lib) errors_with_text = [] for err in errors: buf = ffi.new("char[]", 256) lib.ERR_error_string_n(err.code, buf, len(buf)) err_text_reason = ffi.string(buf) errors_with_text.append( _OpenSSLErrorWithText( err.code, err.lib, err.func, err.reason, err_text_reason ) ) raise InternalError( "Unknown OpenSSL error. This error is commonly encountered when " "another library is not cleaning up the OpenSSL error stack. If " "you are using cryptography with another library that uses " "OpenSSL try disabling it before reporting a bug. Otherwise " "please file an issue at https://github.com/pyca/cryptography/" "issues with information on how to reproduce " "this. ({0!r})".format(errors_with_text), errors_with_text ) def build_conditional_library(lib, conditional_names): conditional_lib = types.ModuleType("lib") conditional_lib._original_lib = lib excluded_names = set() for condition, names_cb in conditional_names.items(): if not getattr(lib, condition): excluded_names.update(names_cb()) for attr in dir(lib): if attr not in excluded_names: setattr(conditional_lib, attr, getattr(lib, attr)) return conditional_lib class Binding(object): """ OpenSSL API wrapper. """ lib = None ffi = ffi _lib_loaded = False _init_lock = threading.Lock() _lock_init_lock = threading.Lock() def __init__(self): self._ensure_ffi_initialized() @classmethod def _register_osrandom_engine(cls): # Clear any errors extant in the queue before we start. In many # scenarios other things may be interacting with OpenSSL in the same # process space and it has proven untenable to assume that they will # reliably clear the error queue. Once we clear it here we will # error on any subsequent unexpected item in the stack. cls.lib.ERR_clear_error() if cls.lib.Cryptography_HAS_ENGINE: result = cls.lib.Cryptography_add_osrandom_engine() _openssl_assert(cls.lib, result in (1, 2)) @classmethod def _ensure_ffi_initialized(cls): with cls._init_lock: if not cls._lib_loaded: cls.lib = build_conditional_library(lib, CONDITIONAL_NAMES) cls._lib_loaded = True # initialize the SSL library cls.lib.SSL_library_init() # adds all ciphers/digests for EVP cls.lib.OpenSSL_add_all_algorithms() # loads error strings for libcrypto and libssl functions cls.lib.SSL_load_error_strings() cls._register_osrandom_engine() @classmethod def init_static_locks(cls): with cls._lock_init_lock: cls._ensure_ffi_initialized() # Use Python's implementation if available, importing _ssl triggers # the setup for this. __import__("_ssl") if (not cls.lib.Cryptography_HAS_LOCKING_CALLBACKS or cls.lib.CRYPTO_get_locking_callback() != cls.ffi.NULL): return # If nothing else has setup a locking callback already, we set up # our own res = lib.Cryptography_setup_ssl_threads() _openssl_assert(cls.lib, res == 1) def _verify_openssl_version(lib): if ( lib.CRYPTOGRAPHY_OPENSSL_LESS_THAN_102 and not lib.CRYPTOGRAPHY_IS_LIBRESSL ): warnings.warn( "OpenSSL version 1.0.1 is no longer supported by the OpenSSL " "project, please upgrade. The next version of cryptography will " "drop support for it.", utils.CryptographyDeprecationWarning ) def _verify_package_version(version): # Occasionally we run into situations where the version of the Python # package does not match the version of the shared object that is loaded. # This may occur in environments where multiple versions of cryptography # are installed and available in the python path. To avoid errors cropping # up later this code checks that the currently imported package and the # shared object that were loaded have the same version and raise an # ImportError if they do not so_package_version = ffi.string(lib.CRYPTOGRAPHY_PACKAGE_VERSION) if version.encode("ascii") != so_package_version: raise ImportError( "The version of cryptography does not match the loaded " "shared object. This can happen if you have multiple copies of " "cryptography installed in your Python path. Please try creating " "a new virtual environment to resolve this issue. " "Loaded python version: {}, shared object version: {}".format( version, so_package_version ) ) _verify_package_version(cryptography.__version__) # OpenSSL is not thread safe until the locks are initialized. We call this # method in module scope so that it executes with the import lock. On # Pythons < 3.4 this import lock is a global lock, which can prevent a race # condition registering the OpenSSL locks. On Python 3.4+ the import lock # is per module so this approach will not work. Binding.init_static_locks() _verify_openssl_version(Binding.lib) ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/cryptography/hazmat/primitives/__init__.py ================================================ # This file is dual licensed under the terms of the Apache License, Version # 2.0, and the BSD License. See the LICENSE file in the root of this repository # for complete details. from __future__ import absolute_import, division, print_function ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/cryptography/hazmat/primitives/asymmetric/__init__.py ================================================ # This file is dual licensed under the terms of the Apache License, Version # 2.0, and the BSD License. See the LICENSE file in the root of this repository # for complete details. from __future__ import absolute_import, division, print_function import abc import six @six.add_metaclass(abc.ABCMeta) class AsymmetricSignatureContext(object): @abc.abstractmethod def update(self, data): """ Processes the provided bytes and returns nothing. """ @abc.abstractmethod def finalize(self): """ Returns the signature as bytes. """ @six.add_metaclass(abc.ABCMeta) class AsymmetricVerificationContext(object): @abc.abstractmethod def update(self, data): """ Processes the provided bytes and returns nothing. """ @abc.abstractmethod def verify(self): """ Raises an exception if the bytes provided to update do not match the signature or the signature does not match the public key. """ ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/cryptography/hazmat/primitives/asymmetric/dh.py ================================================ # This file is dual licensed under the terms of the Apache License, Version # 2.0, and the BSD License. See the LICENSE file in the root of this repository # for complete details. from __future__ import absolute_import, division, print_function import abc import six from cryptography import utils def generate_parameters(generator, key_size, backend): return backend.generate_dh_parameters(generator, key_size) class DHPrivateNumbers(object): def __init__(self, x, public_numbers): if not isinstance(x, six.integer_types): raise TypeError("x must be an integer.") if not isinstance(public_numbers, DHPublicNumbers): raise TypeError("public_numbers must be an instance of " "DHPublicNumbers.") self._x = x self._public_numbers = public_numbers def __eq__(self, other): if not isinstance(other, DHPrivateNumbers): return NotImplemented return ( self._x == other._x and self._public_numbers == other._public_numbers ) def __ne__(self, other): return not self == other def private_key(self, backend): return backend.load_dh_private_numbers(self) public_numbers = utils.read_only_property("_public_numbers") x = utils.read_only_property("_x") class DHPublicNumbers(object): def __init__(self, y, parameter_numbers): if not isinstance(y, six.integer_types): raise TypeError("y must be an integer.") if not isinstance(parameter_numbers, DHParameterNumbers): raise TypeError( "parameters must be an instance of DHParameterNumbers.") self._y = y self._parameter_numbers = parameter_numbers def __eq__(self, other): if not isinstance(other, DHPublicNumbers): return NotImplemented return ( self._y == other._y and self._parameter_numbers == other._parameter_numbers ) def __ne__(self, other): return not self == other def public_key(self, backend): return backend.load_dh_public_numbers(self) y = utils.read_only_property("_y") parameter_numbers = utils.read_only_property("_parameter_numbers") class DHParameterNumbers(object): def __init__(self, p, g, q=None): if ( not isinstance(p, six.integer_types) or not isinstance(g, six.integer_types) ): raise TypeError("p and g must be integers") if q is not None and not isinstance(q, six.integer_types): raise TypeError("q must be integer or None") if g < 2: raise ValueError("DH generator must be 2 or greater") self._p = p self._g = g self._q = q def __eq__(self, other): if not isinstance(other, DHParameterNumbers): return NotImplemented return ( self._p == other._p and self._g == other._g and self._q == other._q ) def __ne__(self, other): return not self == other def parameters(self, backend): return backend.load_dh_parameter_numbers(self) p = utils.read_only_property("_p") g = utils.read_only_property("_g") q = utils.read_only_property("_q") @six.add_metaclass(abc.ABCMeta) class DHParameters(object): @abc.abstractmethod def generate_private_key(self): """ Generates and returns a DHPrivateKey. """ @abc.abstractmethod def parameter_bytes(self, encoding, format): """ Returns the parameters serialized as bytes. """ @abc.abstractmethod def parameter_numbers(self): """ Returns a DHParameterNumbers. """ DHParametersWithSerialization = DHParameters @six.add_metaclass(abc.ABCMeta) class DHPrivateKey(object): @abc.abstractproperty def key_size(self): """ The bit length of the prime modulus. """ @abc.abstractmethod def public_key(self): """ The DHPublicKey associated with this private key. """ @abc.abstractmethod def parameters(self): """ The DHParameters object associated with this private key. """ @abc.abstractmethod def exchange(self, peer_public_key): """ Given peer's DHPublicKey, carry out the key exchange and return shared key as bytes. """ @six.add_metaclass(abc.ABCMeta) class DHPrivateKeyWithSerialization(DHPrivateKey): @abc.abstractmethod def private_numbers(self): """ Returns a DHPrivateNumbers. """ @abc.abstractmethod def private_bytes(self, encoding, format, encryption_algorithm): """ Returns the key serialized as bytes. """ @six.add_metaclass(abc.ABCMeta) class DHPublicKey(object): @abc.abstractproperty def key_size(self): """ The bit length of the prime modulus. """ @abc.abstractmethod def parameters(self): """ The DHParameters object associated with this public key. """ @abc.abstractmethod def public_numbers(self): """ Returns a DHPublicNumbers. """ @abc.abstractmethod def public_bytes(self, encoding, format): """ Returns the key serialized as bytes. """ DHPublicKeyWithSerialization = DHPublicKey ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/cryptography/hazmat/primitives/asymmetric/dsa.py ================================================ # This file is dual licensed under the terms of the Apache License, Version # 2.0, and the BSD License. See the LICENSE file in the root of this repository # for complete details. from __future__ import absolute_import, division, print_function import abc import six from cryptography import utils @six.add_metaclass(abc.ABCMeta) class DSAParameters(object): @abc.abstractmethod def generate_private_key(self): """ Generates and returns a DSAPrivateKey. """ @six.add_metaclass(abc.ABCMeta) class DSAParametersWithNumbers(DSAParameters): @abc.abstractmethod def parameter_numbers(self): """ Returns a DSAParameterNumbers. """ @six.add_metaclass(abc.ABCMeta) class DSAPrivateKey(object): @abc.abstractproperty def key_size(self): """ The bit length of the prime modulus. """ @abc.abstractmethod def public_key(self): """ The DSAPublicKey associated with this private key. """ @abc.abstractmethod def parameters(self): """ The DSAParameters object associated with this private key. """ @abc.abstractmethod def signer(self, signature_algorithm): """ Returns an AsymmetricSignatureContext used for signing data. """ @abc.abstractmethod def sign(self, data, algorithm): """ Signs the data """ @six.add_metaclass(abc.ABCMeta) class DSAPrivateKeyWithSerialization(DSAPrivateKey): @abc.abstractmethod def private_numbers(self): """ Returns a DSAPrivateNumbers. """ @abc.abstractmethod def private_bytes(self, encoding, format, encryption_algorithm): """ Returns the key serialized as bytes. """ @six.add_metaclass(abc.ABCMeta) class DSAPublicKey(object): @abc.abstractproperty def key_size(self): """ The bit length of the prime modulus. """ @abc.abstractmethod def parameters(self): """ The DSAParameters object associated with this public key. """ @abc.abstractmethod def verifier(self, signature, signature_algorithm): """ Returns an AsymmetricVerificationContext used for signing data. """ @abc.abstractmethod def public_numbers(self): """ Returns a DSAPublicNumbers. """ @abc.abstractmethod def public_bytes(self, encoding, format): """ Returns the key serialized as bytes. """ @abc.abstractmethod def verify(self, signature, data, algorithm): """ Verifies the signature of the data. """ DSAPublicKeyWithSerialization = DSAPublicKey def generate_parameters(key_size, backend): return backend.generate_dsa_parameters(key_size) def generate_private_key(key_size, backend): return backend.generate_dsa_private_key_and_parameters(key_size) def _check_dsa_parameters(parameters): if parameters.p.bit_length() not in [1024, 2048, 3072]: raise ValueError("p must be exactly 1024, 2048, or 3072 bits long") if parameters.q.bit_length() not in [160, 224, 256]: raise ValueError("q must be exactly 160, 224, or 256 bits long") if not (1 < parameters.g < parameters.p): raise ValueError("g, p don't satisfy 1 < g < p.") def _check_dsa_private_numbers(numbers): parameters = numbers.public_numbers.parameter_numbers _check_dsa_parameters(parameters) if numbers.x <= 0 or numbers.x >= parameters.q: raise ValueError("x must be > 0 and < q.") if numbers.public_numbers.y != pow(parameters.g, numbers.x, parameters.p): raise ValueError("y must be equal to (g ** x % p).") class DSAParameterNumbers(object): def __init__(self, p, q, g): if ( not isinstance(p, six.integer_types) or not isinstance(q, six.integer_types) or not isinstance(g, six.integer_types) ): raise TypeError( "DSAParameterNumbers p, q, and g arguments must be integers." ) self._p = p self._q = q self._g = g p = utils.read_only_property("_p") q = utils.read_only_property("_q") g = utils.read_only_property("_g") def parameters(self, backend): return backend.load_dsa_parameter_numbers(self) def __eq__(self, other): if not isinstance(other, DSAParameterNumbers): return NotImplemented return self.p == other.p and self.q == other.q and self.g == other.g def __ne__(self, other): return not self == other def __repr__(self): return ( "".format( self=self ) ) class DSAPublicNumbers(object): def __init__(self, y, parameter_numbers): if not isinstance(y, six.integer_types): raise TypeError("DSAPublicNumbers y argument must be an integer.") if not isinstance(parameter_numbers, DSAParameterNumbers): raise TypeError( "parameter_numbers must be a DSAParameterNumbers instance." ) self._y = y self._parameter_numbers = parameter_numbers y = utils.read_only_property("_y") parameter_numbers = utils.read_only_property("_parameter_numbers") def public_key(self, backend): return backend.load_dsa_public_numbers(self) def __eq__(self, other): if not isinstance(other, DSAPublicNumbers): return NotImplemented return ( self.y == other.y and self.parameter_numbers == other.parameter_numbers ) def __ne__(self, other): return not self == other def __repr__(self): return ( "".format(self=self) ) class DSAPrivateNumbers(object): def __init__(self, x, public_numbers): if not isinstance(x, six.integer_types): raise TypeError("DSAPrivateNumbers x argument must be an integer.") if not isinstance(public_numbers, DSAPublicNumbers): raise TypeError( "public_numbers must be a DSAPublicNumbers instance." ) self._public_numbers = public_numbers self._x = x x = utils.read_only_property("_x") public_numbers = utils.read_only_property("_public_numbers") def private_key(self, backend): return backend.load_dsa_private_numbers(self) def __eq__(self, other): if not isinstance(other, DSAPrivateNumbers): return NotImplemented return ( self.x == other.x and self.public_numbers == other.public_numbers ) def __ne__(self, other): return not self == other ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/cryptography/hazmat/primitives/asymmetric/ec.py ================================================ # This file is dual licensed under the terms of the Apache License, Version # 2.0, and the BSD License. See the LICENSE file in the root of this repository # for complete details. from __future__ import absolute_import, division, print_function import abc import warnings import six from cryptography import utils from cryptography.hazmat._oid import ObjectIdentifier class EllipticCurveOID(object): SECP192R1 = ObjectIdentifier("1.2.840.10045.3.1.1") SECP224R1 = ObjectIdentifier("1.3.132.0.33") SECP256K1 = ObjectIdentifier("1.3.132.0.10") SECP256R1 = ObjectIdentifier("1.2.840.10045.3.1.7") SECP384R1 = ObjectIdentifier("1.3.132.0.34") SECP521R1 = ObjectIdentifier("1.3.132.0.35") BRAINPOOLP256R1 = ObjectIdentifier("1.3.36.3.3.2.8.1.1.7") BRAINPOOLP384R1 = ObjectIdentifier("1.3.36.3.3.2.8.1.1.11") BRAINPOOLP512R1 = ObjectIdentifier("1.3.36.3.3.2.8.1.1.13") SECT163K1 = ObjectIdentifier("1.3.132.0.1") SECT163R2 = ObjectIdentifier("1.3.132.0.15") SECT233K1 = ObjectIdentifier("1.3.132.0.26") SECT233R1 = ObjectIdentifier("1.3.132.0.27") SECT283K1 = ObjectIdentifier("1.3.132.0.16") SECT283R1 = ObjectIdentifier("1.3.132.0.17") SECT409K1 = ObjectIdentifier("1.3.132.0.36") SECT409R1 = ObjectIdentifier("1.3.132.0.37") SECT571K1 = ObjectIdentifier("1.3.132.0.38") SECT571R1 = ObjectIdentifier("1.3.132.0.39") @six.add_metaclass(abc.ABCMeta) class EllipticCurve(object): @abc.abstractproperty def name(self): """ The name of the curve. e.g. secp256r1. """ @abc.abstractproperty def key_size(self): """ Bit size of a secret scalar for the curve. """ @six.add_metaclass(abc.ABCMeta) class EllipticCurveSignatureAlgorithm(object): @abc.abstractproperty def algorithm(self): """ The digest algorithm used with this signature. """ @six.add_metaclass(abc.ABCMeta) class EllipticCurvePrivateKey(object): @abc.abstractmethod def signer(self, signature_algorithm): """ Returns an AsymmetricSignatureContext used for signing data. """ @abc.abstractmethod def exchange(self, algorithm, peer_public_key): """ Performs a key exchange operation using the provided algorithm with the provided peer's public key. """ @abc.abstractmethod def public_key(self): """ The EllipticCurvePublicKey for this private key. """ @abc.abstractproperty def curve(self): """ The EllipticCurve that this key is on. """ @abc.abstractproperty def key_size(self): """ Bit size of a secret scalar for the curve. """ @abc.abstractmethod def sign(self, data, signature_algorithm): """ Signs the data """ @six.add_metaclass(abc.ABCMeta) class EllipticCurvePrivateKeyWithSerialization(EllipticCurvePrivateKey): @abc.abstractmethod def private_numbers(self): """ Returns an EllipticCurvePrivateNumbers. """ @abc.abstractmethod def private_bytes(self, encoding, format, encryption_algorithm): """ Returns the key serialized as bytes. """ @six.add_metaclass(abc.ABCMeta) class EllipticCurvePublicKey(object): @abc.abstractmethod def verifier(self, signature, signature_algorithm): """ Returns an AsymmetricVerificationContext used for signing data. """ @abc.abstractproperty def curve(self): """ The EllipticCurve that this key is on. """ @abc.abstractproperty def key_size(self): """ Bit size of a secret scalar for the curve. """ @abc.abstractmethod def public_numbers(self): """ Returns an EllipticCurvePublicNumbers. """ @abc.abstractmethod def public_bytes(self, encoding, format): """ Returns the key serialized as bytes. """ @abc.abstractmethod def verify(self, signature, data, signature_algorithm): """ Verifies the signature of the data. """ @classmethod def from_encoded_point(cls, curve, data): utils._check_bytes("data", data) if not isinstance(curve, EllipticCurve): raise TypeError("curve must be an EllipticCurve instance") if len(data) == 0: raise ValueError("data must not be an empty byte string") if six.indexbytes(data, 0) not in [0x02, 0x03, 0x04]: raise ValueError("Unsupported elliptic curve point type") from cryptography.hazmat.backends.openssl.backend import backend return backend.load_elliptic_curve_public_bytes(curve, data) EllipticCurvePublicKeyWithSerialization = EllipticCurvePublicKey @utils.register_interface(EllipticCurve) class SECT571R1(object): name = "sect571r1" key_size = 570 @utils.register_interface(EllipticCurve) class SECT409R1(object): name = "sect409r1" key_size = 409 @utils.register_interface(EllipticCurve) class SECT283R1(object): name = "sect283r1" key_size = 283 @utils.register_interface(EllipticCurve) class SECT233R1(object): name = "sect233r1" key_size = 233 @utils.register_interface(EllipticCurve) class SECT163R2(object): name = "sect163r2" key_size = 163 @utils.register_interface(EllipticCurve) class SECT571K1(object): name = "sect571k1" key_size = 571 @utils.register_interface(EllipticCurve) class SECT409K1(object): name = "sect409k1" key_size = 409 @utils.register_interface(EllipticCurve) class SECT283K1(object): name = "sect283k1" key_size = 283 @utils.register_interface(EllipticCurve) class SECT233K1(object): name = "sect233k1" key_size = 233 @utils.register_interface(EllipticCurve) class SECT163K1(object): name = "sect163k1" key_size = 163 @utils.register_interface(EllipticCurve) class SECP521R1(object): name = "secp521r1" key_size = 521 @utils.register_interface(EllipticCurve) class SECP384R1(object): name = "secp384r1" key_size = 384 @utils.register_interface(EllipticCurve) class SECP256R1(object): name = "secp256r1" key_size = 256 @utils.register_interface(EllipticCurve) class SECP256K1(object): name = "secp256k1" key_size = 256 @utils.register_interface(EllipticCurve) class SECP224R1(object): name = "secp224r1" key_size = 224 @utils.register_interface(EllipticCurve) class SECP192R1(object): name = "secp192r1" key_size = 192 @utils.register_interface(EllipticCurve) class BrainpoolP256R1(object): name = "brainpoolP256r1" key_size = 256 @utils.register_interface(EllipticCurve) class BrainpoolP384R1(object): name = "brainpoolP384r1" key_size = 384 @utils.register_interface(EllipticCurve) class BrainpoolP512R1(object): name = "brainpoolP512r1" key_size = 512 _CURVE_TYPES = { "prime192v1": SECP192R1, "prime256v1": SECP256R1, "secp192r1": SECP192R1, "secp224r1": SECP224R1, "secp256r1": SECP256R1, "secp384r1": SECP384R1, "secp521r1": SECP521R1, "secp256k1": SECP256K1, "sect163k1": SECT163K1, "sect233k1": SECT233K1, "sect283k1": SECT283K1, "sect409k1": SECT409K1, "sect571k1": SECT571K1, "sect163r2": SECT163R2, "sect233r1": SECT233R1, "sect283r1": SECT283R1, "sect409r1": SECT409R1, "sect571r1": SECT571R1, "brainpoolP256r1": BrainpoolP256R1, "brainpoolP384r1": BrainpoolP384R1, "brainpoolP512r1": BrainpoolP512R1, } @utils.register_interface(EllipticCurveSignatureAlgorithm) class ECDSA(object): def __init__(self, algorithm): self._algorithm = algorithm algorithm = utils.read_only_property("_algorithm") def generate_private_key(curve, backend): return backend.generate_elliptic_curve_private_key(curve) def derive_private_key(private_value, curve, backend): if not isinstance(private_value, six.integer_types): raise TypeError("private_value must be an integer type.") if private_value <= 0: raise ValueError("private_value must be a positive integer.") if not isinstance(curve, EllipticCurve): raise TypeError("curve must provide the EllipticCurve interface.") return backend.derive_elliptic_curve_private_key(private_value, curve) class EllipticCurvePublicNumbers(object): def __init__(self, x, y, curve): if ( not isinstance(x, six.integer_types) or not isinstance(y, six.integer_types) ): raise TypeError("x and y must be integers.") if not isinstance(curve, EllipticCurve): raise TypeError("curve must provide the EllipticCurve interface.") self._y = y self._x = x self._curve = curve def public_key(self, backend): return backend.load_elliptic_curve_public_numbers(self) def encode_point(self): warnings.warn( "encode_point has been deprecated on EllipticCurvePublicNumbers" " and will be removed in a future version. Please use " "EllipticCurvePublicKey.public_bytes to obtain both " "compressed and uncompressed point encoding.", utils.DeprecatedIn25, stacklevel=2, ) # key_size is in bits. Convert to bytes and round up byte_length = (self.curve.key_size + 7) // 8 return ( b'\x04' + utils.int_to_bytes(self.x, byte_length) + utils.int_to_bytes(self.y, byte_length) ) @classmethod def from_encoded_point(cls, curve, data): if not isinstance(curve, EllipticCurve): raise TypeError("curve must be an EllipticCurve instance") warnings.warn( "Support for unsafe construction of public numbers from " "encoded data will be removed in a future version. " "Please use EllipticCurvePublicKey.from_encoded_point", utils.DeprecatedIn25, stacklevel=2, ) if data.startswith(b'\x04'): # key_size is in bits. Convert to bytes and round up byte_length = (curve.key_size + 7) // 8 if len(data) == 2 * byte_length + 1: x = utils.int_from_bytes(data[1:byte_length + 1], 'big') y = utils.int_from_bytes(data[byte_length + 1:], 'big') return cls(x, y, curve) else: raise ValueError('Invalid elliptic curve point data length') else: raise ValueError('Unsupported elliptic curve point type') curve = utils.read_only_property("_curve") x = utils.read_only_property("_x") y = utils.read_only_property("_y") def __eq__(self, other): if not isinstance(other, EllipticCurvePublicNumbers): return NotImplemented return ( self.x == other.x and self.y == other.y and self.curve.name == other.curve.name and self.curve.key_size == other.curve.key_size ) def __ne__(self, other): return not self == other def __hash__(self): return hash((self.x, self.y, self.curve.name, self.curve.key_size)) def __repr__(self): return ( "".format(self) ) class EllipticCurvePrivateNumbers(object): def __init__(self, private_value, public_numbers): if not isinstance(private_value, six.integer_types): raise TypeError("private_value must be an integer.") if not isinstance(public_numbers, EllipticCurvePublicNumbers): raise TypeError( "public_numbers must be an EllipticCurvePublicNumbers " "instance." ) self._private_value = private_value self._public_numbers = public_numbers def private_key(self, backend): return backend.load_elliptic_curve_private_numbers(self) private_value = utils.read_only_property("_private_value") public_numbers = utils.read_only_property("_public_numbers") def __eq__(self, other): if not isinstance(other, EllipticCurvePrivateNumbers): return NotImplemented return ( self.private_value == other.private_value and self.public_numbers == other.public_numbers ) def __ne__(self, other): return not self == other def __hash__(self): return hash((self.private_value, self.public_numbers)) class ECDH(object): pass _OID_TO_CURVE = { EllipticCurveOID.SECP192R1: SECP192R1, EllipticCurveOID.SECP224R1: SECP224R1, EllipticCurveOID.SECP256K1: SECP256K1, EllipticCurveOID.SECP256R1: SECP256R1, EllipticCurveOID.SECP384R1: SECP384R1, EllipticCurveOID.SECP521R1: SECP521R1, EllipticCurveOID.BRAINPOOLP256R1: BrainpoolP256R1, EllipticCurveOID.BRAINPOOLP384R1: BrainpoolP384R1, EllipticCurveOID.BRAINPOOLP512R1: BrainpoolP512R1, EllipticCurveOID.SECT163K1: SECT163K1, EllipticCurveOID.SECT163R2: SECT163R2, EllipticCurveOID.SECT233K1: SECT233K1, EllipticCurveOID.SECT233R1: SECT233R1, EllipticCurveOID.SECT283K1: SECT283K1, EllipticCurveOID.SECT283R1: SECT283R1, EllipticCurveOID.SECT409K1: SECT409K1, EllipticCurveOID.SECT409R1: SECT409R1, EllipticCurveOID.SECT571K1: SECT571K1, EllipticCurveOID.SECT571R1: SECT571R1, } def get_curve_for_oid(oid): try: return _OID_TO_CURVE[oid] except KeyError: raise LookupError( "The provided object identifier has no matching elliptic " "curve class" ) ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/cryptography/hazmat/primitives/asymmetric/ed25519.py ================================================ # This file is dual licensed under the terms of the Apache License, Version # 2.0, and the BSD License. See the LICENSE file in the root of this repository # for complete details. from __future__ import absolute_import, division, print_function import abc import six from cryptography.exceptions import UnsupportedAlgorithm, _Reasons _ED25519_KEY_SIZE = 32 _ED25519_SIG_SIZE = 64 @six.add_metaclass(abc.ABCMeta) class Ed25519PublicKey(object): @classmethod def from_public_bytes(cls, data): from cryptography.hazmat.backends.openssl.backend import backend if not backend.ed25519_supported(): raise UnsupportedAlgorithm( "ed25519 is not supported by this version of OpenSSL.", _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM ) return backend.ed25519_load_public_bytes(data) @abc.abstractmethod def public_bytes(self, encoding, format): """ The serialized bytes of the public key. """ @abc.abstractmethod def verify(self, signature, data): """ Verify the signature. """ @six.add_metaclass(abc.ABCMeta) class Ed25519PrivateKey(object): @classmethod def generate(cls): from cryptography.hazmat.backends.openssl.backend import backend if not backend.ed25519_supported(): raise UnsupportedAlgorithm( "ed25519 is not supported by this version of OpenSSL.", _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM ) return backend.ed25519_generate_key() @classmethod def from_private_bytes(cls, data): from cryptography.hazmat.backends.openssl.backend import backend if not backend.ed25519_supported(): raise UnsupportedAlgorithm( "ed25519 is not supported by this version of OpenSSL.", _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM ) return backend.ed25519_load_private_bytes(data) @abc.abstractmethod def public_key(self): """ The Ed25519PublicKey derived from the private key. """ @abc.abstractmethod def private_bytes(self, encoding, format, encryption_algorithm): """ The serialized bytes of the private key. """ @abc.abstractmethod def sign(self, data): """ Signs the data. """ ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/cryptography/hazmat/primitives/asymmetric/ed448.py ================================================ # This file is dual licensed under the terms of the Apache License, Version # 2.0, and the BSD License. See the LICENSE file in the root of this repository # for complete details. from __future__ import absolute_import, division, print_function import abc import six from cryptography.exceptions import UnsupportedAlgorithm, _Reasons @six.add_metaclass(abc.ABCMeta) class Ed448PublicKey(object): @classmethod def from_public_bytes(cls, data): from cryptography.hazmat.backends.openssl.backend import backend if not backend.ed448_supported(): raise UnsupportedAlgorithm( "ed448 is not supported by this version of OpenSSL.", _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM ) return backend.ed448_load_public_bytes(data) @abc.abstractmethod def public_bytes(self, encoding, format): """ The serialized bytes of the public key. """ @abc.abstractmethod def verify(self, signature, data): """ Verify the signature. """ @six.add_metaclass(abc.ABCMeta) class Ed448PrivateKey(object): @classmethod def generate(cls): from cryptography.hazmat.backends.openssl.backend import backend if not backend.ed448_supported(): raise UnsupportedAlgorithm( "ed448 is not supported by this version of OpenSSL.", _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM ) return backend.ed448_generate_key() @classmethod def from_private_bytes(cls, data): from cryptography.hazmat.backends.openssl.backend import backend if not backend.ed448_supported(): raise UnsupportedAlgorithm( "ed448 is not supported by this version of OpenSSL.", _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM ) return backend.ed448_load_private_bytes(data) @abc.abstractmethod def public_key(self): """ The Ed448PublicKey derived from the private key. """ @abc.abstractmethod def sign(self, data): """ Signs the data. """ @abc.abstractmethod def private_bytes(self, encoding, format, encryption_algorithm): """ The serialized bytes of the private key. """ ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/cryptography/hazmat/primitives/asymmetric/padding.py ================================================ # This file is dual licensed under the terms of the Apache License, Version # 2.0, and the BSD License. See the LICENSE file in the root of this repository # for complete details. from __future__ import absolute_import, division, print_function import abc import math import six from cryptography import utils from cryptography.hazmat.primitives import hashes from cryptography.hazmat.primitives.asymmetric import rsa @six.add_metaclass(abc.ABCMeta) class AsymmetricPadding(object): @abc.abstractproperty def name(self): """ A string naming this padding (e.g. "PSS", "PKCS1"). """ @utils.register_interface(AsymmetricPadding) class PKCS1v15(object): name = "EMSA-PKCS1-v1_5" @utils.register_interface(AsymmetricPadding) class PSS(object): MAX_LENGTH = object() name = "EMSA-PSS" def __init__(self, mgf, salt_length): self._mgf = mgf if (not isinstance(salt_length, six.integer_types) and salt_length is not self.MAX_LENGTH): raise TypeError("salt_length must be an integer.") if salt_length is not self.MAX_LENGTH and salt_length < 0: raise ValueError("salt_length must be zero or greater.") self._salt_length = salt_length @utils.register_interface(AsymmetricPadding) class OAEP(object): name = "EME-OAEP" def __init__(self, mgf, algorithm, label): if not isinstance(algorithm, hashes.HashAlgorithm): raise TypeError("Expected instance of hashes.HashAlgorithm.") self._mgf = mgf self._algorithm = algorithm self._label = label class MGF1(object): MAX_LENGTH = object() def __init__(self, algorithm): if not isinstance(algorithm, hashes.HashAlgorithm): raise TypeError("Expected instance of hashes.HashAlgorithm.") self._algorithm = algorithm def calculate_max_pss_salt_length(key, hash_algorithm): if not isinstance(key, (rsa.RSAPrivateKey, rsa.RSAPublicKey)): raise TypeError("key must be an RSA public or private key") # bit length - 1 per RFC 3447 emlen = int(math.ceil((key.key_size - 1) / 8.0)) salt_length = emlen - hash_algorithm.digest_size - 2 assert salt_length >= 0 return salt_length ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/cryptography/hazmat/primitives/asymmetric/rsa.py ================================================ # This file is dual licensed under the terms of the Apache License, Version # 2.0, and the BSD License. See the LICENSE file in the root of this repository # for complete details. from __future__ import absolute_import, division, print_function import abc try: # Only available in math in 3.5+ from math import gcd except ImportError: from fractions import gcd import six from cryptography import utils from cryptography.exceptions import UnsupportedAlgorithm, _Reasons from cryptography.hazmat.backends.interfaces import RSABackend @six.add_metaclass(abc.ABCMeta) class RSAPrivateKey(object): @abc.abstractmethod def signer(self, padding, algorithm): """ Returns an AsymmetricSignatureContext used for signing data. """ @abc.abstractmethod def decrypt(self, ciphertext, padding): """ Decrypts the provided ciphertext. """ @abc.abstractproperty def key_size(self): """ The bit length of the public modulus. """ @abc.abstractmethod def public_key(self): """ The RSAPublicKey associated with this private key. """ @abc.abstractmethod def sign(self, data, padding, algorithm): """ Signs the data. """ @six.add_metaclass(abc.ABCMeta) class RSAPrivateKeyWithSerialization(RSAPrivateKey): @abc.abstractmethod def private_numbers(self): """ Returns an RSAPrivateNumbers. """ @abc.abstractmethod def private_bytes(self, encoding, format, encryption_algorithm): """ Returns the key serialized as bytes. """ @six.add_metaclass(abc.ABCMeta) class RSAPublicKey(object): @abc.abstractmethod def verifier(self, signature, padding, algorithm): """ Returns an AsymmetricVerificationContext used for verifying signatures. """ @abc.abstractmethod def encrypt(self, plaintext, padding): """ Encrypts the given plaintext. """ @abc.abstractproperty def key_size(self): """ The bit length of the public modulus. """ @abc.abstractmethod def public_numbers(self): """ Returns an RSAPublicNumbers """ @abc.abstractmethod def public_bytes(self, encoding, format): """ Returns the key serialized as bytes. """ @abc.abstractmethod def verify(self, signature, data, padding, algorithm): """ Verifies the signature of the data. """ RSAPublicKeyWithSerialization = RSAPublicKey def generate_private_key(public_exponent, key_size, backend): if not isinstance(backend, RSABackend): raise UnsupportedAlgorithm( "Backend object does not implement RSABackend.", _Reasons.BACKEND_MISSING_INTERFACE ) _verify_rsa_parameters(public_exponent, key_size) return backend.generate_rsa_private_key(public_exponent, key_size) def _verify_rsa_parameters(public_exponent, key_size): if public_exponent < 3: raise ValueError("public_exponent must be >= 3.") if public_exponent & 1 == 0: raise ValueError("public_exponent must be odd.") if key_size < 512: raise ValueError("key_size must be at least 512-bits.") def _check_private_key_components(p, q, private_exponent, dmp1, dmq1, iqmp, public_exponent, modulus): if modulus < 3: raise ValueError("modulus must be >= 3.") if p >= modulus: raise ValueError("p must be < modulus.") if q >= modulus: raise ValueError("q must be < modulus.") if dmp1 >= modulus: raise ValueError("dmp1 must be < modulus.") if dmq1 >= modulus: raise ValueError("dmq1 must be < modulus.") if iqmp >= modulus: raise ValueError("iqmp must be < modulus.") if private_exponent >= modulus: raise ValueError("private_exponent must be < modulus.") if public_exponent < 3 or public_exponent >= modulus: raise ValueError("public_exponent must be >= 3 and < modulus.") if public_exponent & 1 == 0: raise ValueError("public_exponent must be odd.") if dmp1 & 1 == 0: raise ValueError("dmp1 must be odd.") if dmq1 & 1 == 0: raise ValueError("dmq1 must be odd.") if p * q != modulus: raise ValueError("p*q must equal modulus.") def _check_public_key_components(e, n): if n < 3: raise ValueError("n must be >= 3.") if e < 3 or e >= n: raise ValueError("e must be >= 3 and < n.") if e & 1 == 0: raise ValueError("e must be odd.") def _modinv(e, m): """ Modular Multiplicative Inverse. Returns x such that: (x*e) mod m == 1 """ x1, y1, x2, y2 = 1, 0, 0, 1 a, b = e, m while b > 0: q, r = divmod(a, b) xn, yn = x1 - q * x2, y1 - q * y2 a, b, x1, y1, x2, y2 = b, r, x2, y2, xn, yn return x1 % m def rsa_crt_iqmp(p, q): """ Compute the CRT (q ** -1) % p value from RSA primes p and q. """ return _modinv(q, p) def rsa_crt_dmp1(private_exponent, p): """ Compute the CRT private_exponent % (p - 1) value from the RSA private_exponent (d) and p. """ return private_exponent % (p - 1) def rsa_crt_dmq1(private_exponent, q): """ Compute the CRT private_exponent % (q - 1) value from the RSA private_exponent (d) and q. """ return private_exponent % (q - 1) # Controls the number of iterations rsa_recover_prime_factors will perform # to obtain the prime factors. Each iteration increments by 2 so the actual # maximum attempts is half this number. _MAX_RECOVERY_ATTEMPTS = 1000 def rsa_recover_prime_factors(n, e, d): """ Compute factors p and q from the private exponent d. We assume that n has no more than two factors. This function is adapted from code in PyCrypto. """ # See 8.2.2(i) in Handbook of Applied Cryptography. ktot = d * e - 1 # The quantity d*e-1 is a multiple of phi(n), even, # and can be represented as t*2^s. t = ktot while t % 2 == 0: t = t // 2 # Cycle through all multiplicative inverses in Zn. # The algorithm is non-deterministic, but there is a 50% chance # any candidate a leads to successful factoring. # See "Digitalized Signatures and Public Key Functions as Intractable # as Factorization", M. Rabin, 1979 spotted = False a = 2 while not spotted and a < _MAX_RECOVERY_ATTEMPTS: k = t # Cycle through all values a^{t*2^i}=a^k while k < ktot: cand = pow(a, k, n) # Check if a^k is a non-trivial root of unity (mod n) if cand != 1 and cand != (n - 1) and pow(cand, 2, n) == 1: # We have found a number such that (cand-1)(cand+1)=0 (mod n). # Either of the terms divides n. p = gcd(cand + 1, n) spotted = True break k *= 2 # This value was not any good... let's try another! a += 2 if not spotted: raise ValueError("Unable to compute factors p and q from exponent d.") # Found ! q, r = divmod(n, p) assert r == 0 p, q = sorted((p, q), reverse=True) return (p, q) class RSAPrivateNumbers(object): def __init__(self, p, q, d, dmp1, dmq1, iqmp, public_numbers): if ( not isinstance(p, six.integer_types) or not isinstance(q, six.integer_types) or not isinstance(d, six.integer_types) or not isinstance(dmp1, six.integer_types) or not isinstance(dmq1, six.integer_types) or not isinstance(iqmp, six.integer_types) ): raise TypeError( "RSAPrivateNumbers p, q, d, dmp1, dmq1, iqmp arguments must" " all be an integers." ) if not isinstance(public_numbers, RSAPublicNumbers): raise TypeError( "RSAPrivateNumbers public_numbers must be an RSAPublicNumbers" " instance." ) self._p = p self._q = q self._d = d self._dmp1 = dmp1 self._dmq1 = dmq1 self._iqmp = iqmp self._public_numbers = public_numbers p = utils.read_only_property("_p") q = utils.read_only_property("_q") d = utils.read_only_property("_d") dmp1 = utils.read_only_property("_dmp1") dmq1 = utils.read_only_property("_dmq1") iqmp = utils.read_only_property("_iqmp") public_numbers = utils.read_only_property("_public_numbers") def private_key(self, backend): return backend.load_rsa_private_numbers(self) def __eq__(self, other): if not isinstance(other, RSAPrivateNumbers): return NotImplemented return ( self.p == other.p and self.q == other.q and self.d == other.d and self.dmp1 == other.dmp1 and self.dmq1 == other.dmq1 and self.iqmp == other.iqmp and self.public_numbers == other.public_numbers ) def __ne__(self, other): return not self == other def __hash__(self): return hash(( self.p, self.q, self.d, self.dmp1, self.dmq1, self.iqmp, self.public_numbers, )) class RSAPublicNumbers(object): def __init__(self, e, n): if ( not isinstance(e, six.integer_types) or not isinstance(n, six.integer_types) ): raise TypeError("RSAPublicNumbers arguments must be integers.") self._e = e self._n = n e = utils.read_only_property("_e") n = utils.read_only_property("_n") def public_key(self, backend): return backend.load_rsa_public_numbers(self) def __repr__(self): return "".format(self) def __eq__(self, other): if not isinstance(other, RSAPublicNumbers): return NotImplemented return self.e == other.e and self.n == other.n def __ne__(self, other): return not self == other def __hash__(self): return hash((self.e, self.n)) ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/cryptography/hazmat/primitives/asymmetric/utils.py ================================================ # This file is dual licensed under the terms of the Apache License, Version # 2.0, and the BSD License. See the LICENSE file in the root of this repository # for complete details. from __future__ import absolute_import, division, print_function from cryptography import utils from cryptography.hazmat._der import ( DERReader, INTEGER, SEQUENCE, encode_der, encode_der_integer ) from cryptography.hazmat.primitives import hashes def decode_dss_signature(signature): with DERReader(signature).read_single_element(SEQUENCE) as seq: r = seq.read_element(INTEGER).as_integer() s = seq.read_element(INTEGER).as_integer() return r, s def encode_dss_signature(r, s): return encode_der( SEQUENCE, encode_der(INTEGER, encode_der_integer(r)), encode_der(INTEGER, encode_der_integer(s)), ) class Prehashed(object): def __init__(self, algorithm): if not isinstance(algorithm, hashes.HashAlgorithm): raise TypeError("Expected instance of HashAlgorithm.") self._algorithm = algorithm self._digest_size = algorithm.digest_size digest_size = utils.read_only_property("_digest_size") ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/cryptography/hazmat/primitives/asymmetric/x25519.py ================================================ # This file is dual licensed under the terms of the Apache License, Version # 2.0, and the BSD License. See the LICENSE file in the root of this repository # for complete details. from __future__ import absolute_import, division, print_function import abc import six from cryptography.exceptions import UnsupportedAlgorithm, _Reasons @six.add_metaclass(abc.ABCMeta) class X25519PublicKey(object): @classmethod def from_public_bytes(cls, data): from cryptography.hazmat.backends.openssl.backend import backend if not backend.x25519_supported(): raise UnsupportedAlgorithm( "X25519 is not supported by this version of OpenSSL.", _Reasons.UNSUPPORTED_EXCHANGE_ALGORITHM ) return backend.x25519_load_public_bytes(data) @abc.abstractmethod def public_bytes(self, encoding=None, format=None): """ The serialized bytes of the public key. """ @six.add_metaclass(abc.ABCMeta) class X25519PrivateKey(object): @classmethod def generate(cls): from cryptography.hazmat.backends.openssl.backend import backend if not backend.x25519_supported(): raise UnsupportedAlgorithm( "X25519 is not supported by this version of OpenSSL.", _Reasons.UNSUPPORTED_EXCHANGE_ALGORITHM ) return backend.x25519_generate_key() @classmethod def from_private_bytes(cls, data): from cryptography.hazmat.backends.openssl.backend import backend if not backend.x25519_supported(): raise UnsupportedAlgorithm( "X25519 is not supported by this version of OpenSSL.", _Reasons.UNSUPPORTED_EXCHANGE_ALGORITHM ) return backend.x25519_load_private_bytes(data) @abc.abstractmethod def public_key(self): """ The serialized bytes of the public key. """ @abc.abstractmethod def private_bytes(self, encoding, format, encryption_algorithm): """ The serialized bytes of the private key. """ @abc.abstractmethod def exchange(self, peer_public_key): """ Performs a key exchange operation using the provided peer's public key. """ ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/cryptography/hazmat/primitives/asymmetric/x448.py ================================================ # This file is dual licensed under the terms of the Apache License, Version # 2.0, and the BSD License. See the LICENSE file in the root of this repository # for complete details. from __future__ import absolute_import, division, print_function import abc import six from cryptography.exceptions import UnsupportedAlgorithm, _Reasons @six.add_metaclass(abc.ABCMeta) class X448PublicKey(object): @classmethod def from_public_bytes(cls, data): from cryptography.hazmat.backends.openssl.backend import backend if not backend.x448_supported(): raise UnsupportedAlgorithm( "X448 is not supported by this version of OpenSSL.", _Reasons.UNSUPPORTED_EXCHANGE_ALGORITHM ) return backend.x448_load_public_bytes(data) @abc.abstractmethod def public_bytes(self, encoding, format): """ The serialized bytes of the public key. """ @six.add_metaclass(abc.ABCMeta) class X448PrivateKey(object): @classmethod def generate(cls): from cryptography.hazmat.backends.openssl.backend import backend if not backend.x448_supported(): raise UnsupportedAlgorithm( "X448 is not supported by this version of OpenSSL.", _Reasons.UNSUPPORTED_EXCHANGE_ALGORITHM ) return backend.x448_generate_key() @classmethod def from_private_bytes(cls, data): from cryptography.hazmat.backends.openssl.backend import backend if not backend.x448_supported(): raise UnsupportedAlgorithm( "X448 is not supported by this version of OpenSSL.", _Reasons.UNSUPPORTED_EXCHANGE_ALGORITHM ) return backend.x448_load_private_bytes(data) @abc.abstractmethod def public_key(self): """ The serialized bytes of the public key. """ @abc.abstractmethod def private_bytes(self, encoding, format, encryption_algorithm): """ The serialized bytes of the private key. """ @abc.abstractmethod def exchange(self, peer_public_key): """ Performs a key exchange operation using the provided peer's public key. """ ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/cryptography/hazmat/primitives/ciphers/__init__.py ================================================ # This file is dual licensed under the terms of the Apache License, Version # 2.0, and the BSD License. See the LICENSE file in the root of this repository # for complete details. from __future__ import absolute_import, division, print_function from cryptography.hazmat.primitives.ciphers.base import ( AEADCipherContext, AEADDecryptionContext, AEADEncryptionContext, BlockCipherAlgorithm, Cipher, CipherAlgorithm, CipherContext ) __all__ = [ "Cipher", "CipherAlgorithm", "BlockCipherAlgorithm", "CipherContext", "AEADCipherContext", "AEADDecryptionContext", "AEADEncryptionContext", ] ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/cryptography/hazmat/primitives/ciphers/aead.py ================================================ # This file is dual licensed under the terms of the Apache License, Version # 2.0, and the BSD License. See the LICENSE file in the root of this repository # for complete details. from __future__ import absolute_import, division, print_function import os from cryptography import exceptions, utils from cryptography.hazmat.backends.openssl import aead from cryptography.hazmat.backends.openssl.backend import backend class ChaCha20Poly1305(object): _MAX_SIZE = 2 ** 32 def __init__(self, key): if not backend.aead_cipher_supported(self): raise exceptions.UnsupportedAlgorithm( "ChaCha20Poly1305 is not supported by this version of OpenSSL", exceptions._Reasons.UNSUPPORTED_CIPHER ) utils._check_byteslike("key", key) if len(key) != 32: raise ValueError("ChaCha20Poly1305 key must be 32 bytes.") self._key = key @classmethod def generate_key(cls): return os.urandom(32) def encrypt(self, nonce, data, associated_data): if associated_data is None: associated_data = b"" if len(data) > self._MAX_SIZE or len(associated_data) > self._MAX_SIZE: # This is OverflowError to match what cffi would raise raise OverflowError( "Data or associated data too long. Max 2**32 bytes" ) self._check_params(nonce, data, associated_data) return aead._encrypt( backend, self, nonce, data, associated_data, 16 ) def decrypt(self, nonce, data, associated_data): if associated_data is None: associated_data = b"" self._check_params(nonce, data, associated_data) return aead._decrypt( backend, self, nonce, data, associated_data, 16 ) def _check_params(self, nonce, data, associated_data): utils._check_byteslike("nonce", nonce) utils._check_bytes("data", data) utils._check_bytes("associated_data", associated_data) if len(nonce) != 12: raise ValueError("Nonce must be 12 bytes") class AESCCM(object): _MAX_SIZE = 2 ** 32 def __init__(self, key, tag_length=16): utils._check_byteslike("key", key) if len(key) not in (16, 24, 32): raise ValueError("AESCCM key must be 128, 192, or 256 bits.") self._key = key if not isinstance(tag_length, int): raise TypeError("tag_length must be an integer") if tag_length not in (4, 6, 8, 10, 12, 14, 16): raise ValueError("Invalid tag_length") self._tag_length = tag_length if not backend.aead_cipher_supported(self): raise exceptions.UnsupportedAlgorithm( "AESCCM is not supported by this version of OpenSSL", exceptions._Reasons.UNSUPPORTED_CIPHER ) @classmethod def generate_key(cls, bit_length): if not isinstance(bit_length, int): raise TypeError("bit_length must be an integer") if bit_length not in (128, 192, 256): raise ValueError("bit_length must be 128, 192, or 256") return os.urandom(bit_length // 8) def encrypt(self, nonce, data, associated_data): if associated_data is None: associated_data = b"" if len(data) > self._MAX_SIZE or len(associated_data) > self._MAX_SIZE: # This is OverflowError to match what cffi would raise raise OverflowError( "Data or associated data too long. Max 2**32 bytes" ) self._check_params(nonce, data, associated_data) self._validate_lengths(nonce, len(data)) return aead._encrypt( backend, self, nonce, data, associated_data, self._tag_length ) def decrypt(self, nonce, data, associated_data): if associated_data is None: associated_data = b"" self._check_params(nonce, data, associated_data) return aead._decrypt( backend, self, nonce, data, associated_data, self._tag_length ) def _validate_lengths(self, nonce, data_len): # For information about computing this, see # https://tools.ietf.org/html/rfc3610#section-2.1 l_val = 15 - len(nonce) if 2 ** (8 * l_val) < data_len: raise ValueError("Nonce too long for data") def _check_params(self, nonce, data, associated_data): utils._check_byteslike("nonce", nonce) utils._check_bytes("data", data) utils._check_bytes("associated_data", associated_data) if not 7 <= len(nonce) <= 13: raise ValueError("Nonce must be between 7 and 13 bytes") class AESGCM(object): _MAX_SIZE = 2 ** 32 def __init__(self, key): utils._check_byteslike("key", key) if len(key) not in (16, 24, 32): raise ValueError("AESGCM key must be 128, 192, or 256 bits.") self._key = key @classmethod def generate_key(cls, bit_length): if not isinstance(bit_length, int): raise TypeError("bit_length must be an integer") if bit_length not in (128, 192, 256): raise ValueError("bit_length must be 128, 192, or 256") return os.urandom(bit_length // 8) def encrypt(self, nonce, data, associated_data): if associated_data is None: associated_data = b"" if len(data) > self._MAX_SIZE or len(associated_data) > self._MAX_SIZE: # This is OverflowError to match what cffi would raise raise OverflowError( "Data or associated data too long. Max 2**32 bytes" ) self._check_params(nonce, data, associated_data) return aead._encrypt( backend, self, nonce, data, associated_data, 16 ) def decrypt(self, nonce, data, associated_data): if associated_data is None: associated_data = b"" self._check_params(nonce, data, associated_data) return aead._decrypt( backend, self, nonce, data, associated_data, 16 ) def _check_params(self, nonce, data, associated_data): utils._check_byteslike("nonce", nonce) utils._check_bytes("data", data) utils._check_bytes("associated_data", associated_data) if len(nonce) == 0: raise ValueError("Nonce must be at least 1 byte") ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/cryptography/hazmat/primitives/ciphers/algorithms.py ================================================ # This file is dual licensed under the terms of the Apache License, Version # 2.0, and the BSD License. See the LICENSE file in the root of this repository # for complete details. from __future__ import absolute_import, division, print_function from cryptography import utils from cryptography.hazmat.primitives.ciphers import ( BlockCipherAlgorithm, CipherAlgorithm ) from cryptography.hazmat.primitives.ciphers.modes import ModeWithNonce def _verify_key_size(algorithm, key): # Verify that the key is instance of bytes utils._check_byteslike("key", key) # Verify that the key size matches the expected key size if len(key) * 8 not in algorithm.key_sizes: raise ValueError("Invalid key size ({}) for {}.".format( len(key) * 8, algorithm.name )) return key @utils.register_interface(BlockCipherAlgorithm) @utils.register_interface(CipherAlgorithm) class AES(object): name = "AES" block_size = 128 # 512 added to support AES-256-XTS, which uses 512-bit keys key_sizes = frozenset([128, 192, 256, 512]) def __init__(self, key): self.key = _verify_key_size(self, key) @property def key_size(self): return len(self.key) * 8 @utils.register_interface(BlockCipherAlgorithm) @utils.register_interface(CipherAlgorithm) class Camellia(object): name = "camellia" block_size = 128 key_sizes = frozenset([128, 192, 256]) def __init__(self, key): self.key = _verify_key_size(self, key) @property def key_size(self): return len(self.key) * 8 @utils.register_interface(BlockCipherAlgorithm) @utils.register_interface(CipherAlgorithm) class TripleDES(object): name = "3DES" block_size = 64 key_sizes = frozenset([64, 128, 192]) def __init__(self, key): if len(key) == 8: key += key + key elif len(key) == 16: key += key[:8] self.key = _verify_key_size(self, key) @property def key_size(self): return len(self.key) * 8 @utils.register_interface(BlockCipherAlgorithm) @utils.register_interface(CipherAlgorithm) class Blowfish(object): name = "Blowfish" block_size = 64 key_sizes = frozenset(range(32, 449, 8)) def __init__(self, key): self.key = _verify_key_size(self, key) @property def key_size(self): return len(self.key) * 8 @utils.register_interface(BlockCipherAlgorithm) @utils.register_interface(CipherAlgorithm) class CAST5(object): name = "CAST5" block_size = 64 key_sizes = frozenset(range(40, 129, 8)) def __init__(self, key): self.key = _verify_key_size(self, key) @property def key_size(self): return len(self.key) * 8 @utils.register_interface(CipherAlgorithm) class ARC4(object): name = "RC4" key_sizes = frozenset([40, 56, 64, 80, 128, 160, 192, 256]) def __init__(self, key): self.key = _verify_key_size(self, key) @property def key_size(self): return len(self.key) * 8 @utils.register_interface(CipherAlgorithm) class IDEA(object): name = "IDEA" block_size = 64 key_sizes = frozenset([128]) def __init__(self, key): self.key = _verify_key_size(self, key) @property def key_size(self): return len(self.key) * 8 @utils.register_interface(BlockCipherAlgorithm) @utils.register_interface(CipherAlgorithm) class SEED(object): name = "SEED" block_size = 128 key_sizes = frozenset([128]) def __init__(self, key): self.key = _verify_key_size(self, key) @property def key_size(self): return len(self.key) * 8 @utils.register_interface(CipherAlgorithm) @utils.register_interface(ModeWithNonce) class ChaCha20(object): name = "ChaCha20" key_sizes = frozenset([256]) def __init__(self, key, nonce): self.key = _verify_key_size(self, key) utils._check_byteslike("nonce", nonce) if len(nonce) != 16: raise ValueError("nonce must be 128-bits (16 bytes)") self._nonce = nonce nonce = utils.read_only_property("_nonce") @property def key_size(self): return len(self.key) * 8 ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/cryptography/hazmat/primitives/ciphers/base.py ================================================ # This file is dual licensed under the terms of the Apache License, Version # 2.0, and the BSD License. See the LICENSE file in the root of this repository # for complete details. from __future__ import absolute_import, division, print_function import abc import six from cryptography import utils from cryptography.exceptions import ( AlreadyFinalized, AlreadyUpdated, NotYetFinalized, UnsupportedAlgorithm, _Reasons ) from cryptography.hazmat.backends.interfaces import CipherBackend from cryptography.hazmat.primitives.ciphers import modes @six.add_metaclass(abc.ABCMeta) class CipherAlgorithm(object): @abc.abstractproperty def name(self): """ A string naming this mode (e.g. "AES", "Camellia"). """ @abc.abstractproperty def key_size(self): """ The size of the key being used as an integer in bits (e.g. 128, 256). """ @six.add_metaclass(abc.ABCMeta) class BlockCipherAlgorithm(object): @abc.abstractproperty def block_size(self): """ The size of a block as an integer in bits (e.g. 64, 128). """ @six.add_metaclass(abc.ABCMeta) class CipherContext(object): @abc.abstractmethod def update(self, data): """ Processes the provided bytes through the cipher and returns the results as bytes. """ @abc.abstractmethod def update_into(self, data, buf): """ Processes the provided bytes and writes the resulting data into the provided buffer. Returns the number of bytes written. """ @abc.abstractmethod def finalize(self): """ Returns the results of processing the final block as bytes. """ @six.add_metaclass(abc.ABCMeta) class AEADCipherContext(object): @abc.abstractmethod def authenticate_additional_data(self, data): """ Authenticates the provided bytes. """ @six.add_metaclass(abc.ABCMeta) class AEADDecryptionContext(object): @abc.abstractmethod def finalize_with_tag(self, tag): """ Returns the results of processing the final block as bytes and allows delayed passing of the authentication tag. """ @six.add_metaclass(abc.ABCMeta) class AEADEncryptionContext(object): @abc.abstractproperty def tag(self): """ Returns tag bytes. This is only available after encryption is finalized. """ class Cipher(object): def __init__(self, algorithm, mode, backend): if not isinstance(backend, CipherBackend): raise UnsupportedAlgorithm( "Backend object does not implement CipherBackend.", _Reasons.BACKEND_MISSING_INTERFACE ) if not isinstance(algorithm, CipherAlgorithm): raise TypeError("Expected interface of CipherAlgorithm.") if mode is not None: mode.validate_for_algorithm(algorithm) self.algorithm = algorithm self.mode = mode self._backend = backend def encryptor(self): if isinstance(self.mode, modes.ModeWithAuthenticationTag): if self.mode.tag is not None: raise ValueError( "Authentication tag must be None when encrypting." ) ctx = self._backend.create_symmetric_encryption_ctx( self.algorithm, self.mode ) return self._wrap_ctx(ctx, encrypt=True) def decryptor(self): ctx = self._backend.create_symmetric_decryption_ctx( self.algorithm, self.mode ) return self._wrap_ctx(ctx, encrypt=False) def _wrap_ctx(self, ctx, encrypt): if isinstance(self.mode, modes.ModeWithAuthenticationTag): if encrypt: return _AEADEncryptionContext(ctx) else: return _AEADCipherContext(ctx) else: return _CipherContext(ctx) @utils.register_interface(CipherContext) class _CipherContext(object): def __init__(self, ctx): self._ctx = ctx def update(self, data): if self._ctx is None: raise AlreadyFinalized("Context was already finalized.") return self._ctx.update(data) def update_into(self, data, buf): if self._ctx is None: raise AlreadyFinalized("Context was already finalized.") return self._ctx.update_into(data, buf) def finalize(self): if self._ctx is None: raise AlreadyFinalized("Context was already finalized.") data = self._ctx.finalize() self._ctx = None return data @utils.register_interface(AEADCipherContext) @utils.register_interface(CipherContext) @utils.register_interface(AEADDecryptionContext) class _AEADCipherContext(object): def __init__(self, ctx): self._ctx = ctx self._bytes_processed = 0 self._aad_bytes_processed = 0 self._tag = None self._updated = False def _check_limit(self, data_size): if self._ctx is None: raise AlreadyFinalized("Context was already finalized.") self._updated = True self._bytes_processed += data_size if self._bytes_processed > self._ctx._mode._MAX_ENCRYPTED_BYTES: raise ValueError( "{} has a maximum encrypted byte limit of {}".format( self._ctx._mode.name, self._ctx._mode._MAX_ENCRYPTED_BYTES ) ) def update(self, data): self._check_limit(len(data)) return self._ctx.update(data) def update_into(self, data, buf): self._check_limit(len(data)) return self._ctx.update_into(data, buf) def finalize(self): if self._ctx is None: raise AlreadyFinalized("Context was already finalized.") data = self._ctx.finalize() self._tag = self._ctx.tag self._ctx = None return data def finalize_with_tag(self, tag): if self._ctx is None: raise AlreadyFinalized("Context was already finalized.") data = self._ctx.finalize_with_tag(tag) self._tag = self._ctx.tag self._ctx = None return data def authenticate_additional_data(self, data): if self._ctx is None: raise AlreadyFinalized("Context was already finalized.") if self._updated: raise AlreadyUpdated("Update has been called on this context.") self._aad_bytes_processed += len(data) if self._aad_bytes_processed > self._ctx._mode._MAX_AAD_BYTES: raise ValueError( "{} has a maximum AAD byte limit of {}".format( self._ctx._mode.name, self._ctx._mode._MAX_AAD_BYTES ) ) self._ctx.authenticate_additional_data(data) @utils.register_interface(AEADEncryptionContext) class _AEADEncryptionContext(_AEADCipherContext): @property def tag(self): if self._ctx is not None: raise NotYetFinalized("You must finalize encryption before " "getting the tag.") return self._tag ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/cryptography/hazmat/primitives/ciphers/modes.py ================================================ # This file is dual licensed under the terms of the Apache License, Version # 2.0, and the BSD License. See the LICENSE file in the root of this repository # for complete details. from __future__ import absolute_import, division, print_function import abc import six from cryptography import utils @six.add_metaclass(abc.ABCMeta) class Mode(object): @abc.abstractproperty def name(self): """ A string naming this mode (e.g. "ECB", "CBC"). """ @abc.abstractmethod def validate_for_algorithm(self, algorithm): """ Checks that all the necessary invariants of this (mode, algorithm) combination are met. """ @six.add_metaclass(abc.ABCMeta) class ModeWithInitializationVector(object): @abc.abstractproperty def initialization_vector(self): """ The value of the initialization vector for this mode as bytes. """ @six.add_metaclass(abc.ABCMeta) class ModeWithTweak(object): @abc.abstractproperty def tweak(self): """ The value of the tweak for this mode as bytes. """ @six.add_metaclass(abc.ABCMeta) class ModeWithNonce(object): @abc.abstractproperty def nonce(self): """ The value of the nonce for this mode as bytes. """ @six.add_metaclass(abc.ABCMeta) class ModeWithAuthenticationTag(object): @abc.abstractproperty def tag(self): """ The value of the tag supplied to the constructor of this mode. """ def _check_aes_key_length(self, algorithm): if algorithm.key_size > 256 and algorithm.name == "AES": raise ValueError( "Only 128, 192, and 256 bit keys are allowed for this AES mode" ) def _check_iv_length(self, algorithm): if len(self.initialization_vector) * 8 != algorithm.block_size: raise ValueError("Invalid IV size ({}) for {}.".format( len(self.initialization_vector), self.name )) def _check_iv_and_key_length(self, algorithm): _check_aes_key_length(self, algorithm) _check_iv_length(self, algorithm) @utils.register_interface(Mode) @utils.register_interface(ModeWithInitializationVector) class CBC(object): name = "CBC" def __init__(self, initialization_vector): utils._check_byteslike("initialization_vector", initialization_vector) self._initialization_vector = initialization_vector initialization_vector = utils.read_only_property("_initialization_vector") validate_for_algorithm = _check_iv_and_key_length @utils.register_interface(Mode) @utils.register_interface(ModeWithTweak) class XTS(object): name = "XTS" def __init__(self, tweak): utils._check_byteslike("tweak", tweak) if len(tweak) != 16: raise ValueError("tweak must be 128-bits (16 bytes)") self._tweak = tweak tweak = utils.read_only_property("_tweak") def validate_for_algorithm(self, algorithm): if algorithm.key_size not in (256, 512): raise ValueError( "The XTS specification requires a 256-bit key for AES-128-XTS" " and 512-bit key for AES-256-XTS" ) @utils.register_interface(Mode) class ECB(object): name = "ECB" validate_for_algorithm = _check_aes_key_length @utils.register_interface(Mode) @utils.register_interface(ModeWithInitializationVector) class OFB(object): name = "OFB" def __init__(self, initialization_vector): utils._check_byteslike("initialization_vector", initialization_vector) self._initialization_vector = initialization_vector initialization_vector = utils.read_only_property("_initialization_vector") validate_for_algorithm = _check_iv_and_key_length @utils.register_interface(Mode) @utils.register_interface(ModeWithInitializationVector) class CFB(object): name = "CFB" def __init__(self, initialization_vector): utils._check_byteslike("initialization_vector", initialization_vector) self._initialization_vector = initialization_vector initialization_vector = utils.read_only_property("_initialization_vector") validate_for_algorithm = _check_iv_and_key_length @utils.register_interface(Mode) @utils.register_interface(ModeWithInitializationVector) class CFB8(object): name = "CFB8" def __init__(self, initialization_vector): utils._check_byteslike("initialization_vector", initialization_vector) self._initialization_vector = initialization_vector initialization_vector = utils.read_only_property("_initialization_vector") validate_for_algorithm = _check_iv_and_key_length @utils.register_interface(Mode) @utils.register_interface(ModeWithNonce) class CTR(object): name = "CTR" def __init__(self, nonce): utils._check_byteslike("nonce", nonce) self._nonce = nonce nonce = utils.read_only_property("_nonce") def validate_for_algorithm(self, algorithm): _check_aes_key_length(self, algorithm) if len(self.nonce) * 8 != algorithm.block_size: raise ValueError("Invalid nonce size ({}) for {}.".format( len(self.nonce), self.name )) @utils.register_interface(Mode) @utils.register_interface(ModeWithInitializationVector) @utils.register_interface(ModeWithAuthenticationTag) class GCM(object): name = "GCM" _MAX_ENCRYPTED_BYTES = (2 ** 39 - 256) // 8 _MAX_AAD_BYTES = (2 ** 64) // 8 def __init__(self, initialization_vector, tag=None, min_tag_length=16): # len(initialization_vector) must in [1, 2 ** 64), but it's impossible # to actually construct a bytes object that large, so we don't check # for it utils._check_byteslike("initialization_vector", initialization_vector) if len(initialization_vector) == 0: raise ValueError("initialization_vector must be at least 1 byte") self._initialization_vector = initialization_vector if tag is not None: utils._check_bytes("tag", tag) if min_tag_length < 4: raise ValueError("min_tag_length must be >= 4") if len(tag) < min_tag_length: raise ValueError( "Authentication tag must be {} bytes or longer.".format( min_tag_length) ) self._tag = tag self._min_tag_length = min_tag_length tag = utils.read_only_property("_tag") initialization_vector = utils.read_only_property("_initialization_vector") def validate_for_algorithm(self, algorithm): _check_aes_key_length(self, algorithm) ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/cryptography/hazmat/primitives/cmac.py ================================================ # This file is dual licensed under the terms of the Apache License, Version # 2.0, and the BSD License. See the LICENSE file in the root of this repository # for complete details. from __future__ import absolute_import, division, print_function from cryptography import utils from cryptography.exceptions import ( AlreadyFinalized, UnsupportedAlgorithm, _Reasons ) from cryptography.hazmat.backends.interfaces import CMACBackend from cryptography.hazmat.primitives import ciphers class CMAC(object): def __init__(self, algorithm, backend, ctx=None): if not isinstance(backend, CMACBackend): raise UnsupportedAlgorithm( "Backend object does not implement CMACBackend.", _Reasons.BACKEND_MISSING_INTERFACE ) if not isinstance(algorithm, ciphers.BlockCipherAlgorithm): raise TypeError( "Expected instance of BlockCipherAlgorithm." ) self._algorithm = algorithm self._backend = backend if ctx is None: self._ctx = self._backend.create_cmac_ctx(self._algorithm) else: self._ctx = ctx def update(self, data): if self._ctx is None: raise AlreadyFinalized("Context was already finalized.") utils._check_bytes("data", data) self._ctx.update(data) def finalize(self): if self._ctx is None: raise AlreadyFinalized("Context was already finalized.") digest = self._ctx.finalize() self._ctx = None return digest def verify(self, signature): utils._check_bytes("signature", signature) if self._ctx is None: raise AlreadyFinalized("Context was already finalized.") ctx, self._ctx = self._ctx, None ctx.verify(signature) def copy(self): if self._ctx is None: raise AlreadyFinalized("Context was already finalized.") return CMAC( self._algorithm, backend=self._backend, ctx=self._ctx.copy() ) ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/cryptography/hazmat/primitives/constant_time.py ================================================ # This file is dual licensed under the terms of the Apache License, Version # 2.0, and the BSD License. See the LICENSE file in the root of this repository # for complete details. from __future__ import absolute_import, division, print_function import hmac import warnings from cryptography import utils from cryptography.hazmat.bindings._constant_time import lib if hasattr(hmac, "compare_digest"): def bytes_eq(a, b): if not isinstance(a, bytes) or not isinstance(b, bytes): raise TypeError("a and b must be bytes.") return hmac.compare_digest(a, b) else: warnings.warn( "Support for your Python version is deprecated. The next version of " "cryptography will remove support. Please upgrade to a release " "(2.7.7+) that supports hmac.compare_digest as soon as possible.", utils.PersistentlyDeprecated2018, ) def bytes_eq(a, b): if not isinstance(a, bytes) or not isinstance(b, bytes): raise TypeError("a and b must be bytes.") return lib.Cryptography_constant_time_bytes_eq( a, len(a), b, len(b) ) == 1 ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/cryptography/hazmat/primitives/hashes.py ================================================ # This file is dual licensed under the terms of the Apache License, Version # 2.0, and the BSD License. See the LICENSE file in the root of this repository # for complete details. from __future__ import absolute_import, division, print_function import abc import six from cryptography import utils from cryptography.exceptions import ( AlreadyFinalized, UnsupportedAlgorithm, _Reasons ) from cryptography.hazmat.backends.interfaces import HashBackend @six.add_metaclass(abc.ABCMeta) class HashAlgorithm(object): @abc.abstractproperty def name(self): """ A string naming this algorithm (e.g. "sha256", "md5"). """ @abc.abstractproperty def digest_size(self): """ The size of the resulting digest in bytes. """ @six.add_metaclass(abc.ABCMeta) class HashContext(object): @abc.abstractproperty def algorithm(self): """ A HashAlgorithm that will be used by this context. """ @abc.abstractmethod def update(self, data): """ Processes the provided bytes through the hash. """ @abc.abstractmethod def finalize(self): """ Finalizes the hash context and returns the hash digest as bytes. """ @abc.abstractmethod def copy(self): """ Return a HashContext that is a copy of the current context. """ @six.add_metaclass(abc.ABCMeta) class ExtendableOutputFunction(object): """ An interface for extendable output functions. """ @utils.register_interface(HashContext) class Hash(object): def __init__(self, algorithm, backend, ctx=None): if not isinstance(backend, HashBackend): raise UnsupportedAlgorithm( "Backend object does not implement HashBackend.", _Reasons.BACKEND_MISSING_INTERFACE ) if not isinstance(algorithm, HashAlgorithm): raise TypeError("Expected instance of hashes.HashAlgorithm.") self._algorithm = algorithm self._backend = backend if ctx is None: self._ctx = self._backend.create_hash_ctx(self.algorithm) else: self._ctx = ctx algorithm = utils.read_only_property("_algorithm") def update(self, data): if self._ctx is None: raise AlreadyFinalized("Context was already finalized.") utils._check_byteslike("data", data) self._ctx.update(data) def copy(self): if self._ctx is None: raise AlreadyFinalized("Context was already finalized.") return Hash( self.algorithm, backend=self._backend, ctx=self._ctx.copy() ) def finalize(self): if self._ctx is None: raise AlreadyFinalized("Context was already finalized.") digest = self._ctx.finalize() self._ctx = None return digest @utils.register_interface(HashAlgorithm) class SHA1(object): name = "sha1" digest_size = 20 block_size = 64 @utils.register_interface(HashAlgorithm) class SHA512_224(object): # noqa: N801 name = "sha512-224" digest_size = 28 block_size = 128 @utils.register_interface(HashAlgorithm) class SHA512_256(object): # noqa: N801 name = "sha512-256" digest_size = 32 block_size = 128 @utils.register_interface(HashAlgorithm) class SHA224(object): name = "sha224" digest_size = 28 block_size = 64 @utils.register_interface(HashAlgorithm) class SHA256(object): name = "sha256" digest_size = 32 block_size = 64 @utils.register_interface(HashAlgorithm) class SHA384(object): name = "sha384" digest_size = 48 block_size = 128 @utils.register_interface(HashAlgorithm) class SHA512(object): name = "sha512" digest_size = 64 block_size = 128 @utils.register_interface(HashAlgorithm) class SHA3_224(object): # noqa: N801 name = "sha3-224" digest_size = 28 @utils.register_interface(HashAlgorithm) class SHA3_256(object): # noqa: N801 name = "sha3-256" digest_size = 32 @utils.register_interface(HashAlgorithm) class SHA3_384(object): # noqa: N801 name = "sha3-384" digest_size = 48 @utils.register_interface(HashAlgorithm) class SHA3_512(object): # noqa: N801 name = "sha3-512" digest_size = 64 @utils.register_interface(HashAlgorithm) @utils.register_interface(ExtendableOutputFunction) class SHAKE128(object): name = "shake128" def __init__(self, digest_size): if not isinstance(digest_size, six.integer_types): raise TypeError("digest_size must be an integer") if digest_size < 1: raise ValueError("digest_size must be a positive integer") self._digest_size = digest_size digest_size = utils.read_only_property("_digest_size") @utils.register_interface(HashAlgorithm) @utils.register_interface(ExtendableOutputFunction) class SHAKE256(object): name = "shake256" def __init__(self, digest_size): if not isinstance(digest_size, six.integer_types): raise TypeError("digest_size must be an integer") if digest_size < 1: raise ValueError("digest_size must be a positive integer") self._digest_size = digest_size digest_size = utils.read_only_property("_digest_size") @utils.register_interface(HashAlgorithm) class MD5(object): name = "md5" digest_size = 16 block_size = 64 @utils.register_interface(HashAlgorithm) class BLAKE2b(object): name = "blake2b" _max_digest_size = 64 _min_digest_size = 1 block_size = 128 def __init__(self, digest_size): if digest_size != 64: raise ValueError("Digest size must be 64") self._digest_size = digest_size digest_size = utils.read_only_property("_digest_size") @utils.register_interface(HashAlgorithm) class BLAKE2s(object): name = "blake2s" block_size = 64 _max_digest_size = 32 _min_digest_size = 1 def __init__(self, digest_size): if digest_size != 32: raise ValueError("Digest size must be 32") self._digest_size = digest_size digest_size = utils.read_only_property("_digest_size") ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/cryptography/hazmat/primitives/hmac.py ================================================ # This file is dual licensed under the terms of the Apache License, Version # 2.0, and the BSD License. See the LICENSE file in the root of this repository # for complete details. from __future__ import absolute_import, division, print_function from cryptography import utils from cryptography.exceptions import ( AlreadyFinalized, UnsupportedAlgorithm, _Reasons ) from cryptography.hazmat.backends.interfaces import HMACBackend from cryptography.hazmat.primitives import hashes @utils.register_interface(hashes.HashContext) class HMAC(object): def __init__(self, key, algorithm, backend, ctx=None): if not isinstance(backend, HMACBackend): raise UnsupportedAlgorithm( "Backend object does not implement HMACBackend.", _Reasons.BACKEND_MISSING_INTERFACE ) if not isinstance(algorithm, hashes.HashAlgorithm): raise TypeError("Expected instance of hashes.HashAlgorithm.") self._algorithm = algorithm self._backend = backend self._key = key if ctx is None: self._ctx = self._backend.create_hmac_ctx(key, self.algorithm) else: self._ctx = ctx algorithm = utils.read_only_property("_algorithm") def update(self, data): if self._ctx is None: raise AlreadyFinalized("Context was already finalized.") utils._check_byteslike("data", data) self._ctx.update(data) def copy(self): if self._ctx is None: raise AlreadyFinalized("Context was already finalized.") return HMAC( self._key, self.algorithm, backend=self._backend, ctx=self._ctx.copy() ) def finalize(self): if self._ctx is None: raise AlreadyFinalized("Context was already finalized.") digest = self._ctx.finalize() self._ctx = None return digest def verify(self, signature): utils._check_bytes("signature", signature) if self._ctx is None: raise AlreadyFinalized("Context was already finalized.") ctx, self._ctx = self._ctx, None ctx.verify(signature) ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/cryptography/hazmat/primitives/kdf/__init__.py ================================================ # This file is dual licensed under the terms of the Apache License, Version # 2.0, and the BSD License. See the LICENSE file in the root of this repository # for complete details. from __future__ import absolute_import, division, print_function import abc import six @six.add_metaclass(abc.ABCMeta) class KeyDerivationFunction(object): @abc.abstractmethod def derive(self, key_material): """ Deterministically generates and returns a new key based on the existing key material. """ @abc.abstractmethod def verify(self, key_material, expected_key): """ Checks whether the key generated by the key material matches the expected derived key. Raises an exception if they do not match. """ ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/cryptography/hazmat/primitives/kdf/concatkdf.py ================================================ # This file is dual licensed under the terms of the Apache License, Version # 2.0, and the BSD License. See the LICENSE file in the root of this repository # for complete details. from __future__ import absolute_import, division, print_function import struct from cryptography import utils from cryptography.exceptions import ( AlreadyFinalized, InvalidKey, UnsupportedAlgorithm, _Reasons ) from cryptography.hazmat.backends.interfaces import HMACBackend from cryptography.hazmat.backends.interfaces import HashBackend from cryptography.hazmat.primitives import constant_time, hashes, hmac from cryptography.hazmat.primitives.kdf import KeyDerivationFunction def _int_to_u32be(n): return struct.pack('>I', n) def _common_args_checks(algorithm, length, otherinfo): max_length = algorithm.digest_size * (2 ** 32 - 1) if length > max_length: raise ValueError( "Can not derive keys larger than {} bits.".format( max_length )) if otherinfo is not None: utils._check_bytes("otherinfo", otherinfo) def _concatkdf_derive(key_material, length, auxfn, otherinfo): utils._check_byteslike("key_material", key_material) output = [b""] outlen = 0 counter = 1 while (length > outlen): h = auxfn() h.update(_int_to_u32be(counter)) h.update(key_material) h.update(otherinfo) output.append(h.finalize()) outlen += len(output[-1]) counter += 1 return b"".join(output)[:length] @utils.register_interface(KeyDerivationFunction) class ConcatKDFHash(object): def __init__(self, algorithm, length, otherinfo, backend): _common_args_checks(algorithm, length, otherinfo) self._algorithm = algorithm self._length = length self._otherinfo = otherinfo if self._otherinfo is None: self._otherinfo = b"" if not isinstance(backend, HashBackend): raise UnsupportedAlgorithm( "Backend object does not implement HashBackend.", _Reasons.BACKEND_MISSING_INTERFACE ) self._backend = backend self._used = False def _hash(self): return hashes.Hash(self._algorithm, self._backend) def derive(self, key_material): if self._used: raise AlreadyFinalized self._used = True return _concatkdf_derive(key_material, self._length, self._hash, self._otherinfo) def verify(self, key_material, expected_key): if not constant_time.bytes_eq(self.derive(key_material), expected_key): raise InvalidKey @utils.register_interface(KeyDerivationFunction) class ConcatKDFHMAC(object): def __init__(self, algorithm, length, salt, otherinfo, backend): _common_args_checks(algorithm, length, otherinfo) self._algorithm = algorithm self._length = length self._otherinfo = otherinfo if self._otherinfo is None: self._otherinfo = b"" if salt is None: salt = b"\x00" * algorithm.block_size else: utils._check_bytes("salt", salt) self._salt = salt if not isinstance(backend, HMACBackend): raise UnsupportedAlgorithm( "Backend object does not implement HMACBackend.", _Reasons.BACKEND_MISSING_INTERFACE ) self._backend = backend self._used = False def _hmac(self): return hmac.HMAC(self._salt, self._algorithm, self._backend) def derive(self, key_material): if self._used: raise AlreadyFinalized self._used = True return _concatkdf_derive(key_material, self._length, self._hmac, self._otherinfo) def verify(self, key_material, expected_key): if not constant_time.bytes_eq(self.derive(key_material), expected_key): raise InvalidKey ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/cryptography/hazmat/primitives/kdf/hkdf.py ================================================ # This file is dual licensed under the terms of the Apache License, Version # 2.0, and the BSD License. See the LICENSE file in the root of this repository # for complete details. from __future__ import absolute_import, division, print_function import six from cryptography import utils from cryptography.exceptions import ( AlreadyFinalized, InvalidKey, UnsupportedAlgorithm, _Reasons ) from cryptography.hazmat.backends.interfaces import HMACBackend from cryptography.hazmat.primitives import constant_time, hmac from cryptography.hazmat.primitives.kdf import KeyDerivationFunction @utils.register_interface(KeyDerivationFunction) class HKDF(object): def __init__(self, algorithm, length, salt, info, backend): if not isinstance(backend, HMACBackend): raise UnsupportedAlgorithm( "Backend object does not implement HMACBackend.", _Reasons.BACKEND_MISSING_INTERFACE ) self._algorithm = algorithm if salt is None: salt = b"\x00" * self._algorithm.digest_size else: utils._check_bytes("salt", salt) self._salt = salt self._backend = backend self._hkdf_expand = HKDFExpand(self._algorithm, length, info, backend) def _extract(self, key_material): h = hmac.HMAC(self._salt, self._algorithm, backend=self._backend) h.update(key_material) return h.finalize() def derive(self, key_material): utils._check_byteslike("key_material", key_material) return self._hkdf_expand.derive(self._extract(key_material)) def verify(self, key_material, expected_key): if not constant_time.bytes_eq(self.derive(key_material), expected_key): raise InvalidKey @utils.register_interface(KeyDerivationFunction) class HKDFExpand(object): def __init__(self, algorithm, length, info, backend): if not isinstance(backend, HMACBackend): raise UnsupportedAlgorithm( "Backend object does not implement HMACBackend.", _Reasons.BACKEND_MISSING_INTERFACE ) self._algorithm = algorithm self._backend = backend max_length = 255 * algorithm.digest_size if length > max_length: raise ValueError( "Can not derive keys larger than {} octets.".format( max_length )) self._length = length if info is None: info = b"" else: utils._check_bytes("info", info) self._info = info self._used = False def _expand(self, key_material): output = [b""] counter = 1 while self._algorithm.digest_size * (len(output) - 1) < self._length: h = hmac.HMAC(key_material, self._algorithm, backend=self._backend) h.update(output[-1]) h.update(self._info) h.update(six.int2byte(counter)) output.append(h.finalize()) counter += 1 return b"".join(output)[:self._length] def derive(self, key_material): utils._check_byteslike("key_material", key_material) if self._used: raise AlreadyFinalized self._used = True return self._expand(key_material) def verify(self, key_material, expected_key): if not constant_time.bytes_eq(self.derive(key_material), expected_key): raise InvalidKey ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/cryptography/hazmat/primitives/kdf/kbkdf.py ================================================ # This file is dual licensed under the terms of the Apache License, Version # 2.0, and the BSD License. See the LICENSE file in the root of this repository # for complete details. from __future__ import absolute_import, division, print_function from enum import Enum from six.moves import range from cryptography import utils from cryptography.exceptions import ( AlreadyFinalized, InvalidKey, UnsupportedAlgorithm, _Reasons ) from cryptography.hazmat.backends.interfaces import HMACBackend from cryptography.hazmat.primitives import constant_time, hashes, hmac from cryptography.hazmat.primitives.kdf import KeyDerivationFunction class Mode(Enum): CounterMode = "ctr" class CounterLocation(Enum): BeforeFixed = "before_fixed" AfterFixed = "after_fixed" @utils.register_interface(KeyDerivationFunction) class KBKDFHMAC(object): def __init__(self, algorithm, mode, length, rlen, llen, location, label, context, fixed, backend): if not isinstance(backend, HMACBackend): raise UnsupportedAlgorithm( "Backend object does not implement HMACBackend.", _Reasons.BACKEND_MISSING_INTERFACE ) if not isinstance(algorithm, hashes.HashAlgorithm): raise UnsupportedAlgorithm( "Algorithm supplied is not a supported hash algorithm.", _Reasons.UNSUPPORTED_HASH ) if not backend.hmac_supported(algorithm): raise UnsupportedAlgorithm( "Algorithm supplied is not a supported hmac algorithm.", _Reasons.UNSUPPORTED_HASH ) if not isinstance(mode, Mode): raise TypeError("mode must be of type Mode") if not isinstance(location, CounterLocation): raise TypeError("location must be of type CounterLocation") if (label or context) and fixed: raise ValueError("When supplying fixed data, " "label and context are ignored.") if rlen is None or not self._valid_byte_length(rlen): raise ValueError("rlen must be between 1 and 4") if llen is None and fixed is None: raise ValueError("Please specify an llen") if llen is not None and not isinstance(llen, int): raise TypeError("llen must be an integer") if label is None: label = b'' if context is None: context = b'' utils._check_bytes("label", label) utils._check_bytes("context", context) self._algorithm = algorithm self._mode = mode self._length = length self._rlen = rlen self._llen = llen self._location = location self._label = label self._context = context self._backend = backend self._used = False self._fixed_data = fixed def _valid_byte_length(self, value): if not isinstance(value, int): raise TypeError('value must be of type int') value_bin = utils.int_to_bytes(1, value) if not 1 <= len(value_bin) <= 4: return False return True def derive(self, key_material): if self._used: raise AlreadyFinalized utils._check_byteslike("key_material", key_material) self._used = True # inverse floor division (equivalent to ceiling) rounds = -(-self._length // self._algorithm.digest_size) output = [b''] # For counter mode, the number of iterations shall not be # larger than 2^r-1, where r <= 32 is the binary length of the counter # This ensures that the counter values used as an input to the # PRF will not repeat during a particular call to the KDF function. r_bin = utils.int_to_bytes(1, self._rlen) if rounds > pow(2, len(r_bin) * 8) - 1: raise ValueError('There are too many iterations.') for i in range(1, rounds + 1): h = hmac.HMAC(key_material, self._algorithm, backend=self._backend) counter = utils.int_to_bytes(i, self._rlen) if self._location == CounterLocation.BeforeFixed: h.update(counter) h.update(self._generate_fixed_input()) if self._location == CounterLocation.AfterFixed: h.update(counter) output.append(h.finalize()) return b''.join(output)[:self._length] def _generate_fixed_input(self): if self._fixed_data and isinstance(self._fixed_data, bytes): return self._fixed_data l_val = utils.int_to_bytes(self._length * 8, self._llen) return b"".join([self._label, b"\x00", self._context, l_val]) def verify(self, key_material, expected_key): if not constant_time.bytes_eq(self.derive(key_material), expected_key): raise InvalidKey ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/cryptography/hazmat/primitives/kdf/pbkdf2.py ================================================ # This file is dual licensed under the terms of the Apache License, Version # 2.0, and the BSD License. See the LICENSE file in the root of this repository # for complete details. from __future__ import absolute_import, division, print_function from cryptography import utils from cryptography.exceptions import ( AlreadyFinalized, InvalidKey, UnsupportedAlgorithm, _Reasons ) from cryptography.hazmat.backends.interfaces import PBKDF2HMACBackend from cryptography.hazmat.primitives import constant_time from cryptography.hazmat.primitives.kdf import KeyDerivationFunction @utils.register_interface(KeyDerivationFunction) class PBKDF2HMAC(object): def __init__(self, algorithm, length, salt, iterations, backend): if not isinstance(backend, PBKDF2HMACBackend): raise UnsupportedAlgorithm( "Backend object does not implement PBKDF2HMACBackend.", _Reasons.BACKEND_MISSING_INTERFACE ) if not backend.pbkdf2_hmac_supported(algorithm): raise UnsupportedAlgorithm( "{} is not supported for PBKDF2 by this backend.".format( algorithm.name), _Reasons.UNSUPPORTED_HASH ) self._used = False self._algorithm = algorithm self._length = length utils._check_bytes("salt", salt) self._salt = salt self._iterations = iterations self._backend = backend def derive(self, key_material): if self._used: raise AlreadyFinalized("PBKDF2 instances can only be used once.") self._used = True utils._check_byteslike("key_material", key_material) return self._backend.derive_pbkdf2_hmac( self._algorithm, self._length, self._salt, self._iterations, key_material ) def verify(self, key_material, expected_key): derived_key = self.derive(key_material) if not constant_time.bytes_eq(derived_key, expected_key): raise InvalidKey("Keys do not match.") ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/cryptography/hazmat/primitives/kdf/scrypt.py ================================================ # This file is dual licensed under the terms of the Apache License, Version # 2.0, and the BSD License. See the LICENSE file in the root of this repository # for complete details. from __future__ import absolute_import, division, print_function import sys from cryptography import utils from cryptography.exceptions import ( AlreadyFinalized, InvalidKey, UnsupportedAlgorithm, _Reasons ) from cryptography.hazmat.backends.interfaces import ScryptBackend from cryptography.hazmat.primitives import constant_time from cryptography.hazmat.primitives.kdf import KeyDerivationFunction # This is used by the scrypt tests to skip tests that require more memory # than the MEM_LIMIT _MEM_LIMIT = sys.maxsize // 2 @utils.register_interface(KeyDerivationFunction) class Scrypt(object): def __init__(self, salt, length, n, r, p, backend): if not isinstance(backend, ScryptBackend): raise UnsupportedAlgorithm( "Backend object does not implement ScryptBackend.", _Reasons.BACKEND_MISSING_INTERFACE ) self._length = length utils._check_bytes("salt", salt) if n < 2 or (n & (n - 1)) != 0: raise ValueError("n must be greater than 1 and be a power of 2.") if r < 1: raise ValueError("r must be greater than or equal to 1.") if p < 1: raise ValueError("p must be greater than or equal to 1.") self._used = False self._salt = salt self._n = n self._r = r self._p = p self._backend = backend def derive(self, key_material): if self._used: raise AlreadyFinalized("Scrypt instances can only be used once.") self._used = True utils._check_byteslike("key_material", key_material) return self._backend.derive_scrypt( key_material, self._salt, self._length, self._n, self._r, self._p ) def verify(self, key_material, expected_key): derived_key = self.derive(key_material) if not constant_time.bytes_eq(derived_key, expected_key): raise InvalidKey("Keys do not match.") ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/cryptography/hazmat/primitives/kdf/x963kdf.py ================================================ # This file is dual licensed under the terms of the Apache License, Version # 2.0, and the BSD License. See the LICENSE file in the root of this repository # for complete details. from __future__ import absolute_import, division, print_function import struct from cryptography import utils from cryptography.exceptions import ( AlreadyFinalized, InvalidKey, UnsupportedAlgorithm, _Reasons ) from cryptography.hazmat.backends.interfaces import HashBackend from cryptography.hazmat.primitives import constant_time, hashes from cryptography.hazmat.primitives.kdf import KeyDerivationFunction def _int_to_u32be(n): return struct.pack('>I', n) @utils.register_interface(KeyDerivationFunction) class X963KDF(object): def __init__(self, algorithm, length, sharedinfo, backend): max_len = algorithm.digest_size * (2 ** 32 - 1) if length > max_len: raise ValueError( "Can not derive keys larger than {} bits.".format(max_len)) if sharedinfo is not None: utils._check_bytes("sharedinfo", sharedinfo) self._algorithm = algorithm self._length = length self._sharedinfo = sharedinfo if not isinstance(backend, HashBackend): raise UnsupportedAlgorithm( "Backend object does not implement HashBackend.", _Reasons.BACKEND_MISSING_INTERFACE ) self._backend = backend self._used = False def derive(self, key_material): if self._used: raise AlreadyFinalized self._used = True utils._check_byteslike("key_material", key_material) output = [b""] outlen = 0 counter = 1 while self._length > outlen: h = hashes.Hash(self._algorithm, self._backend) h.update(key_material) h.update(_int_to_u32be(counter)) if self._sharedinfo is not None: h.update(self._sharedinfo) output.append(h.finalize()) outlen += len(output[-1]) counter += 1 return b"".join(output)[:self._length] def verify(self, key_material, expected_key): if not constant_time.bytes_eq(self.derive(key_material), expected_key): raise InvalidKey ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/cryptography/hazmat/primitives/keywrap.py ================================================ # This file is dual licensed under the terms of the Apache License, Version # 2.0, and the BSD License. See the LICENSE file in the root of this repository # for complete details. from __future__ import absolute_import, division, print_function import struct from cryptography.hazmat.primitives.ciphers import Cipher from cryptography.hazmat.primitives.ciphers.algorithms import AES from cryptography.hazmat.primitives.ciphers.modes import ECB from cryptography.hazmat.primitives.constant_time import bytes_eq def _wrap_core(wrapping_key, a, r, backend): # RFC 3394 Key Wrap - 2.2.1 (index method) encryptor = Cipher(AES(wrapping_key), ECB(), backend).encryptor() n = len(r) for j in range(6): for i in range(n): # every encryption operation is a discrete 16 byte chunk (because # AES has a 128-bit block size) and since we're using ECB it is # safe to reuse the encryptor for the entire operation b = encryptor.update(a + r[i]) # pack/unpack are safe as these are always 64-bit chunks a = struct.pack( ">Q", struct.unpack(">Q", b[:8])[0] ^ ((n * j) + i + 1) ) r[i] = b[-8:] assert encryptor.finalize() == b"" return a + b"".join(r) def aes_key_wrap(wrapping_key, key_to_wrap, backend): if len(wrapping_key) not in [16, 24, 32]: raise ValueError("The wrapping key must be a valid AES key length") if len(key_to_wrap) < 16: raise ValueError("The key to wrap must be at least 16 bytes") if len(key_to_wrap) % 8 != 0: raise ValueError("The key to wrap must be a multiple of 8 bytes") a = b"\xa6\xa6\xa6\xa6\xa6\xa6\xa6\xa6" r = [key_to_wrap[i:i + 8] for i in range(0, len(key_to_wrap), 8)] return _wrap_core(wrapping_key, a, r, backend) def _unwrap_core(wrapping_key, a, r, backend): # Implement RFC 3394 Key Unwrap - 2.2.2 (index method) decryptor = Cipher(AES(wrapping_key), ECB(), backend).decryptor() n = len(r) for j in reversed(range(6)): for i in reversed(range(n)): # pack/unpack are safe as these are always 64-bit chunks atr = struct.pack( ">Q", struct.unpack(">Q", a)[0] ^ ((n * j) + i + 1) ) + r[i] # every decryption operation is a discrete 16 byte chunk so # it is safe to reuse the decryptor for the entire operation b = decryptor.update(atr) a = b[:8] r[i] = b[-8:] assert decryptor.finalize() == b"" return a, r def aes_key_wrap_with_padding(wrapping_key, key_to_wrap, backend): if len(wrapping_key) not in [16, 24, 32]: raise ValueError("The wrapping key must be a valid AES key length") aiv = b"\xA6\x59\x59\xA6" + struct.pack(">i", len(key_to_wrap)) # pad the key to wrap if necessary pad = (8 - (len(key_to_wrap) % 8)) % 8 key_to_wrap = key_to_wrap + b"\x00" * pad if len(key_to_wrap) == 8: # RFC 5649 - 4.1 - exactly 8 octets after padding encryptor = Cipher(AES(wrapping_key), ECB(), backend).encryptor() b = encryptor.update(aiv + key_to_wrap) assert encryptor.finalize() == b"" return b else: r = [key_to_wrap[i:i + 8] for i in range(0, len(key_to_wrap), 8)] return _wrap_core(wrapping_key, aiv, r, backend) def aes_key_unwrap_with_padding(wrapping_key, wrapped_key, backend): if len(wrapped_key) < 16: raise InvalidUnwrap("Must be at least 16 bytes") if len(wrapping_key) not in [16, 24, 32]: raise ValueError("The wrapping key must be a valid AES key length") if len(wrapped_key) == 16: # RFC 5649 - 4.2 - exactly two 64-bit blocks decryptor = Cipher(AES(wrapping_key), ECB(), backend).decryptor() b = decryptor.update(wrapped_key) assert decryptor.finalize() == b"" a = b[:8] data = b[8:] n = 1 else: r = [wrapped_key[i:i + 8] for i in range(0, len(wrapped_key), 8)] encrypted_aiv = r.pop(0) n = len(r) a, r = _unwrap_core(wrapping_key, encrypted_aiv, r, backend) data = b"".join(r) # 1) Check that MSB(32,A) = A65959A6. # 2) Check that 8*(n-1) < LSB(32,A) <= 8*n. If so, let # MLI = LSB(32,A). # 3) Let b = (8*n)-MLI, and then check that the rightmost b octets of # the output data are zero. (mli,) = struct.unpack(">I", a[4:]) b = (8 * n) - mli if ( not bytes_eq(a[:4], b"\xa6\x59\x59\xa6") or not 8 * (n - 1) < mli <= 8 * n or ( b != 0 and not bytes_eq(data[-b:], b"\x00" * b) ) ): raise InvalidUnwrap() if b == 0: return data else: return data[:-b] def aes_key_unwrap(wrapping_key, wrapped_key, backend): if len(wrapped_key) < 24: raise InvalidUnwrap("Must be at least 24 bytes") if len(wrapped_key) % 8 != 0: raise InvalidUnwrap("The wrapped key must be a multiple of 8 bytes") if len(wrapping_key) not in [16, 24, 32]: raise ValueError("The wrapping key must be a valid AES key length") aiv = b"\xa6\xa6\xa6\xa6\xa6\xa6\xa6\xa6" r = [wrapped_key[i:i + 8] for i in range(0, len(wrapped_key), 8)] a = r.pop(0) a, r = _unwrap_core(wrapping_key, a, r, backend) if not bytes_eq(a, aiv): raise InvalidUnwrap() return b"".join(r) class InvalidUnwrap(Exception): pass ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/cryptography/hazmat/primitives/padding.py ================================================ # This file is dual licensed under the terms of the Apache License, Version # 2.0, and the BSD License. See the LICENSE file in the root of this repository # for complete details. from __future__ import absolute_import, division, print_function import abc import six from cryptography import utils from cryptography.exceptions import AlreadyFinalized from cryptography.hazmat.bindings._padding import lib @six.add_metaclass(abc.ABCMeta) class PaddingContext(object): @abc.abstractmethod def update(self, data): """ Pads the provided bytes and returns any available data as bytes. """ @abc.abstractmethod def finalize(self): """ Finalize the padding, returns bytes. """ def _byte_padding_check(block_size): if not (0 <= block_size <= 2040): raise ValueError("block_size must be in range(0, 2041).") if block_size % 8 != 0: raise ValueError("block_size must be a multiple of 8.") def _byte_padding_update(buffer_, data, block_size): if buffer_ is None: raise AlreadyFinalized("Context was already finalized.") utils._check_bytes("data", data) buffer_ += data finished_blocks = len(buffer_) // (block_size // 8) result = buffer_[:finished_blocks * (block_size // 8)] buffer_ = buffer_[finished_blocks * (block_size // 8):] return buffer_, result def _byte_padding_pad(buffer_, block_size, paddingfn): if buffer_ is None: raise AlreadyFinalized("Context was already finalized.") pad_size = block_size // 8 - len(buffer_) return buffer_ + paddingfn(pad_size) def _byte_unpadding_update(buffer_, data, block_size): if buffer_ is None: raise AlreadyFinalized("Context was already finalized.") utils._check_bytes("data", data) buffer_ += data finished_blocks = max(len(buffer_) // (block_size // 8) - 1, 0) result = buffer_[:finished_blocks * (block_size // 8)] buffer_ = buffer_[finished_blocks * (block_size // 8):] return buffer_, result def _byte_unpadding_check(buffer_, block_size, checkfn): if buffer_ is None: raise AlreadyFinalized("Context was already finalized.") if len(buffer_) != block_size // 8: raise ValueError("Invalid padding bytes.") valid = checkfn(buffer_, block_size // 8) if not valid: raise ValueError("Invalid padding bytes.") pad_size = six.indexbytes(buffer_, -1) return buffer_[:-pad_size] class PKCS7(object): def __init__(self, block_size): _byte_padding_check(block_size) self.block_size = block_size def padder(self): return _PKCS7PaddingContext(self.block_size) def unpadder(self): return _PKCS7UnpaddingContext(self.block_size) @utils.register_interface(PaddingContext) class _PKCS7PaddingContext(object): def __init__(self, block_size): self.block_size = block_size # TODO: more copies than necessary, we should use zero-buffer (#193) self._buffer = b"" def update(self, data): self._buffer, result = _byte_padding_update( self._buffer, data, self.block_size) return result def _padding(self, size): return six.int2byte(size) * size def finalize(self): result = _byte_padding_pad( self._buffer, self.block_size, self._padding) self._buffer = None return result @utils.register_interface(PaddingContext) class _PKCS7UnpaddingContext(object): def __init__(self, block_size): self.block_size = block_size # TODO: more copies than necessary, we should use zero-buffer (#193) self._buffer = b"" def update(self, data): self._buffer, result = _byte_unpadding_update( self._buffer, data, self.block_size) return result def finalize(self): result = _byte_unpadding_check( self._buffer, self.block_size, lib.Cryptography_check_pkcs7_padding) self._buffer = None return result class ANSIX923(object): def __init__(self, block_size): _byte_padding_check(block_size) self.block_size = block_size def padder(self): return _ANSIX923PaddingContext(self.block_size) def unpadder(self): return _ANSIX923UnpaddingContext(self.block_size) @utils.register_interface(PaddingContext) class _ANSIX923PaddingContext(object): def __init__(self, block_size): self.block_size = block_size # TODO: more copies than necessary, we should use zero-buffer (#193) self._buffer = b"" def update(self, data): self._buffer, result = _byte_padding_update( self._buffer, data, self.block_size) return result def _padding(self, size): return six.int2byte(0) * (size - 1) + six.int2byte(size) def finalize(self): result = _byte_padding_pad( self._buffer, self.block_size, self._padding) self._buffer = None return result @utils.register_interface(PaddingContext) class _ANSIX923UnpaddingContext(object): def __init__(self, block_size): self.block_size = block_size # TODO: more copies than necessary, we should use zero-buffer (#193) self._buffer = b"" def update(self, data): self._buffer, result = _byte_unpadding_update( self._buffer, data, self.block_size) return result def finalize(self): result = _byte_unpadding_check( self._buffer, self.block_size, lib.Cryptography_check_ansix923_padding) self._buffer = None return result ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/cryptography/hazmat/primitives/poly1305.py ================================================ # This file is dual licensed under the terms of the Apache License, Version # 2.0, and the BSD License. See the LICENSE file in the root of this repository # for complete details. from __future__ import absolute_import, division, print_function from cryptography import utils from cryptography.exceptions import ( AlreadyFinalized, UnsupportedAlgorithm, _Reasons ) class Poly1305(object): def __init__(self, key): from cryptography.hazmat.backends.openssl.backend import backend if not backend.poly1305_supported(): raise UnsupportedAlgorithm( "poly1305 is not supported by this version of OpenSSL.", _Reasons.UNSUPPORTED_MAC ) self._ctx = backend.create_poly1305_ctx(key) def update(self, data): if self._ctx is None: raise AlreadyFinalized("Context was already finalized.") utils._check_byteslike("data", data) self._ctx.update(data) def finalize(self): if self._ctx is None: raise AlreadyFinalized("Context was already finalized.") mac = self._ctx.finalize() self._ctx = None return mac def verify(self, tag): utils._check_bytes("tag", tag) if self._ctx is None: raise AlreadyFinalized("Context was already finalized.") ctx, self._ctx = self._ctx, None ctx.verify(tag) @classmethod def generate_tag(cls, key, data): p = Poly1305(key) p.update(data) return p.finalize() @classmethod def verify_tag(cls, key, data, tag): p = Poly1305(key) p.update(data) p.verify(tag) ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/cryptography/hazmat/primitives/serialization/__init__.py ================================================ # This file is dual licensed under the terms of the Apache License, Version # 2.0, and the BSD License. See the LICENSE file in the root of this repository # for complete details. from __future__ import absolute_import, division, print_function from cryptography.hazmat.primitives.serialization.base import ( BestAvailableEncryption, Encoding, KeySerializationEncryption, NoEncryption, ParameterFormat, PrivateFormat, PublicFormat, load_der_parameters, load_der_private_key, load_der_public_key, load_pem_parameters, load_pem_private_key, load_pem_public_key, ) from cryptography.hazmat.primitives.serialization.ssh import ( load_ssh_public_key ) _PEM_DER = (Encoding.PEM, Encoding.DER) __all__ = [ "load_der_parameters", "load_der_private_key", "load_der_public_key", "load_pem_parameters", "load_pem_private_key", "load_pem_public_key", "load_ssh_public_key", "Encoding", "PrivateFormat", "PublicFormat", "ParameterFormat", "KeySerializationEncryption", "BestAvailableEncryption", "NoEncryption", ] ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/cryptography/hazmat/primitives/serialization/base.py ================================================ # This file is dual licensed under the terms of the Apache License, Version # 2.0, and the BSD License. See the LICENSE file in the root of this repository # for complete details. from __future__ import absolute_import, division, print_function import abc from enum import Enum import six from cryptography import utils def load_pem_private_key(data, password, backend): return backend.load_pem_private_key(data, password) def load_pem_public_key(data, backend): return backend.load_pem_public_key(data) def load_pem_parameters(data, backend): return backend.load_pem_parameters(data) def load_der_private_key(data, password, backend): return backend.load_der_private_key(data, password) def load_der_public_key(data, backend): return backend.load_der_public_key(data) def load_der_parameters(data, backend): return backend.load_der_parameters(data) class Encoding(Enum): PEM = "PEM" DER = "DER" OpenSSH = "OpenSSH" Raw = "Raw" X962 = "ANSI X9.62" class PrivateFormat(Enum): PKCS8 = "PKCS8" TraditionalOpenSSL = "TraditionalOpenSSL" Raw = "Raw" class PublicFormat(Enum): SubjectPublicKeyInfo = "X.509 subjectPublicKeyInfo with PKCS#1" PKCS1 = "Raw PKCS#1" OpenSSH = "OpenSSH" Raw = "Raw" CompressedPoint = "X9.62 Compressed Point" UncompressedPoint = "X9.62 Uncompressed Point" class ParameterFormat(Enum): PKCS3 = "PKCS3" @six.add_metaclass(abc.ABCMeta) class KeySerializationEncryption(object): pass @utils.register_interface(KeySerializationEncryption) class BestAvailableEncryption(object): def __init__(self, password): if not isinstance(password, bytes) or len(password) == 0: raise ValueError("Password must be 1 or more bytes.") self.password = password @utils.register_interface(KeySerializationEncryption) class NoEncryption(object): pass ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/cryptography/hazmat/primitives/serialization/pkcs12.py ================================================ # This file is dual licensed under the terms of the Apache License, Version # 2.0, and the BSD License. See the LICENSE file in the root of this repository # for complete details. from __future__ import absolute_import, division, print_function def load_key_and_certificates(data, password, backend): return backend.load_key_and_certificates_from_pkcs12(data, password) ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/cryptography/hazmat/primitives/serialization/ssh.py ================================================ # This file is dual licensed under the terms of the Apache License, Version # 2.0, and the BSD License. See the LICENSE file in the root of this repository # for complete details. from __future__ import absolute_import, division, print_function import base64 import struct import six from cryptography import utils from cryptography.exceptions import UnsupportedAlgorithm from cryptography.hazmat.primitives.asymmetric import dsa, ec, ed25519, rsa def load_ssh_public_key(data, backend): key_parts = data.split(b' ', 2) if len(key_parts) < 2: raise ValueError( 'Key is not in the proper format or contains extra data.') key_type = key_parts[0] if key_type == b'ssh-rsa': loader = _load_ssh_rsa_public_key elif key_type == b'ssh-dss': loader = _load_ssh_dss_public_key elif key_type in [ b'ecdsa-sha2-nistp256', b'ecdsa-sha2-nistp384', b'ecdsa-sha2-nistp521', ]: loader = _load_ssh_ecdsa_public_key elif key_type == b'ssh-ed25519': loader = _load_ssh_ed25519_public_key else: raise UnsupportedAlgorithm('Key type is not supported.') key_body = key_parts[1] try: decoded_data = base64.b64decode(key_body) except TypeError: raise ValueError('Key is not in the proper format.') inner_key_type, rest = _ssh_read_next_string(decoded_data) if inner_key_type != key_type: raise ValueError( 'Key header and key body contain different key type values.' ) return loader(key_type, rest, backend) def _load_ssh_rsa_public_key(key_type, decoded_data, backend): e, rest = _ssh_read_next_mpint(decoded_data) n, rest = _ssh_read_next_mpint(rest) if rest: raise ValueError('Key body contains extra bytes.') return rsa.RSAPublicNumbers(e, n).public_key(backend) def _load_ssh_dss_public_key(key_type, decoded_data, backend): p, rest = _ssh_read_next_mpint(decoded_data) q, rest = _ssh_read_next_mpint(rest) g, rest = _ssh_read_next_mpint(rest) y, rest = _ssh_read_next_mpint(rest) if rest: raise ValueError('Key body contains extra bytes.') parameter_numbers = dsa.DSAParameterNumbers(p, q, g) public_numbers = dsa.DSAPublicNumbers(y, parameter_numbers) return public_numbers.public_key(backend) def _load_ssh_ecdsa_public_key(expected_key_type, decoded_data, backend): curve_name, rest = _ssh_read_next_string(decoded_data) data, rest = _ssh_read_next_string(rest) if expected_key_type != b"ecdsa-sha2-" + curve_name: raise ValueError( 'Key header and key body contain different key type values.' ) if rest: raise ValueError('Key body contains extra bytes.') curve = { b"nistp256": ec.SECP256R1, b"nistp384": ec.SECP384R1, b"nistp521": ec.SECP521R1, }[curve_name]() if six.indexbytes(data, 0) != 4: raise NotImplementedError( "Compressed elliptic curve points are not supported" ) return ec.EllipticCurvePublicKey.from_encoded_point(curve, data) def _load_ssh_ed25519_public_key(expected_key_type, decoded_data, backend): data, rest = _ssh_read_next_string(decoded_data) if rest: raise ValueError('Key body contains extra bytes.') return ed25519.Ed25519PublicKey.from_public_bytes(data) def _ssh_read_next_string(data): """ Retrieves the next RFC 4251 string value from the data. While the RFC calls these strings, in Python they are bytes objects. """ if len(data) < 4: raise ValueError("Key is not in the proper format") str_len, = struct.unpack('>I', data[:4]) if len(data) < str_len + 4: raise ValueError("Key is not in the proper format") return data[4:4 + str_len], data[4 + str_len:] def _ssh_read_next_mpint(data): """ Reads the next mpint from the data. Currently, all mpints are interpreted as unsigned. """ mpint_data, rest = _ssh_read_next_string(data) return ( utils.int_from_bytes(mpint_data, byteorder='big', signed=False), rest ) def _ssh_write_string(data): return struct.pack(">I", len(data)) + data def _ssh_write_mpint(value): data = utils.int_to_bytes(value) if six.indexbytes(data, 0) & 0x80: data = b"\x00" + data return _ssh_write_string(data) ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/cryptography/hazmat/primitives/twofactor/__init__.py ================================================ # This file is dual licensed under the terms of the Apache License, Version # 2.0, and the BSD License. See the LICENSE file in the root of this repository # for complete details. from __future__ import absolute_import, division, print_function class InvalidToken(Exception): pass ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/cryptography/hazmat/primitives/twofactor/hotp.py ================================================ # This file is dual licensed under the terms of the Apache License, Version # 2.0, and the BSD License. See the LICENSE file in the root of this repository # for complete details. from __future__ import absolute_import, division, print_function import struct import six from cryptography.exceptions import ( UnsupportedAlgorithm, _Reasons ) from cryptography.hazmat.backends.interfaces import HMACBackend from cryptography.hazmat.primitives import constant_time, hmac from cryptography.hazmat.primitives.hashes import SHA1, SHA256, SHA512 from cryptography.hazmat.primitives.twofactor import InvalidToken from cryptography.hazmat.primitives.twofactor.utils import _generate_uri class HOTP(object): def __init__(self, key, length, algorithm, backend, enforce_key_length=True): if not isinstance(backend, HMACBackend): raise UnsupportedAlgorithm( "Backend object does not implement HMACBackend.", _Reasons.BACKEND_MISSING_INTERFACE ) if len(key) < 16 and enforce_key_length is True: raise ValueError("Key length has to be at least 128 bits.") if not isinstance(length, six.integer_types): raise TypeError("Length parameter must be an integer type.") if length < 6 or length > 8: raise ValueError("Length of HOTP has to be between 6 to 8.") if not isinstance(algorithm, (SHA1, SHA256, SHA512)): raise TypeError("Algorithm must be SHA1, SHA256 or SHA512.") self._key = key self._length = length self._algorithm = algorithm self._backend = backend def generate(self, counter): truncated_value = self._dynamic_truncate(counter) hotp = truncated_value % (10 ** self._length) return "{0:0{1}}".format(hotp, self._length).encode() def verify(self, hotp, counter): if not constant_time.bytes_eq(self.generate(counter), hotp): raise InvalidToken("Supplied HOTP value does not match.") def _dynamic_truncate(self, counter): ctx = hmac.HMAC(self._key, self._algorithm, self._backend) ctx.update(struct.pack(">Q", counter)) hmac_value = ctx.finalize() offset = six.indexbytes(hmac_value, len(hmac_value) - 1) & 0b1111 p = hmac_value[offset:offset + 4] return struct.unpack(">I", p)[0] & 0x7fffffff def get_provisioning_uri(self, account_name, counter, issuer): return _generate_uri(self, "hotp", account_name, issuer, [ ("counter", int(counter)), ]) ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/cryptography/hazmat/primitives/twofactor/totp.py ================================================ # This file is dual licensed under the terms of the Apache License, Version # 2.0, and the BSD License. See the LICENSE file in the root of this repository # for complete details. from __future__ import absolute_import, division, print_function from cryptography.exceptions import ( UnsupportedAlgorithm, _Reasons ) from cryptography.hazmat.backends.interfaces import HMACBackend from cryptography.hazmat.primitives import constant_time from cryptography.hazmat.primitives.twofactor import InvalidToken from cryptography.hazmat.primitives.twofactor.hotp import HOTP from cryptography.hazmat.primitives.twofactor.utils import _generate_uri class TOTP(object): def __init__(self, key, length, algorithm, time_step, backend, enforce_key_length=True): if not isinstance(backend, HMACBackend): raise UnsupportedAlgorithm( "Backend object does not implement HMACBackend.", _Reasons.BACKEND_MISSING_INTERFACE ) self._time_step = time_step self._hotp = HOTP(key, length, algorithm, backend, enforce_key_length) def generate(self, time): counter = int(time / self._time_step) return self._hotp.generate(counter) def verify(self, totp, time): if not constant_time.bytes_eq(self.generate(time), totp): raise InvalidToken("Supplied TOTP value does not match.") def get_provisioning_uri(self, account_name, issuer): return _generate_uri(self._hotp, "totp", account_name, issuer, [ ("period", int(self._time_step)), ]) ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/cryptography/hazmat/primitives/twofactor/utils.py ================================================ # This file is dual licensed under the terms of the Apache License, Version # 2.0, and the BSD License. See the LICENSE file in the root of this repository # for complete details. from __future__ import absolute_import, division, print_function import base64 from six.moves.urllib.parse import quote, urlencode def _generate_uri(hotp, type_name, account_name, issuer, extra_parameters): parameters = [ ("digits", hotp._length), ("secret", base64.b32encode(hotp._key)), ("algorithm", hotp._algorithm.name.upper()), ] if issuer is not None: parameters.append(("issuer", issuer)) parameters.extend(extra_parameters) uriparts = { "type": type_name, "label": ("%s:%s" % (quote(issuer), quote(account_name)) if issuer else quote(account_name)), "parameters": urlencode(parameters), } return "otpauth://{type}/{label}?{parameters}".format(**uriparts) ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/cryptography/utils.py ================================================ # This file is dual licensed under the terms of the Apache License, Version # 2.0, and the BSD License. See the LICENSE file in the root of this repository # for complete details. from __future__ import absolute_import, division, print_function import abc import binascii import inspect import sys import warnings # We use a UserWarning subclass, instead of DeprecationWarning, because CPython # decided deprecation warnings should be invisble by default. class CryptographyDeprecationWarning(UserWarning): pass # Several APIs were deprecated with no specific end-of-life date because of the # ubiquity of their use. They should not be removed until we agree on when that # cycle ends. PersistentlyDeprecated2017 = CryptographyDeprecationWarning PersistentlyDeprecated2018 = CryptographyDeprecationWarning DeprecatedIn25 = CryptographyDeprecationWarning DeprecatedIn27 = CryptographyDeprecationWarning def _check_bytes(name, value): if not isinstance(value, bytes): raise TypeError("{} must be bytes".format(name)) def _check_byteslike(name, value): try: memoryview(value) except TypeError: raise TypeError("{} must be bytes-like".format(name)) def read_only_property(name): return property(lambda self: getattr(self, name)) def register_interface(iface): def register_decorator(klass): verify_interface(iface, klass) iface.register(klass) return klass return register_decorator def register_interface_if(predicate, iface): def register_decorator(klass): if predicate: verify_interface(iface, klass) iface.register(klass) return klass return register_decorator if hasattr(int, "from_bytes"): int_from_bytes = int.from_bytes else: def int_from_bytes(data, byteorder, signed=False): assert byteorder == 'big' assert not signed return int(binascii.hexlify(data), 16) if hasattr(int, "to_bytes"): def int_to_bytes(integer, length=None): return integer.to_bytes( length or (integer.bit_length() + 7) // 8 or 1, 'big' ) else: def int_to_bytes(integer, length=None): hex_string = '%x' % integer if length is None: n = len(hex_string) else: n = length * 2 return binascii.unhexlify(hex_string.zfill(n + (n & 1))) class InterfaceNotImplemented(Exception): pass if hasattr(inspect, "signature"): signature = inspect.signature else: signature = inspect.getargspec def verify_interface(iface, klass): for method in iface.__abstractmethods__: if not hasattr(klass, method): raise InterfaceNotImplemented( "{} is missing a {!r} method".format(klass, method) ) if isinstance(getattr(iface, method), abc.abstractproperty): # Can't properly verify these yet. continue sig = signature(getattr(iface, method)) actual = signature(getattr(klass, method)) if sig != actual: raise InterfaceNotImplemented( "{}.{}'s signature differs from the expected. Expected: " "{!r}. Received: {!r}".format( klass, method, sig, actual ) ) # No longer needed as of 2.2, but retained because we have external consumers # who use it. def bit_length(x): return x.bit_length() class _DeprecatedValue(object): def __init__(self, value, message, warning_class): self.value = value self.message = message self.warning_class = warning_class class _ModuleWithDeprecations(object): def __init__(self, module): self.__dict__["_module"] = module def __getattr__(self, attr): obj = getattr(self._module, attr) if isinstance(obj, _DeprecatedValue): warnings.warn(obj.message, obj.warning_class, stacklevel=2) obj = obj.value return obj def __setattr__(self, attr, value): setattr(self._module, attr, value) def __delattr__(self, attr): obj = getattr(self._module, attr) if isinstance(obj, _DeprecatedValue): warnings.warn(obj.message, obj.warning_class, stacklevel=2) delattr(self._module, attr) def __dir__(self): return ["_module"] + dir(self._module) def deprecated(value, module_name, message, warning_class): module = sys.modules[module_name] if not isinstance(module, _ModuleWithDeprecations): sys.modules[module_name] = _ModuleWithDeprecations(module) return _DeprecatedValue(value, message, warning_class) def cached_property(func): cached_name = "_cached_{}".format(func) sentinel = object() def inner(instance): cache = getattr(instance, cached_name, sentinel) if cache is not sentinel: return cache result = func(instance) setattr(instance, cached_name, result) return result return property(inner) ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/cryptography/x509/__init__.py ================================================ # This file is dual licensed under the terms of the Apache License, Version # 2.0, and the BSD License. See the LICENSE file in the root of this repository # for complete details. from __future__ import absolute_import, division, print_function from cryptography.x509 import certificate_transparency from cryptography.x509.base import ( Certificate, CertificateBuilder, CertificateRevocationList, CertificateRevocationListBuilder, CertificateSigningRequest, CertificateSigningRequestBuilder, InvalidVersion, RevokedCertificate, RevokedCertificateBuilder, Version, load_der_x509_certificate, load_der_x509_crl, load_der_x509_csr, load_pem_x509_certificate, load_pem_x509_crl, load_pem_x509_csr, random_serial_number, ) from cryptography.x509.extensions import ( AccessDescription, AuthorityInformationAccess, AuthorityKeyIdentifier, BasicConstraints, CRLDistributionPoints, CRLNumber, CRLReason, CertificateIssuer, CertificatePolicies, DeltaCRLIndicator, DistributionPoint, DuplicateExtension, ExtendedKeyUsage, Extension, ExtensionNotFound, ExtensionType, Extensions, FreshestCRL, GeneralNames, InhibitAnyPolicy, InvalidityDate, IssuerAlternativeName, IssuingDistributionPoint, KeyUsage, NameConstraints, NoticeReference, OCSPNoCheck, OCSPNonce, PolicyConstraints, PolicyInformation, PrecertPoison, PrecertificateSignedCertificateTimestamps, ReasonFlags, SubjectAlternativeName, SubjectKeyIdentifier, TLSFeature, TLSFeatureType, UnrecognizedExtension, UserNotice ) from cryptography.x509.general_name import ( DNSName, DirectoryName, GeneralName, IPAddress, OtherName, RFC822Name, RegisteredID, UniformResourceIdentifier, UnsupportedGeneralNameType, _GENERAL_NAMES ) from cryptography.x509.name import ( Name, NameAttribute, RelativeDistinguishedName ) from cryptography.x509.oid import ( AuthorityInformationAccessOID, CRLEntryExtensionOID, CertificatePoliciesOID, ExtendedKeyUsageOID, ExtensionOID, NameOID, ObjectIdentifier, SignatureAlgorithmOID, _SIG_OIDS_TO_HASH ) OID_AUTHORITY_INFORMATION_ACCESS = ExtensionOID.AUTHORITY_INFORMATION_ACCESS OID_AUTHORITY_KEY_IDENTIFIER = ExtensionOID.AUTHORITY_KEY_IDENTIFIER OID_BASIC_CONSTRAINTS = ExtensionOID.BASIC_CONSTRAINTS OID_CERTIFICATE_POLICIES = ExtensionOID.CERTIFICATE_POLICIES OID_CRL_DISTRIBUTION_POINTS = ExtensionOID.CRL_DISTRIBUTION_POINTS OID_EXTENDED_KEY_USAGE = ExtensionOID.EXTENDED_KEY_USAGE OID_FRESHEST_CRL = ExtensionOID.FRESHEST_CRL OID_INHIBIT_ANY_POLICY = ExtensionOID.INHIBIT_ANY_POLICY OID_ISSUER_ALTERNATIVE_NAME = ExtensionOID.ISSUER_ALTERNATIVE_NAME OID_KEY_USAGE = ExtensionOID.KEY_USAGE OID_NAME_CONSTRAINTS = ExtensionOID.NAME_CONSTRAINTS OID_OCSP_NO_CHECK = ExtensionOID.OCSP_NO_CHECK OID_POLICY_CONSTRAINTS = ExtensionOID.POLICY_CONSTRAINTS OID_POLICY_MAPPINGS = ExtensionOID.POLICY_MAPPINGS OID_SUBJECT_ALTERNATIVE_NAME = ExtensionOID.SUBJECT_ALTERNATIVE_NAME OID_SUBJECT_DIRECTORY_ATTRIBUTES = ExtensionOID.SUBJECT_DIRECTORY_ATTRIBUTES OID_SUBJECT_INFORMATION_ACCESS = ExtensionOID.SUBJECT_INFORMATION_ACCESS OID_SUBJECT_KEY_IDENTIFIER = ExtensionOID.SUBJECT_KEY_IDENTIFIER OID_DSA_WITH_SHA1 = SignatureAlgorithmOID.DSA_WITH_SHA1 OID_DSA_WITH_SHA224 = SignatureAlgorithmOID.DSA_WITH_SHA224 OID_DSA_WITH_SHA256 = SignatureAlgorithmOID.DSA_WITH_SHA256 OID_ECDSA_WITH_SHA1 = SignatureAlgorithmOID.ECDSA_WITH_SHA1 OID_ECDSA_WITH_SHA224 = SignatureAlgorithmOID.ECDSA_WITH_SHA224 OID_ECDSA_WITH_SHA256 = SignatureAlgorithmOID.ECDSA_WITH_SHA256 OID_ECDSA_WITH_SHA384 = SignatureAlgorithmOID.ECDSA_WITH_SHA384 OID_ECDSA_WITH_SHA512 = SignatureAlgorithmOID.ECDSA_WITH_SHA512 OID_RSA_WITH_MD5 = SignatureAlgorithmOID.RSA_WITH_MD5 OID_RSA_WITH_SHA1 = SignatureAlgorithmOID.RSA_WITH_SHA1 OID_RSA_WITH_SHA224 = SignatureAlgorithmOID.RSA_WITH_SHA224 OID_RSA_WITH_SHA256 = SignatureAlgorithmOID.RSA_WITH_SHA256 OID_RSA_WITH_SHA384 = SignatureAlgorithmOID.RSA_WITH_SHA384 OID_RSA_WITH_SHA512 = SignatureAlgorithmOID.RSA_WITH_SHA512 OID_RSASSA_PSS = SignatureAlgorithmOID.RSASSA_PSS OID_COMMON_NAME = NameOID.COMMON_NAME OID_COUNTRY_NAME = NameOID.COUNTRY_NAME OID_DOMAIN_COMPONENT = NameOID.DOMAIN_COMPONENT OID_DN_QUALIFIER = NameOID.DN_QUALIFIER OID_EMAIL_ADDRESS = NameOID.EMAIL_ADDRESS OID_GENERATION_QUALIFIER = NameOID.GENERATION_QUALIFIER OID_GIVEN_NAME = NameOID.GIVEN_NAME OID_LOCALITY_NAME = NameOID.LOCALITY_NAME OID_ORGANIZATIONAL_UNIT_NAME = NameOID.ORGANIZATIONAL_UNIT_NAME OID_ORGANIZATION_NAME = NameOID.ORGANIZATION_NAME OID_PSEUDONYM = NameOID.PSEUDONYM OID_SERIAL_NUMBER = NameOID.SERIAL_NUMBER OID_STATE_OR_PROVINCE_NAME = NameOID.STATE_OR_PROVINCE_NAME OID_SURNAME = NameOID.SURNAME OID_TITLE = NameOID.TITLE OID_CLIENT_AUTH = ExtendedKeyUsageOID.CLIENT_AUTH OID_CODE_SIGNING = ExtendedKeyUsageOID.CODE_SIGNING OID_EMAIL_PROTECTION = ExtendedKeyUsageOID.EMAIL_PROTECTION OID_OCSP_SIGNING = ExtendedKeyUsageOID.OCSP_SIGNING OID_SERVER_AUTH = ExtendedKeyUsageOID.SERVER_AUTH OID_TIME_STAMPING = ExtendedKeyUsageOID.TIME_STAMPING OID_ANY_POLICY = CertificatePoliciesOID.ANY_POLICY OID_CPS_QUALIFIER = CertificatePoliciesOID.CPS_QUALIFIER OID_CPS_USER_NOTICE = CertificatePoliciesOID.CPS_USER_NOTICE OID_CERTIFICATE_ISSUER = CRLEntryExtensionOID.CERTIFICATE_ISSUER OID_CRL_REASON = CRLEntryExtensionOID.CRL_REASON OID_INVALIDITY_DATE = CRLEntryExtensionOID.INVALIDITY_DATE OID_CA_ISSUERS = AuthorityInformationAccessOID.CA_ISSUERS OID_OCSP = AuthorityInformationAccessOID.OCSP __all__ = [ "certificate_transparency", "load_pem_x509_certificate", "load_der_x509_certificate", "load_pem_x509_csr", "load_der_x509_csr", "load_pem_x509_crl", "load_der_x509_crl", "random_serial_number", "InvalidVersion", "DeltaCRLIndicator", "DuplicateExtension", "ExtensionNotFound", "UnsupportedGeneralNameType", "NameAttribute", "Name", "RelativeDistinguishedName", "ObjectIdentifier", "ExtensionType", "Extensions", "Extension", "ExtendedKeyUsage", "FreshestCRL", "IssuingDistributionPoint", "TLSFeature", "TLSFeatureType", "OCSPNoCheck", "BasicConstraints", "CRLNumber", "KeyUsage", "AuthorityInformationAccess", "AccessDescription", "CertificatePolicies", "PolicyInformation", "UserNotice", "NoticeReference", "SubjectKeyIdentifier", "NameConstraints", "CRLDistributionPoints", "DistributionPoint", "ReasonFlags", "InhibitAnyPolicy", "SubjectAlternativeName", "IssuerAlternativeName", "AuthorityKeyIdentifier", "GeneralNames", "GeneralName", "RFC822Name", "DNSName", "UniformResourceIdentifier", "RegisteredID", "DirectoryName", "IPAddress", "OtherName", "Certificate", "CertificateRevocationList", "CertificateRevocationListBuilder", "CertificateSigningRequest", "RevokedCertificate", "RevokedCertificateBuilder", "CertificateSigningRequestBuilder", "CertificateBuilder", "Version", "_SIG_OIDS_TO_HASH", "OID_CA_ISSUERS", "OID_OCSP", "_GENERAL_NAMES", "CertificateIssuer", "CRLReason", "InvalidityDate", "UnrecognizedExtension", "PolicyConstraints", "PrecertificateSignedCertificateTimestamps", "PrecertPoison", "OCSPNonce", ] ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/cryptography/x509/base.py ================================================ # This file is dual licensed under the terms of the Apache License, Version # 2.0, and the BSD License. See the LICENSE file in the root of this repository # for complete details. from __future__ import absolute_import, division, print_function import abc import datetime import os from enum import Enum import six from cryptography import utils from cryptography.hazmat.primitives.asymmetric import ( dsa, ec, ed25519, ed448, rsa ) from cryptography.x509.extensions import Extension, ExtensionType from cryptography.x509.name import Name _EARLIEST_UTC_TIME = datetime.datetime(1950, 1, 1) def _reject_duplicate_extension(extension, extensions): # This is quadratic in the number of extensions for e in extensions: if e.oid == extension.oid: raise ValueError('This extension has already been set.') def _convert_to_naive_utc_time(time): """Normalizes a datetime to a naive datetime in UTC. time -- datetime to normalize. Assumed to be in UTC if not timezone aware. """ if time.tzinfo is not None: offset = time.utcoffset() offset = offset if offset else datetime.timedelta() return time.replace(tzinfo=None) - offset else: return time class Version(Enum): v1 = 0 v3 = 2 def load_pem_x509_certificate(data, backend): return backend.load_pem_x509_certificate(data) def load_der_x509_certificate(data, backend): return backend.load_der_x509_certificate(data) def load_pem_x509_csr(data, backend): return backend.load_pem_x509_csr(data) def load_der_x509_csr(data, backend): return backend.load_der_x509_csr(data) def load_pem_x509_crl(data, backend): return backend.load_pem_x509_crl(data) def load_der_x509_crl(data, backend): return backend.load_der_x509_crl(data) class InvalidVersion(Exception): def __init__(self, msg, parsed_version): super(InvalidVersion, self).__init__(msg) self.parsed_version = parsed_version @six.add_metaclass(abc.ABCMeta) class Certificate(object): @abc.abstractmethod def fingerprint(self, algorithm): """ Returns bytes using digest passed. """ @abc.abstractproperty def serial_number(self): """ Returns certificate serial number """ @abc.abstractproperty def version(self): """ Returns the certificate version """ @abc.abstractmethod def public_key(self): """ Returns the public key """ @abc.abstractproperty def not_valid_before(self): """ Not before time (represented as UTC datetime) """ @abc.abstractproperty def not_valid_after(self): """ Not after time (represented as UTC datetime) """ @abc.abstractproperty def issuer(self): """ Returns the issuer name object. """ @abc.abstractproperty def subject(self): """ Returns the subject name object. """ @abc.abstractproperty def signature_hash_algorithm(self): """ Returns a HashAlgorithm corresponding to the type of the digest signed in the certificate. """ @abc.abstractproperty def signature_algorithm_oid(self): """ Returns the ObjectIdentifier of the signature algorithm. """ @abc.abstractproperty def extensions(self): """ Returns an Extensions object. """ @abc.abstractproperty def signature(self): """ Returns the signature bytes. """ @abc.abstractproperty def tbs_certificate_bytes(self): """ Returns the tbsCertificate payload bytes as defined in RFC 5280. """ @abc.abstractmethod def __eq__(self, other): """ Checks equality. """ @abc.abstractmethod def __ne__(self, other): """ Checks not equal. """ @abc.abstractmethod def __hash__(self): """ Computes a hash. """ @abc.abstractmethod def public_bytes(self, encoding): """ Serializes the certificate to PEM or DER format. """ @six.add_metaclass(abc.ABCMeta) class CertificateRevocationList(object): @abc.abstractmethod def public_bytes(self, encoding): """ Serializes the CRL to PEM or DER format. """ @abc.abstractmethod def fingerprint(self, algorithm): """ Returns bytes using digest passed. """ @abc.abstractmethod def get_revoked_certificate_by_serial_number(self, serial_number): """ Returns an instance of RevokedCertificate or None if the serial_number is not in the CRL. """ @abc.abstractproperty def signature_hash_algorithm(self): """ Returns a HashAlgorithm corresponding to the type of the digest signed in the certificate. """ @abc.abstractproperty def signature_algorithm_oid(self): """ Returns the ObjectIdentifier of the signature algorithm. """ @abc.abstractproperty def issuer(self): """ Returns the X509Name with the issuer of this CRL. """ @abc.abstractproperty def next_update(self): """ Returns the date of next update for this CRL. """ @abc.abstractproperty def last_update(self): """ Returns the date of last update for this CRL. """ @abc.abstractproperty def extensions(self): """ Returns an Extensions object containing a list of CRL extensions. """ @abc.abstractproperty def signature(self): """ Returns the signature bytes. """ @abc.abstractproperty def tbs_certlist_bytes(self): """ Returns the tbsCertList payload bytes as defined in RFC 5280. """ @abc.abstractmethod def __eq__(self, other): """ Checks equality. """ @abc.abstractmethod def __ne__(self, other): """ Checks not equal. """ @abc.abstractmethod def __len__(self): """ Number of revoked certificates in the CRL. """ @abc.abstractmethod def __getitem__(self, idx): """ Returns a revoked certificate (or slice of revoked certificates). """ @abc.abstractmethod def __iter__(self): """ Iterator over the revoked certificates """ @abc.abstractmethod def is_signature_valid(self, public_key): """ Verifies signature of revocation list against given public key. """ @six.add_metaclass(abc.ABCMeta) class CertificateSigningRequest(object): @abc.abstractmethod def __eq__(self, other): """ Checks equality. """ @abc.abstractmethod def __ne__(self, other): """ Checks not equal. """ @abc.abstractmethod def __hash__(self): """ Computes a hash. """ @abc.abstractmethod def public_key(self): """ Returns the public key """ @abc.abstractproperty def subject(self): """ Returns the subject name object. """ @abc.abstractproperty def signature_hash_algorithm(self): """ Returns a HashAlgorithm corresponding to the type of the digest signed in the certificate. """ @abc.abstractproperty def signature_algorithm_oid(self): """ Returns the ObjectIdentifier of the signature algorithm. """ @abc.abstractproperty def extensions(self): """ Returns the extensions in the signing request. """ @abc.abstractmethod def public_bytes(self, encoding): """ Encodes the request to PEM or DER format. """ @abc.abstractproperty def signature(self): """ Returns the signature bytes. """ @abc.abstractproperty def tbs_certrequest_bytes(self): """ Returns the PKCS#10 CertificationRequestInfo bytes as defined in RFC 2986. """ @abc.abstractproperty def is_signature_valid(self): """ Verifies signature of signing request. """ @six.add_metaclass(abc.ABCMeta) class RevokedCertificate(object): @abc.abstractproperty def serial_number(self): """ Returns the serial number of the revoked certificate. """ @abc.abstractproperty def revocation_date(self): """ Returns the date of when this certificate was revoked. """ @abc.abstractproperty def extensions(self): """ Returns an Extensions object containing a list of Revoked extensions. """ class CertificateSigningRequestBuilder(object): def __init__(self, subject_name=None, extensions=[]): """ Creates an empty X.509 certificate request (v1). """ self._subject_name = subject_name self._extensions = extensions def subject_name(self, name): """ Sets the certificate requestor's distinguished name. """ if not isinstance(name, Name): raise TypeError('Expecting x509.Name object.') if self._subject_name is not None: raise ValueError('The subject name may only be set once.') return CertificateSigningRequestBuilder(name, self._extensions) def add_extension(self, extension, critical): """ Adds an X.509 extension to the certificate request. """ if not isinstance(extension, ExtensionType): raise TypeError("extension must be an ExtensionType") extension = Extension(extension.oid, critical, extension) _reject_duplicate_extension(extension, self._extensions) return CertificateSigningRequestBuilder( self._subject_name, self._extensions + [extension] ) def sign(self, private_key, algorithm, backend): """ Signs the request using the requestor's private key. """ if self._subject_name is None: raise ValueError("A CertificateSigningRequest must have a subject") return backend.create_x509_csr(self, private_key, algorithm) class CertificateBuilder(object): def __init__(self, issuer_name=None, subject_name=None, public_key=None, serial_number=None, not_valid_before=None, not_valid_after=None, extensions=[]): self._version = Version.v3 self._issuer_name = issuer_name self._subject_name = subject_name self._public_key = public_key self._serial_number = serial_number self._not_valid_before = not_valid_before self._not_valid_after = not_valid_after self._extensions = extensions def issuer_name(self, name): """ Sets the CA's distinguished name. """ if not isinstance(name, Name): raise TypeError('Expecting x509.Name object.') if self._issuer_name is not None: raise ValueError('The issuer name may only be set once.') return CertificateBuilder( name, self._subject_name, self._public_key, self._serial_number, self._not_valid_before, self._not_valid_after, self._extensions ) def subject_name(self, name): """ Sets the requestor's distinguished name. """ if not isinstance(name, Name): raise TypeError('Expecting x509.Name object.') if self._subject_name is not None: raise ValueError('The subject name may only be set once.') return CertificateBuilder( self._issuer_name, name, self._public_key, self._serial_number, self._not_valid_before, self._not_valid_after, self._extensions ) def public_key(self, key): """ Sets the requestor's public key (as found in the signing request). """ if not isinstance(key, (dsa.DSAPublicKey, rsa.RSAPublicKey, ec.EllipticCurvePublicKey, ed25519.Ed25519PublicKey, ed448.Ed448PublicKey)): raise TypeError('Expecting one of DSAPublicKey, RSAPublicKey,' ' EllipticCurvePublicKey, Ed25519PublicKey or' ' Ed448PublicKey.') if self._public_key is not None: raise ValueError('The public key may only be set once.') return CertificateBuilder( self._issuer_name, self._subject_name, key, self._serial_number, self._not_valid_before, self._not_valid_after, self._extensions ) def serial_number(self, number): """ Sets the certificate serial number. """ if not isinstance(number, six.integer_types): raise TypeError('Serial number must be of integral type.') if self._serial_number is not None: raise ValueError('The serial number may only be set once.') if number <= 0: raise ValueError('The serial number should be positive.') # ASN.1 integers are always signed, so most significant bit must be # zero. if number.bit_length() >= 160: # As defined in RFC 5280 raise ValueError('The serial number should not be more than 159 ' 'bits.') return CertificateBuilder( self._issuer_name, self._subject_name, self._public_key, number, self._not_valid_before, self._not_valid_after, self._extensions ) def not_valid_before(self, time): """ Sets the certificate activation time. """ if not isinstance(time, datetime.datetime): raise TypeError('Expecting datetime object.') if self._not_valid_before is not None: raise ValueError('The not valid before may only be set once.') time = _convert_to_naive_utc_time(time) if time < _EARLIEST_UTC_TIME: raise ValueError('The not valid before date must be on or after' ' 1950 January 1).') if self._not_valid_after is not None and time > self._not_valid_after: raise ValueError( 'The not valid before date must be before the not valid after ' 'date.' ) return CertificateBuilder( self._issuer_name, self._subject_name, self._public_key, self._serial_number, time, self._not_valid_after, self._extensions ) def not_valid_after(self, time): """ Sets the certificate expiration time. """ if not isinstance(time, datetime.datetime): raise TypeError('Expecting datetime object.') if self._not_valid_after is not None: raise ValueError('The not valid after may only be set once.') time = _convert_to_naive_utc_time(time) if time < _EARLIEST_UTC_TIME: raise ValueError('The not valid after date must be on or after' ' 1950 January 1.') if (self._not_valid_before is not None and time < self._not_valid_before): raise ValueError( 'The not valid after date must be after the not valid before ' 'date.' ) return CertificateBuilder( self._issuer_name, self._subject_name, self._public_key, self._serial_number, self._not_valid_before, time, self._extensions ) def add_extension(self, extension, critical): """ Adds an X.509 extension to the certificate. """ if not isinstance(extension, ExtensionType): raise TypeError("extension must be an ExtensionType") extension = Extension(extension.oid, critical, extension) _reject_duplicate_extension(extension, self._extensions) return CertificateBuilder( self._issuer_name, self._subject_name, self._public_key, self._serial_number, self._not_valid_before, self._not_valid_after, self._extensions + [extension] ) def sign(self, private_key, algorithm, backend): """ Signs the certificate using the CA's private key. """ if self._subject_name is None: raise ValueError("A certificate must have a subject name") if self._issuer_name is None: raise ValueError("A certificate must have an issuer name") if self._serial_number is None: raise ValueError("A certificate must have a serial number") if self._not_valid_before is None: raise ValueError("A certificate must have a not valid before time") if self._not_valid_after is None: raise ValueError("A certificate must have a not valid after time") if self._public_key is None: raise ValueError("A certificate must have a public key") return backend.create_x509_certificate(self, private_key, algorithm) class CertificateRevocationListBuilder(object): def __init__(self, issuer_name=None, last_update=None, next_update=None, extensions=[], revoked_certificates=[]): self._issuer_name = issuer_name self._last_update = last_update self._next_update = next_update self._extensions = extensions self._revoked_certificates = revoked_certificates def issuer_name(self, issuer_name): if not isinstance(issuer_name, Name): raise TypeError('Expecting x509.Name object.') if self._issuer_name is not None: raise ValueError('The issuer name may only be set once.') return CertificateRevocationListBuilder( issuer_name, self._last_update, self._next_update, self._extensions, self._revoked_certificates ) def last_update(self, last_update): if not isinstance(last_update, datetime.datetime): raise TypeError('Expecting datetime object.') if self._last_update is not None: raise ValueError('Last update may only be set once.') last_update = _convert_to_naive_utc_time(last_update) if last_update < _EARLIEST_UTC_TIME: raise ValueError('The last update date must be on or after' ' 1950 January 1.') if self._next_update is not None and last_update > self._next_update: raise ValueError( 'The last update date must be before the next update date.' ) return CertificateRevocationListBuilder( self._issuer_name, last_update, self._next_update, self._extensions, self._revoked_certificates ) def next_update(self, next_update): if not isinstance(next_update, datetime.datetime): raise TypeError('Expecting datetime object.') if self._next_update is not None: raise ValueError('Last update may only be set once.') next_update = _convert_to_naive_utc_time(next_update) if next_update < _EARLIEST_UTC_TIME: raise ValueError('The last update date must be on or after' ' 1950 January 1.') if self._last_update is not None and next_update < self._last_update: raise ValueError( 'The next update date must be after the last update date.' ) return CertificateRevocationListBuilder( self._issuer_name, self._last_update, next_update, self._extensions, self._revoked_certificates ) def add_extension(self, extension, critical): """ Adds an X.509 extension to the certificate revocation list. """ if not isinstance(extension, ExtensionType): raise TypeError("extension must be an ExtensionType") extension = Extension(extension.oid, critical, extension) _reject_duplicate_extension(extension, self._extensions) return CertificateRevocationListBuilder( self._issuer_name, self._last_update, self._next_update, self._extensions + [extension], self._revoked_certificates ) def add_revoked_certificate(self, revoked_certificate): """ Adds a revoked certificate to the CRL. """ if not isinstance(revoked_certificate, RevokedCertificate): raise TypeError("Must be an instance of RevokedCertificate") return CertificateRevocationListBuilder( self._issuer_name, self._last_update, self._next_update, self._extensions, self._revoked_certificates + [revoked_certificate] ) def sign(self, private_key, algorithm, backend): if self._issuer_name is None: raise ValueError("A CRL must have an issuer name") if self._last_update is None: raise ValueError("A CRL must have a last update time") if self._next_update is None: raise ValueError("A CRL must have a next update time") return backend.create_x509_crl(self, private_key, algorithm) class RevokedCertificateBuilder(object): def __init__(self, serial_number=None, revocation_date=None, extensions=[]): self._serial_number = serial_number self._revocation_date = revocation_date self._extensions = extensions def serial_number(self, number): if not isinstance(number, six.integer_types): raise TypeError('Serial number must be of integral type.') if self._serial_number is not None: raise ValueError('The serial number may only be set once.') if number <= 0: raise ValueError('The serial number should be positive') # ASN.1 integers are always signed, so most significant bit must be # zero. if number.bit_length() >= 160: # As defined in RFC 5280 raise ValueError('The serial number should not be more than 159 ' 'bits.') return RevokedCertificateBuilder( number, self._revocation_date, self._extensions ) def revocation_date(self, time): if not isinstance(time, datetime.datetime): raise TypeError('Expecting datetime object.') if self._revocation_date is not None: raise ValueError('The revocation date may only be set once.') time = _convert_to_naive_utc_time(time) if time < _EARLIEST_UTC_TIME: raise ValueError('The revocation date must be on or after' ' 1950 January 1.') return RevokedCertificateBuilder( self._serial_number, time, self._extensions ) def add_extension(self, extension, critical): if not isinstance(extension, ExtensionType): raise TypeError("extension must be an ExtensionType") extension = Extension(extension.oid, critical, extension) _reject_duplicate_extension(extension, self._extensions) return RevokedCertificateBuilder( self._serial_number, self._revocation_date, self._extensions + [extension] ) def build(self, backend): if self._serial_number is None: raise ValueError("A revoked certificate must have a serial number") if self._revocation_date is None: raise ValueError( "A revoked certificate must have a revocation date" ) return backend.create_x509_revoked_certificate(self) def random_serial_number(): return utils.int_from_bytes(os.urandom(20), "big") >> 1 ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/cryptography/x509/certificate_transparency.py ================================================ # This file is dual licensed under the terms of the Apache License, Version # 2.0, and the BSD License. See the LICENSE file in the root of this repository # for complete details. from __future__ import absolute_import, division, print_function import abc from enum import Enum import six class LogEntryType(Enum): X509_CERTIFICATE = 0 PRE_CERTIFICATE = 1 class Version(Enum): v1 = 0 @six.add_metaclass(abc.ABCMeta) class SignedCertificateTimestamp(object): @abc.abstractproperty def version(self): """ Returns the SCT version. """ @abc.abstractproperty def log_id(self): """ Returns an identifier indicating which log this SCT is for. """ @abc.abstractproperty def timestamp(self): """ Returns the timestamp for this SCT. """ @abc.abstractproperty def entry_type(self): """ Returns whether this is an SCT for a certificate or pre-certificate. """ ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/cryptography/x509/extensions.py ================================================ # This file is dual licensed under the terms of the Apache License, Version # 2.0, and the BSD License. See the LICENSE file in the root of this repository # for complete details. from __future__ import absolute_import, division, print_function import abc import datetime import hashlib import ipaddress import warnings from enum import Enum import six from cryptography import utils from cryptography.hazmat._der import ( BIT_STRING, DERReader, OBJECT_IDENTIFIER, SEQUENCE ) from cryptography.hazmat.primitives import constant_time, serialization from cryptography.hazmat.primitives.asymmetric.ec import EllipticCurvePublicKey from cryptography.hazmat.primitives.asymmetric.rsa import RSAPublicKey from cryptography.x509.certificate_transparency import ( SignedCertificateTimestamp ) from cryptography.x509.general_name import GeneralName, IPAddress, OtherName from cryptography.x509.name import RelativeDistinguishedName from cryptography.x509.oid import ( CRLEntryExtensionOID, ExtensionOID, OCSPExtensionOID, ObjectIdentifier, ) def _key_identifier_from_public_key(public_key): if isinstance(public_key, RSAPublicKey): data = public_key.public_bytes( serialization.Encoding.DER, serialization.PublicFormat.PKCS1, ) elif isinstance(public_key, EllipticCurvePublicKey): data = public_key.public_bytes( serialization.Encoding.X962, serialization.PublicFormat.UncompressedPoint ) else: # This is a very slow way to do this. serialized = public_key.public_bytes( serialization.Encoding.DER, serialization.PublicFormat.SubjectPublicKeyInfo ) reader = DERReader(serialized) with reader.read_single_element(SEQUENCE) as public_key_info: algorithm = public_key_info.read_element(SEQUENCE) public_key = public_key_info.read_element(BIT_STRING) # Double-check the algorithm structure. with algorithm: algorithm.read_element(OBJECT_IDENTIFIER) if not algorithm.is_empty(): # Skip the optional parameters field. algorithm.read_any_element() # BIT STRING contents begin with the number of padding bytes added. It # must be zero for SubjectPublicKeyInfo structures. if public_key.read_byte() != 0: raise ValueError('Invalid public key encoding') data = public_key.data return hashlib.sha1(data).digest() def _make_sequence_methods(field_name): def len_method(self): return len(getattr(self, field_name)) def iter_method(self): return iter(getattr(self, field_name)) def getitem_method(self, idx): return getattr(self, field_name)[idx] return len_method, iter_method, getitem_method class DuplicateExtension(Exception): def __init__(self, msg, oid): super(DuplicateExtension, self).__init__(msg) self.oid = oid class ExtensionNotFound(Exception): def __init__(self, msg, oid): super(ExtensionNotFound, self).__init__(msg) self.oid = oid @six.add_metaclass(abc.ABCMeta) class ExtensionType(object): @abc.abstractproperty def oid(self): """ Returns the oid associated with the given extension type. """ class Extensions(object): def __init__(self, extensions): self._extensions = extensions def get_extension_for_oid(self, oid): for ext in self: if ext.oid == oid: return ext raise ExtensionNotFound("No {} extension was found".format(oid), oid) def get_extension_for_class(self, extclass): if extclass is UnrecognizedExtension: raise TypeError( "UnrecognizedExtension can't be used with " "get_extension_for_class because more than one instance of the" " class may be present." ) for ext in self: if isinstance(ext.value, extclass): return ext raise ExtensionNotFound( "No {} extension was found".format(extclass), extclass.oid ) __len__, __iter__, __getitem__ = _make_sequence_methods("_extensions") def __repr__(self): return ( "".format(self._extensions) ) @utils.register_interface(ExtensionType) class CRLNumber(object): oid = ExtensionOID.CRL_NUMBER def __init__(self, crl_number): if not isinstance(crl_number, six.integer_types): raise TypeError("crl_number must be an integer") self._crl_number = crl_number def __eq__(self, other): if not isinstance(other, CRLNumber): return NotImplemented return self.crl_number == other.crl_number def __ne__(self, other): return not self == other def __hash__(self): return hash(self.crl_number) def __repr__(self): return "".format(self.crl_number) crl_number = utils.read_only_property("_crl_number") @utils.register_interface(ExtensionType) class AuthorityKeyIdentifier(object): oid = ExtensionOID.AUTHORITY_KEY_IDENTIFIER def __init__(self, key_identifier, authority_cert_issuer, authority_cert_serial_number): if (authority_cert_issuer is None) != ( authority_cert_serial_number is None ): raise ValueError( "authority_cert_issuer and authority_cert_serial_number " "must both be present or both None" ) if authority_cert_issuer is not None: authority_cert_issuer = list(authority_cert_issuer) if not all( isinstance(x, GeneralName) for x in authority_cert_issuer ): raise TypeError( "authority_cert_issuer must be a list of GeneralName " "objects" ) if authority_cert_serial_number is not None and not isinstance( authority_cert_serial_number, six.integer_types ): raise TypeError( "authority_cert_serial_number must be an integer" ) self._key_identifier = key_identifier self._authority_cert_issuer = authority_cert_issuer self._authority_cert_serial_number = authority_cert_serial_number @classmethod def from_issuer_public_key(cls, public_key): digest = _key_identifier_from_public_key(public_key) return cls( key_identifier=digest, authority_cert_issuer=None, authority_cert_serial_number=None ) @classmethod def from_issuer_subject_key_identifier(cls, ski): if isinstance(ski, SubjectKeyIdentifier): digest = ski.digest else: digest = ski.value.digest warnings.warn( "Extension objects are deprecated as arguments to " "from_issuer_subject_key_identifier and support will be " "removed soon. Please migrate to passing a " "SubjectKeyIdentifier directly.", utils.DeprecatedIn27, stacklevel=2, ) return cls( key_identifier=digest, authority_cert_issuer=None, authority_cert_serial_number=None ) def __repr__(self): return ( "".format(self) ) def __eq__(self, other): if not isinstance(other, AuthorityKeyIdentifier): return NotImplemented return ( self.key_identifier == other.key_identifier and self.authority_cert_issuer == other.authority_cert_issuer and self.authority_cert_serial_number == other.authority_cert_serial_number ) def __ne__(self, other): return not self == other def __hash__(self): if self.authority_cert_issuer is None: aci = None else: aci = tuple(self.authority_cert_issuer) return hash(( self.key_identifier, aci, self.authority_cert_serial_number )) key_identifier = utils.read_only_property("_key_identifier") authority_cert_issuer = utils.read_only_property("_authority_cert_issuer") authority_cert_serial_number = utils.read_only_property( "_authority_cert_serial_number" ) @utils.register_interface(ExtensionType) class SubjectKeyIdentifier(object): oid = ExtensionOID.SUBJECT_KEY_IDENTIFIER def __init__(self, digest): self._digest = digest @classmethod def from_public_key(cls, public_key): return cls(_key_identifier_from_public_key(public_key)) digest = utils.read_only_property("_digest") def __repr__(self): return "".format(self.digest) def __eq__(self, other): if not isinstance(other, SubjectKeyIdentifier): return NotImplemented return constant_time.bytes_eq(self.digest, other.digest) def __ne__(self, other): return not self == other def __hash__(self): return hash(self.digest) @utils.register_interface(ExtensionType) class AuthorityInformationAccess(object): oid = ExtensionOID.AUTHORITY_INFORMATION_ACCESS def __init__(self, descriptions): descriptions = list(descriptions) if not all(isinstance(x, AccessDescription) for x in descriptions): raise TypeError( "Every item in the descriptions list must be an " "AccessDescription" ) self._descriptions = descriptions __len__, __iter__, __getitem__ = _make_sequence_methods("_descriptions") def __repr__(self): return "".format(self._descriptions) def __eq__(self, other): if not isinstance(other, AuthorityInformationAccess): return NotImplemented return self._descriptions == other._descriptions def __ne__(self, other): return not self == other def __hash__(self): return hash(tuple(self._descriptions)) class AccessDescription(object): def __init__(self, access_method, access_location): if not isinstance(access_method, ObjectIdentifier): raise TypeError("access_method must be an ObjectIdentifier") if not isinstance(access_location, GeneralName): raise TypeError("access_location must be a GeneralName") self._access_method = access_method self._access_location = access_location def __repr__(self): return ( "".format(self) ) def __eq__(self, other): if not isinstance(other, AccessDescription): return NotImplemented return ( self.access_method == other.access_method and self.access_location == other.access_location ) def __ne__(self, other): return not self == other def __hash__(self): return hash((self.access_method, self.access_location)) access_method = utils.read_only_property("_access_method") access_location = utils.read_only_property("_access_location") @utils.register_interface(ExtensionType) class BasicConstraints(object): oid = ExtensionOID.BASIC_CONSTRAINTS def __init__(self, ca, path_length): if not isinstance(ca, bool): raise TypeError("ca must be a boolean value") if path_length is not None and not ca: raise ValueError("path_length must be None when ca is False") if ( path_length is not None and (not isinstance(path_length, six.integer_types) or path_length < 0) ): raise TypeError( "path_length must be a non-negative integer or None" ) self._ca = ca self._path_length = path_length ca = utils.read_only_property("_ca") path_length = utils.read_only_property("_path_length") def __repr__(self): return ("").format(self) def __eq__(self, other): if not isinstance(other, BasicConstraints): return NotImplemented return self.ca == other.ca and self.path_length == other.path_length def __ne__(self, other): return not self == other def __hash__(self): return hash((self.ca, self.path_length)) @utils.register_interface(ExtensionType) class DeltaCRLIndicator(object): oid = ExtensionOID.DELTA_CRL_INDICATOR def __init__(self, crl_number): if not isinstance(crl_number, six.integer_types): raise TypeError("crl_number must be an integer") self._crl_number = crl_number crl_number = utils.read_only_property("_crl_number") def __eq__(self, other): if not isinstance(other, DeltaCRLIndicator): return NotImplemented return self.crl_number == other.crl_number def __ne__(self, other): return not self == other def __hash__(self): return hash(self.crl_number) def __repr__(self): return "".format(self) @utils.register_interface(ExtensionType) class CRLDistributionPoints(object): oid = ExtensionOID.CRL_DISTRIBUTION_POINTS def __init__(self, distribution_points): distribution_points = list(distribution_points) if not all( isinstance(x, DistributionPoint) for x in distribution_points ): raise TypeError( "distribution_points must be a list of DistributionPoint " "objects" ) self._distribution_points = distribution_points __len__, __iter__, __getitem__ = _make_sequence_methods( "_distribution_points" ) def __repr__(self): return "".format(self._distribution_points) def __eq__(self, other): if not isinstance(other, CRLDistributionPoints): return NotImplemented return self._distribution_points == other._distribution_points def __ne__(self, other): return not self == other def __hash__(self): return hash(tuple(self._distribution_points)) @utils.register_interface(ExtensionType) class FreshestCRL(object): oid = ExtensionOID.FRESHEST_CRL def __init__(self, distribution_points): distribution_points = list(distribution_points) if not all( isinstance(x, DistributionPoint) for x in distribution_points ): raise TypeError( "distribution_points must be a list of DistributionPoint " "objects" ) self._distribution_points = distribution_points __len__, __iter__, __getitem__ = _make_sequence_methods( "_distribution_points" ) def __repr__(self): return "".format(self._distribution_points) def __eq__(self, other): if not isinstance(other, FreshestCRL): return NotImplemented return self._distribution_points == other._distribution_points def __ne__(self, other): return not self == other def __hash__(self): return hash(tuple(self._distribution_points)) class DistributionPoint(object): def __init__(self, full_name, relative_name, reasons, crl_issuer): if full_name and relative_name: raise ValueError( "You cannot provide both full_name and relative_name, at " "least one must be None." ) if full_name: full_name = list(full_name) if not all(isinstance(x, GeneralName) for x in full_name): raise TypeError( "full_name must be a list of GeneralName objects" ) if relative_name: if not isinstance(relative_name, RelativeDistinguishedName): raise TypeError( "relative_name must be a RelativeDistinguishedName" ) if crl_issuer: crl_issuer = list(crl_issuer) if not all(isinstance(x, GeneralName) for x in crl_issuer): raise TypeError( "crl_issuer must be None or a list of general names" ) if reasons and (not isinstance(reasons, frozenset) or not all( isinstance(x, ReasonFlags) for x in reasons )): raise TypeError("reasons must be None or frozenset of ReasonFlags") if reasons and ( ReasonFlags.unspecified in reasons or ReasonFlags.remove_from_crl in reasons ): raise ValueError( "unspecified and remove_from_crl are not valid reasons in a " "DistributionPoint" ) if reasons and not crl_issuer and not (full_name or relative_name): raise ValueError( "You must supply crl_issuer, full_name, or relative_name when " "reasons is not None" ) self._full_name = full_name self._relative_name = relative_name self._reasons = reasons self._crl_issuer = crl_issuer def __repr__(self): return ( "" .format(self) ) def __eq__(self, other): if not isinstance(other, DistributionPoint): return NotImplemented return ( self.full_name == other.full_name and self.relative_name == other.relative_name and self.reasons == other.reasons and self.crl_issuer == other.crl_issuer ) def __ne__(self, other): return not self == other def __hash__(self): if self.full_name is not None: fn = tuple(self.full_name) else: fn = None if self.crl_issuer is not None: crl_issuer = tuple(self.crl_issuer) else: crl_issuer = None return hash((fn, self.relative_name, self.reasons, crl_issuer)) full_name = utils.read_only_property("_full_name") relative_name = utils.read_only_property("_relative_name") reasons = utils.read_only_property("_reasons") crl_issuer = utils.read_only_property("_crl_issuer") class ReasonFlags(Enum): unspecified = "unspecified" key_compromise = "keyCompromise" ca_compromise = "cACompromise" affiliation_changed = "affiliationChanged" superseded = "superseded" cessation_of_operation = "cessationOfOperation" certificate_hold = "certificateHold" privilege_withdrawn = "privilegeWithdrawn" aa_compromise = "aACompromise" remove_from_crl = "removeFromCRL" @utils.register_interface(ExtensionType) class PolicyConstraints(object): oid = ExtensionOID.POLICY_CONSTRAINTS def __init__(self, require_explicit_policy, inhibit_policy_mapping): if require_explicit_policy is not None and not isinstance( require_explicit_policy, six.integer_types ): raise TypeError( "require_explicit_policy must be a non-negative integer or " "None" ) if inhibit_policy_mapping is not None and not isinstance( inhibit_policy_mapping, six.integer_types ): raise TypeError( "inhibit_policy_mapping must be a non-negative integer or None" ) if inhibit_policy_mapping is None and require_explicit_policy is None: raise ValueError( "At least one of require_explicit_policy and " "inhibit_policy_mapping must not be None" ) self._require_explicit_policy = require_explicit_policy self._inhibit_policy_mapping = inhibit_policy_mapping def __repr__(self): return ( u"".format(self) ) def __eq__(self, other): if not isinstance(other, PolicyConstraints): return NotImplemented return ( self.require_explicit_policy == other.require_explicit_policy and self.inhibit_policy_mapping == other.inhibit_policy_mapping ) def __ne__(self, other): return not self == other def __hash__(self): return hash( (self.require_explicit_policy, self.inhibit_policy_mapping) ) require_explicit_policy = utils.read_only_property( "_require_explicit_policy" ) inhibit_policy_mapping = utils.read_only_property( "_inhibit_policy_mapping" ) @utils.register_interface(ExtensionType) class CertificatePolicies(object): oid = ExtensionOID.CERTIFICATE_POLICIES def __init__(self, policies): policies = list(policies) if not all(isinstance(x, PolicyInformation) for x in policies): raise TypeError( "Every item in the policies list must be a " "PolicyInformation" ) self._policies = policies __len__, __iter__, __getitem__ = _make_sequence_methods("_policies") def __repr__(self): return "".format(self._policies) def __eq__(self, other): if not isinstance(other, CertificatePolicies): return NotImplemented return self._policies == other._policies def __ne__(self, other): return not self == other def __hash__(self): return hash(tuple(self._policies)) class PolicyInformation(object): def __init__(self, policy_identifier, policy_qualifiers): if not isinstance(policy_identifier, ObjectIdentifier): raise TypeError("policy_identifier must be an ObjectIdentifier") self._policy_identifier = policy_identifier if policy_qualifiers: policy_qualifiers = list(policy_qualifiers) if not all( isinstance(x, (six.text_type, UserNotice)) for x in policy_qualifiers ): raise TypeError( "policy_qualifiers must be a list of strings and/or " "UserNotice objects or None" ) self._policy_qualifiers = policy_qualifiers def __repr__(self): return ( "".format(self) ) def __eq__(self, other): if not isinstance(other, PolicyInformation): return NotImplemented return ( self.policy_identifier == other.policy_identifier and self.policy_qualifiers == other.policy_qualifiers ) def __ne__(self, other): return not self == other def __hash__(self): if self.policy_qualifiers is not None: pq = tuple(self.policy_qualifiers) else: pq = None return hash((self.policy_identifier, pq)) policy_identifier = utils.read_only_property("_policy_identifier") policy_qualifiers = utils.read_only_property("_policy_qualifiers") class UserNotice(object): def __init__(self, notice_reference, explicit_text): if notice_reference and not isinstance( notice_reference, NoticeReference ): raise TypeError( "notice_reference must be None or a NoticeReference" ) self._notice_reference = notice_reference self._explicit_text = explicit_text def __repr__(self): return ( "".format(self) ) def __eq__(self, other): if not isinstance(other, UserNotice): return NotImplemented return ( self.notice_reference == other.notice_reference and self.explicit_text == other.explicit_text ) def __ne__(self, other): return not self == other def __hash__(self): return hash((self.notice_reference, self.explicit_text)) notice_reference = utils.read_only_property("_notice_reference") explicit_text = utils.read_only_property("_explicit_text") class NoticeReference(object): def __init__(self, organization, notice_numbers): self._organization = organization notice_numbers = list(notice_numbers) if not all(isinstance(x, int) for x in notice_numbers): raise TypeError( "notice_numbers must be a list of integers" ) self._notice_numbers = notice_numbers def __repr__(self): return ( "".format(self) ) def __eq__(self, other): if not isinstance(other, NoticeReference): return NotImplemented return ( self.organization == other.organization and self.notice_numbers == other.notice_numbers ) def __ne__(self, other): return not self == other def __hash__(self): return hash((self.organization, tuple(self.notice_numbers))) organization = utils.read_only_property("_organization") notice_numbers = utils.read_only_property("_notice_numbers") @utils.register_interface(ExtensionType) class ExtendedKeyUsage(object): oid = ExtensionOID.EXTENDED_KEY_USAGE def __init__(self, usages): usages = list(usages) if not all(isinstance(x, ObjectIdentifier) for x in usages): raise TypeError( "Every item in the usages list must be an ObjectIdentifier" ) self._usages = usages __len__, __iter__, __getitem__ = _make_sequence_methods("_usages") def __repr__(self): return "".format(self._usages) def __eq__(self, other): if not isinstance(other, ExtendedKeyUsage): return NotImplemented return self._usages == other._usages def __ne__(self, other): return not self == other def __hash__(self): return hash(tuple(self._usages)) @utils.register_interface(ExtensionType) class OCSPNoCheck(object): oid = ExtensionOID.OCSP_NO_CHECK def __eq__(self, other): if not isinstance(other, OCSPNoCheck): return NotImplemented return True def __ne__(self, other): return not self == other def __hash__(self): return hash(OCSPNoCheck) def __repr__(self): return "" @utils.register_interface(ExtensionType) class PrecertPoison(object): oid = ExtensionOID.PRECERT_POISON def __eq__(self, other): if not isinstance(other, PrecertPoison): return NotImplemented return True def __ne__(self, other): return not self == other def __hash__(self): return hash(PrecertPoison) def __repr__(self): return "" @utils.register_interface(ExtensionType) class TLSFeature(object): oid = ExtensionOID.TLS_FEATURE def __init__(self, features): features = list(features) if ( not all(isinstance(x, TLSFeatureType) for x in features) or len(features) == 0 ): raise TypeError( "features must be a list of elements from the TLSFeatureType " "enum" ) self._features = features __len__, __iter__, __getitem__ = _make_sequence_methods("_features") def __repr__(self): return "".format(self) def __eq__(self, other): if not isinstance(other, TLSFeature): return NotImplemented return self._features == other._features def __ne__(self, other): return not self == other def __hash__(self): return hash(tuple(self._features)) class TLSFeatureType(Enum): # status_request is defined in RFC 6066 and is used for what is commonly # called OCSP Must-Staple when present in the TLS Feature extension in an # X.509 certificate. status_request = 5 # status_request_v2 is defined in RFC 6961 and allows multiple OCSP # responses to be provided. It is not currently in use by clients or # servers. status_request_v2 = 17 _TLS_FEATURE_TYPE_TO_ENUM = dict((x.value, x) for x in TLSFeatureType) @utils.register_interface(ExtensionType) class InhibitAnyPolicy(object): oid = ExtensionOID.INHIBIT_ANY_POLICY def __init__(self, skip_certs): if not isinstance(skip_certs, six.integer_types): raise TypeError("skip_certs must be an integer") if skip_certs < 0: raise ValueError("skip_certs must be a non-negative integer") self._skip_certs = skip_certs def __repr__(self): return "".format(self) def __eq__(self, other): if not isinstance(other, InhibitAnyPolicy): return NotImplemented return self.skip_certs == other.skip_certs def __ne__(self, other): return not self == other def __hash__(self): return hash(self.skip_certs) skip_certs = utils.read_only_property("_skip_certs") @utils.register_interface(ExtensionType) class KeyUsage(object): oid = ExtensionOID.KEY_USAGE def __init__(self, digital_signature, content_commitment, key_encipherment, data_encipherment, key_agreement, key_cert_sign, crl_sign, encipher_only, decipher_only): if not key_agreement and (encipher_only or decipher_only): raise ValueError( "encipher_only and decipher_only can only be true when " "key_agreement is true" ) self._digital_signature = digital_signature self._content_commitment = content_commitment self._key_encipherment = key_encipherment self._data_encipherment = data_encipherment self._key_agreement = key_agreement self._key_cert_sign = key_cert_sign self._crl_sign = crl_sign self._encipher_only = encipher_only self._decipher_only = decipher_only digital_signature = utils.read_only_property("_digital_signature") content_commitment = utils.read_only_property("_content_commitment") key_encipherment = utils.read_only_property("_key_encipherment") data_encipherment = utils.read_only_property("_data_encipherment") key_agreement = utils.read_only_property("_key_agreement") key_cert_sign = utils.read_only_property("_key_cert_sign") crl_sign = utils.read_only_property("_crl_sign") @property def encipher_only(self): if not self.key_agreement: raise ValueError( "encipher_only is undefined unless key_agreement is true" ) else: return self._encipher_only @property def decipher_only(self): if not self.key_agreement: raise ValueError( "decipher_only is undefined unless key_agreement is true" ) else: return self._decipher_only def __repr__(self): try: encipher_only = self.encipher_only decipher_only = self.decipher_only except ValueError: encipher_only = None decipher_only = None return ("").format( self, encipher_only, decipher_only) def __eq__(self, other): if not isinstance(other, KeyUsage): return NotImplemented return ( self.digital_signature == other.digital_signature and self.content_commitment == other.content_commitment and self.key_encipherment == other.key_encipherment and self.data_encipherment == other.data_encipherment and self.key_agreement == other.key_agreement and self.key_cert_sign == other.key_cert_sign and self.crl_sign == other.crl_sign and self._encipher_only == other._encipher_only and self._decipher_only == other._decipher_only ) def __ne__(self, other): return not self == other def __hash__(self): return hash(( self.digital_signature, self.content_commitment, self.key_encipherment, self.data_encipherment, self.key_agreement, self.key_cert_sign, self.crl_sign, self._encipher_only, self._decipher_only )) @utils.register_interface(ExtensionType) class NameConstraints(object): oid = ExtensionOID.NAME_CONSTRAINTS def __init__(self, permitted_subtrees, excluded_subtrees): if permitted_subtrees is not None: permitted_subtrees = list(permitted_subtrees) if not all( isinstance(x, GeneralName) for x in permitted_subtrees ): raise TypeError( "permitted_subtrees must be a list of GeneralName objects " "or None" ) self._validate_ip_name(permitted_subtrees) if excluded_subtrees is not None: excluded_subtrees = list(excluded_subtrees) if not all( isinstance(x, GeneralName) for x in excluded_subtrees ): raise TypeError( "excluded_subtrees must be a list of GeneralName objects " "or None" ) self._validate_ip_name(excluded_subtrees) if permitted_subtrees is None and excluded_subtrees is None: raise ValueError( "At least one of permitted_subtrees and excluded_subtrees " "must not be None" ) self._permitted_subtrees = permitted_subtrees self._excluded_subtrees = excluded_subtrees def __eq__(self, other): if not isinstance(other, NameConstraints): return NotImplemented return ( self.excluded_subtrees == other.excluded_subtrees and self.permitted_subtrees == other.permitted_subtrees ) def __ne__(self, other): return not self == other def _validate_ip_name(self, tree): if any(isinstance(name, IPAddress) and not isinstance( name.value, (ipaddress.IPv4Network, ipaddress.IPv6Network) ) for name in tree): raise TypeError( "IPAddress name constraints must be an IPv4Network or" " IPv6Network object" ) def __repr__(self): return ( u"".format(self) ) def __hash__(self): if self.permitted_subtrees is not None: ps = tuple(self.permitted_subtrees) else: ps = None if self.excluded_subtrees is not None: es = tuple(self.excluded_subtrees) else: es = None return hash((ps, es)) permitted_subtrees = utils.read_only_property("_permitted_subtrees") excluded_subtrees = utils.read_only_property("_excluded_subtrees") class Extension(object): def __init__(self, oid, critical, value): if not isinstance(oid, ObjectIdentifier): raise TypeError( "oid argument must be an ObjectIdentifier instance." ) if not isinstance(critical, bool): raise TypeError("critical must be a boolean value") self._oid = oid self._critical = critical self._value = value oid = utils.read_only_property("_oid") critical = utils.read_only_property("_critical") value = utils.read_only_property("_value") def __repr__(self): return ("").format(self) def __eq__(self, other): if not isinstance(other, Extension): return NotImplemented return ( self.oid == other.oid and self.critical == other.critical and self.value == other.value ) def __ne__(self, other): return not self == other def __hash__(self): return hash((self.oid, self.critical, self.value)) class GeneralNames(object): def __init__(self, general_names): general_names = list(general_names) if not all(isinstance(x, GeneralName) for x in general_names): raise TypeError( "Every item in the general_names list must be an " "object conforming to the GeneralName interface" ) self._general_names = general_names __len__, __iter__, __getitem__ = _make_sequence_methods("_general_names") def get_values_for_type(self, type): # Return the value of each GeneralName, except for OtherName instances # which we return directly because it has two important properties not # just one value. objs = (i for i in self if isinstance(i, type)) if type != OtherName: objs = (i.value for i in objs) return list(objs) def __repr__(self): return "".format(self._general_names) def __eq__(self, other): if not isinstance(other, GeneralNames): return NotImplemented return self._general_names == other._general_names def __ne__(self, other): return not self == other def __hash__(self): return hash(tuple(self._general_names)) @utils.register_interface(ExtensionType) class SubjectAlternativeName(object): oid = ExtensionOID.SUBJECT_ALTERNATIVE_NAME def __init__(self, general_names): self._general_names = GeneralNames(general_names) __len__, __iter__, __getitem__ = _make_sequence_methods("_general_names") def get_values_for_type(self, type): return self._general_names.get_values_for_type(type) def __repr__(self): return "".format(self._general_names) def __eq__(self, other): if not isinstance(other, SubjectAlternativeName): return NotImplemented return self._general_names == other._general_names def __ne__(self, other): return not self == other def __hash__(self): return hash(self._general_names) @utils.register_interface(ExtensionType) class IssuerAlternativeName(object): oid = ExtensionOID.ISSUER_ALTERNATIVE_NAME def __init__(self, general_names): self._general_names = GeneralNames(general_names) __len__, __iter__, __getitem__ = _make_sequence_methods("_general_names") def get_values_for_type(self, type): return self._general_names.get_values_for_type(type) def __repr__(self): return "".format(self._general_names) def __eq__(self, other): if not isinstance(other, IssuerAlternativeName): return NotImplemented return self._general_names == other._general_names def __ne__(self, other): return not self == other def __hash__(self): return hash(self._general_names) @utils.register_interface(ExtensionType) class CertificateIssuer(object): oid = CRLEntryExtensionOID.CERTIFICATE_ISSUER def __init__(self, general_names): self._general_names = GeneralNames(general_names) __len__, __iter__, __getitem__ = _make_sequence_methods("_general_names") def get_values_for_type(self, type): return self._general_names.get_values_for_type(type) def __repr__(self): return "".format(self._general_names) def __eq__(self, other): if not isinstance(other, CertificateIssuer): return NotImplemented return self._general_names == other._general_names def __ne__(self, other): return not self == other def __hash__(self): return hash(self._general_names) @utils.register_interface(ExtensionType) class CRLReason(object): oid = CRLEntryExtensionOID.CRL_REASON def __init__(self, reason): if not isinstance(reason, ReasonFlags): raise TypeError("reason must be an element from ReasonFlags") self._reason = reason def __repr__(self): return "".format(self._reason) def __eq__(self, other): if not isinstance(other, CRLReason): return NotImplemented return self.reason == other.reason def __ne__(self, other): return not self == other def __hash__(self): return hash(self.reason) reason = utils.read_only_property("_reason") @utils.register_interface(ExtensionType) class InvalidityDate(object): oid = CRLEntryExtensionOID.INVALIDITY_DATE def __init__(self, invalidity_date): if not isinstance(invalidity_date, datetime.datetime): raise TypeError("invalidity_date must be a datetime.datetime") self._invalidity_date = invalidity_date def __repr__(self): return "".format( self._invalidity_date ) def __eq__(self, other): if not isinstance(other, InvalidityDate): return NotImplemented return self.invalidity_date == other.invalidity_date def __ne__(self, other): return not self == other def __hash__(self): return hash(self.invalidity_date) invalidity_date = utils.read_only_property("_invalidity_date") @utils.register_interface(ExtensionType) class PrecertificateSignedCertificateTimestamps(object): oid = ExtensionOID.PRECERT_SIGNED_CERTIFICATE_TIMESTAMPS def __init__(self, signed_certificate_timestamps): signed_certificate_timestamps = list(signed_certificate_timestamps) if not all( isinstance(sct, SignedCertificateTimestamp) for sct in signed_certificate_timestamps ): raise TypeError( "Every item in the signed_certificate_timestamps list must be " "a SignedCertificateTimestamp" ) self._signed_certificate_timestamps = signed_certificate_timestamps __len__, __iter__, __getitem__ = _make_sequence_methods( "_signed_certificate_timestamps" ) def __repr__(self): return ( "".format( list(self) ) ) def __hash__(self): return hash(tuple(self._signed_certificate_timestamps)) def __eq__(self, other): if not isinstance(other, PrecertificateSignedCertificateTimestamps): return NotImplemented return ( self._signed_certificate_timestamps == other._signed_certificate_timestamps ) def __ne__(self, other): return not self == other @utils.register_interface(ExtensionType) class OCSPNonce(object): oid = OCSPExtensionOID.NONCE def __init__(self, nonce): if not isinstance(nonce, bytes): raise TypeError("nonce must be bytes") self._nonce = nonce def __eq__(self, other): if not isinstance(other, OCSPNonce): return NotImplemented return self.nonce == other.nonce def __ne__(self, other): return not self == other def __hash__(self): return hash(self.nonce) def __repr__(self): return "".format(self) nonce = utils.read_only_property("_nonce") @utils.register_interface(ExtensionType) class IssuingDistributionPoint(object): oid = ExtensionOID.ISSUING_DISTRIBUTION_POINT def __init__(self, full_name, relative_name, only_contains_user_certs, only_contains_ca_certs, only_some_reasons, indirect_crl, only_contains_attribute_certs): if ( only_some_reasons and ( not isinstance(only_some_reasons, frozenset) or not all( isinstance(x, ReasonFlags) for x in only_some_reasons ) ) ): raise TypeError( "only_some_reasons must be None or frozenset of ReasonFlags" ) if only_some_reasons and ( ReasonFlags.unspecified in only_some_reasons or ReasonFlags.remove_from_crl in only_some_reasons ): raise ValueError( "unspecified and remove_from_crl are not valid reasons in an " "IssuingDistributionPoint" ) if not ( isinstance(only_contains_user_certs, bool) and isinstance(only_contains_ca_certs, bool) and isinstance(indirect_crl, bool) and isinstance(only_contains_attribute_certs, bool) ): raise TypeError( "only_contains_user_certs, only_contains_ca_certs, " "indirect_crl and only_contains_attribute_certs " "must all be boolean." ) crl_constraints = [ only_contains_user_certs, only_contains_ca_certs, indirect_crl, only_contains_attribute_certs ] if len([x for x in crl_constraints if x]) > 1: raise ValueError( "Only one of the following can be set to True: " "only_contains_user_certs, only_contains_ca_certs, " "indirect_crl, only_contains_attribute_certs" ) if ( not any([ only_contains_user_certs, only_contains_ca_certs, indirect_crl, only_contains_attribute_certs, full_name, relative_name, only_some_reasons ]) ): raise ValueError( "Cannot create empty extension: " "if only_contains_user_certs, only_contains_ca_certs, " "indirect_crl, and only_contains_attribute_certs are all False" ", then either full_name, relative_name, or only_some_reasons " "must have a value." ) self._only_contains_user_certs = only_contains_user_certs self._only_contains_ca_certs = only_contains_ca_certs self._indirect_crl = indirect_crl self._only_contains_attribute_certs = only_contains_attribute_certs self._only_some_reasons = only_some_reasons self._full_name = full_name self._relative_name = relative_name def __repr__(self): return ( "".format(self) ) def __eq__(self, other): if not isinstance(other, IssuingDistributionPoint): return NotImplemented return ( self.full_name == other.full_name and self.relative_name == other.relative_name and self.only_contains_user_certs == other.only_contains_user_certs and self.only_contains_ca_certs == other.only_contains_ca_certs and self.only_some_reasons == other.only_some_reasons and self.indirect_crl == other.indirect_crl and self.only_contains_attribute_certs == other.only_contains_attribute_certs ) def __ne__(self, other): return not self == other def __hash__(self): return hash(( self.full_name, self.relative_name, self.only_contains_user_certs, self.only_contains_ca_certs, self.only_some_reasons, self.indirect_crl, self.only_contains_attribute_certs, )) full_name = utils.read_only_property("_full_name") relative_name = utils.read_only_property("_relative_name") only_contains_user_certs = utils.read_only_property( "_only_contains_user_certs" ) only_contains_ca_certs = utils.read_only_property( "_only_contains_ca_certs" ) only_some_reasons = utils.read_only_property("_only_some_reasons") indirect_crl = utils.read_only_property("_indirect_crl") only_contains_attribute_certs = utils.read_only_property( "_only_contains_attribute_certs" ) @utils.register_interface(ExtensionType) class UnrecognizedExtension(object): def __init__(self, oid, value): if not isinstance(oid, ObjectIdentifier): raise TypeError("oid must be an ObjectIdentifier") self._oid = oid self._value = value oid = utils.read_only_property("_oid") value = utils.read_only_property("_value") def __repr__(self): return ( "".format( self ) ) def __eq__(self, other): if not isinstance(other, UnrecognizedExtension): return NotImplemented return self.oid == other.oid and self.value == other.value def __ne__(self, other): return not self == other def __hash__(self): return hash((self.oid, self.value)) ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/cryptography/x509/general_name.py ================================================ # This file is dual licensed under the terms of the Apache License, Version # 2.0, and the BSD License. See the LICENSE file in the root of this repository # for complete details. from __future__ import absolute_import, division, print_function import abc import ipaddress import warnings from email.utils import parseaddr import six from six.moves import urllib_parse from cryptography import utils from cryptography.x509.name import Name from cryptography.x509.oid import ObjectIdentifier _GENERAL_NAMES = { 0: "otherName", 1: "rfc822Name", 2: "dNSName", 3: "x400Address", 4: "directoryName", 5: "ediPartyName", 6: "uniformResourceIdentifier", 7: "iPAddress", 8: "registeredID", } def _lazy_import_idna(): # Import idna lazily becase it allocates a decent amount of memory, and # we're only using it in deprecated paths. try: import idna return idna except ImportError: raise ImportError( "idna is not installed, but a deprecated feature that requires it" " was used. See: https://cryptography.io/en/latest/faq/#importe" "rror-idna-is-not-installed" ) class UnsupportedGeneralNameType(Exception): def __init__(self, msg, type): super(UnsupportedGeneralNameType, self).__init__(msg) self.type = type @six.add_metaclass(abc.ABCMeta) class GeneralName(object): @abc.abstractproperty def value(self): """ Return the value of the object """ @utils.register_interface(GeneralName) class RFC822Name(object): def __init__(self, value): if isinstance(value, six.text_type): try: value.encode("ascii") except UnicodeEncodeError: value = self._idna_encode(value) warnings.warn( "RFC822Name values should be passed as an A-label string. " "This means unicode characters should be encoded via " "idna. Support for passing unicode strings (aka U-label) " "will be removed in a future version.", utils.PersistentlyDeprecated2017, stacklevel=2, ) else: raise TypeError("value must be string") name, address = parseaddr(value) if name or not address: # parseaddr has found a name (e.g. Name ) or the entire # value is an empty string. raise ValueError("Invalid rfc822name value") self._value = value value = utils.read_only_property("_value") @classmethod def _init_without_validation(cls, value): instance = cls.__new__(cls) instance._value = value return instance def _idna_encode(self, value): idna = _lazy_import_idna() _, address = parseaddr(value) parts = address.split(u"@") return parts[0] + "@" + idna.encode(parts[1]).decode("ascii") def __repr__(self): return "".format(self.value) def __eq__(self, other): if not isinstance(other, RFC822Name): return NotImplemented return self.value == other.value def __ne__(self, other): return not self == other def __hash__(self): return hash(self.value) def _idna_encode(value): idna = _lazy_import_idna() # Retain prefixes '*.' for common/alt names and '.' for name constraints for prefix in ['*.', '.']: if value.startswith(prefix): value = value[len(prefix):] return prefix + idna.encode(value).decode("ascii") return idna.encode(value).decode("ascii") @utils.register_interface(GeneralName) class DNSName(object): def __init__(self, value): if isinstance(value, six.text_type): try: value.encode("ascii") except UnicodeEncodeError: value = _idna_encode(value) warnings.warn( "DNSName values should be passed as an A-label string. " "This means unicode characters should be encoded via " "idna. Support for passing unicode strings (aka U-label) " "will be removed in a future version.", utils.PersistentlyDeprecated2017, stacklevel=2, ) else: raise TypeError("value must be string") self._value = value value = utils.read_only_property("_value") @classmethod def _init_without_validation(cls, value): instance = cls.__new__(cls) instance._value = value return instance def __repr__(self): return "".format(self.value) def __eq__(self, other): if not isinstance(other, DNSName): return NotImplemented return self.value == other.value def __ne__(self, other): return not self == other def __hash__(self): return hash(self.value) @utils.register_interface(GeneralName) class UniformResourceIdentifier(object): def __init__(self, value): if isinstance(value, six.text_type): try: value.encode("ascii") except UnicodeEncodeError: value = self._idna_encode(value) warnings.warn( "URI values should be passed as an A-label string. " "This means unicode characters should be encoded via " "idna. Support for passing unicode strings (aka U-label) " " will be removed in a future version.", utils.PersistentlyDeprecated2017, stacklevel=2, ) else: raise TypeError("value must be string") self._value = value value = utils.read_only_property("_value") @classmethod def _init_without_validation(cls, value): instance = cls.__new__(cls) instance._value = value return instance def _idna_encode(self, value): idna = _lazy_import_idna() parsed = urllib_parse.urlparse(value) if parsed.port: netloc = ( idna.encode(parsed.hostname) + ":{}".format(parsed.port).encode("ascii") ).decode("ascii") else: netloc = idna.encode(parsed.hostname).decode("ascii") # Note that building a URL in this fashion means it should be # semantically indistinguishable from the original but is not # guaranteed to be exactly the same. return urllib_parse.urlunparse(( parsed.scheme, netloc, parsed.path, parsed.params, parsed.query, parsed.fragment )) def __repr__(self): return "".format(self.value) def __eq__(self, other): if not isinstance(other, UniformResourceIdentifier): return NotImplemented return self.value == other.value def __ne__(self, other): return not self == other def __hash__(self): return hash(self.value) @utils.register_interface(GeneralName) class DirectoryName(object): def __init__(self, value): if not isinstance(value, Name): raise TypeError("value must be a Name") self._value = value value = utils.read_only_property("_value") def __repr__(self): return "".format(self.value) def __eq__(self, other): if not isinstance(other, DirectoryName): return NotImplemented return self.value == other.value def __ne__(self, other): return not self == other def __hash__(self): return hash(self.value) @utils.register_interface(GeneralName) class RegisteredID(object): def __init__(self, value): if not isinstance(value, ObjectIdentifier): raise TypeError("value must be an ObjectIdentifier") self._value = value value = utils.read_only_property("_value") def __repr__(self): return "".format(self.value) def __eq__(self, other): if not isinstance(other, RegisteredID): return NotImplemented return self.value == other.value def __ne__(self, other): return not self == other def __hash__(self): return hash(self.value) @utils.register_interface(GeneralName) class IPAddress(object): def __init__(self, value): if not isinstance( value, ( ipaddress.IPv4Address, ipaddress.IPv6Address, ipaddress.IPv4Network, ipaddress.IPv6Network ) ): raise TypeError( "value must be an instance of ipaddress.IPv4Address, " "ipaddress.IPv6Address, ipaddress.IPv4Network, or " "ipaddress.IPv6Network" ) self._value = value value = utils.read_only_property("_value") def __repr__(self): return "".format(self.value) def __eq__(self, other): if not isinstance(other, IPAddress): return NotImplemented return self.value == other.value def __ne__(self, other): return not self == other def __hash__(self): return hash(self.value) @utils.register_interface(GeneralName) class OtherName(object): def __init__(self, type_id, value): if not isinstance(type_id, ObjectIdentifier): raise TypeError("type_id must be an ObjectIdentifier") if not isinstance(value, bytes): raise TypeError("value must be a binary string") self._type_id = type_id self._value = value type_id = utils.read_only_property("_type_id") value = utils.read_only_property("_value") def __repr__(self): return "".format( self.type_id, self.value) def __eq__(self, other): if not isinstance(other, OtherName): return NotImplemented return self.type_id == other.type_id and self.value == other.value def __ne__(self, other): return not self == other def __hash__(self): return hash((self.type_id, self.value)) ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/cryptography/x509/name.py ================================================ # This file is dual licensed under the terms of the Apache License, Version # 2.0, and the BSD License. See the LICENSE file in the root of this repository # for complete details. from __future__ import absolute_import, division, print_function from enum import Enum import six from cryptography import utils from cryptography.x509.oid import NameOID, ObjectIdentifier class _ASN1Type(Enum): UTF8String = 12 NumericString = 18 PrintableString = 19 T61String = 20 IA5String = 22 UTCTime = 23 GeneralizedTime = 24 VisibleString = 26 UniversalString = 28 BMPString = 30 _ASN1_TYPE_TO_ENUM = dict((i.value, i) for i in _ASN1Type) _SENTINEL = object() _NAMEOID_DEFAULT_TYPE = { NameOID.COUNTRY_NAME: _ASN1Type.PrintableString, NameOID.JURISDICTION_COUNTRY_NAME: _ASN1Type.PrintableString, NameOID.SERIAL_NUMBER: _ASN1Type.PrintableString, NameOID.DN_QUALIFIER: _ASN1Type.PrintableString, NameOID.EMAIL_ADDRESS: _ASN1Type.IA5String, NameOID.DOMAIN_COMPONENT: _ASN1Type.IA5String, } #: Short attribute names from RFC 4514: #: https://tools.ietf.org/html/rfc4514#page-7 _NAMEOID_TO_NAME = { NameOID.COMMON_NAME: 'CN', NameOID.LOCALITY_NAME: 'L', NameOID.STATE_OR_PROVINCE_NAME: 'ST', NameOID.ORGANIZATION_NAME: 'O', NameOID.ORGANIZATIONAL_UNIT_NAME: 'OU', NameOID.COUNTRY_NAME: 'C', NameOID.STREET_ADDRESS: 'STREET', NameOID.DOMAIN_COMPONENT: 'DC', NameOID.USER_ID: 'UID', } def _escape_dn_value(val): """Escape special characters in RFC4514 Distinguished Name value.""" # See https://tools.ietf.org/html/rfc4514#section-2.4 val = val.replace('\\', '\\\\') val = val.replace('"', '\\"') val = val.replace('+', '\\+') val = val.replace(',', '\\,') val = val.replace(';', '\\;') val = val.replace('<', '\\<') val = val.replace('>', '\\>') val = val.replace('\0', '\\00') if val[0] in ('#', ' '): val = '\\' + val if val[-1] == ' ': val = val[:-1] + '\\ ' return val class NameAttribute(object): def __init__(self, oid, value, _type=_SENTINEL): if not isinstance(oid, ObjectIdentifier): raise TypeError( "oid argument must be an ObjectIdentifier instance." ) if not isinstance(value, six.text_type): raise TypeError( "value argument must be a text type." ) if ( oid == NameOID.COUNTRY_NAME or oid == NameOID.JURISDICTION_COUNTRY_NAME ): if len(value.encode("utf8")) != 2: raise ValueError( "Country name must be a 2 character country code" ) if len(value) == 0: raise ValueError("Value cannot be an empty string") # The appropriate ASN1 string type varies by OID and is defined across # multiple RFCs including 2459, 3280, and 5280. In general UTF8String # is preferred (2459), but 3280 and 5280 specify several OIDs with # alternate types. This means when we see the sentinel value we need # to look up whether the OID has a non-UTF8 type. If it does, set it # to that. Otherwise, UTF8! if _type == _SENTINEL: _type = _NAMEOID_DEFAULT_TYPE.get(oid, _ASN1Type.UTF8String) if not isinstance(_type, _ASN1Type): raise TypeError("_type must be from the _ASN1Type enum") self._oid = oid self._value = value self._type = _type oid = utils.read_only_property("_oid") value = utils.read_only_property("_value") def rfc4514_string(self): """ Format as RFC4514 Distinguished Name string. Use short attribute name if available, otherwise fall back to OID dotted string. """ key = _NAMEOID_TO_NAME.get(self.oid, self.oid.dotted_string) return '%s=%s' % (key, _escape_dn_value(self.value)) def __eq__(self, other): if not isinstance(other, NameAttribute): return NotImplemented return ( self.oid == other.oid and self.value == other.value ) def __ne__(self, other): return not self == other def __hash__(self): return hash((self.oid, self.value)) def __repr__(self): return "".format(self) class RelativeDistinguishedName(object): def __init__(self, attributes): attributes = list(attributes) if not attributes: raise ValueError("a relative distinguished name cannot be empty") if not all(isinstance(x, NameAttribute) for x in attributes): raise TypeError("attributes must be an iterable of NameAttribute") # Keep list and frozenset to preserve attribute order where it matters self._attributes = attributes self._attribute_set = frozenset(attributes) if len(self._attribute_set) != len(attributes): raise ValueError("duplicate attributes are not allowed") def get_attributes_for_oid(self, oid): return [i for i in self if i.oid == oid] def rfc4514_string(self): """ Format as RFC4514 Distinguished Name string. Within each RDN, attributes are joined by '+', although that is rarely used in certificates. """ return '+'.join(attr.rfc4514_string() for attr in self._attributes) def __eq__(self, other): if not isinstance(other, RelativeDistinguishedName): return NotImplemented return self._attribute_set == other._attribute_set def __ne__(self, other): return not self == other def __hash__(self): return hash(self._attribute_set) def __iter__(self): return iter(self._attributes) def __len__(self): return len(self._attributes) def __repr__(self): return "".format(self.rfc4514_string()) class Name(object): def __init__(self, attributes): attributes = list(attributes) if all(isinstance(x, NameAttribute) for x in attributes): self._attributes = [ RelativeDistinguishedName([x]) for x in attributes ] elif all(isinstance(x, RelativeDistinguishedName) for x in attributes): self._attributes = attributes else: raise TypeError( "attributes must be a list of NameAttribute" " or a list RelativeDistinguishedName" ) def rfc4514_string(self): """ Format as RFC4514 Distinguished Name string. For example 'CN=foobar.com,O=Foo Corp,C=US' An X.509 name is a two-level structure: a list of sets of attributes. Each list element is separated by ',' and within each list element, set elements are separated by '+'. The latter is almost never used in real world certificates. """ return ','.join(attr.rfc4514_string() for attr in self._attributes) def get_attributes_for_oid(self, oid): return [i for i in self if i.oid == oid] @property def rdns(self): return self._attributes def public_bytes(self, backend): return backend.x509_name_bytes(self) def __eq__(self, other): if not isinstance(other, Name): return NotImplemented return self._attributes == other._attributes def __ne__(self, other): return not self == other def __hash__(self): # TODO: this is relatively expensive, if this looks like a bottleneck # for you, consider optimizing! return hash(tuple(self._attributes)) def __iter__(self): for rdn in self._attributes: for ava in rdn: yield ava def __len__(self): return sum(len(rdn) for rdn in self._attributes) def __repr__(self): if six.PY2: return "".format(self.rfc4514_string().encode('utf8')) else: return "".format(self.rfc4514_string()) ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/cryptography/x509/ocsp.py ================================================ # This file is dual licensed under the terms of the Apache License, Version # 2.0, and the BSD License. See the LICENSE file in the root of this repository # for complete details. from __future__ import absolute_import, division, print_function import abc import datetime from enum import Enum import six from cryptography import x509 from cryptography.hazmat.primitives import hashes from cryptography.hazmat.primitives.asymmetric import ed25519, ed448 from cryptography.x509.base import ( _EARLIEST_UTC_TIME, _convert_to_naive_utc_time, _reject_duplicate_extension ) _OIDS_TO_HASH = { "1.3.14.3.2.26": hashes.SHA1(), "2.16.840.1.101.3.4.2.4": hashes.SHA224(), "2.16.840.1.101.3.4.2.1": hashes.SHA256(), "2.16.840.1.101.3.4.2.2": hashes.SHA384(), "2.16.840.1.101.3.4.2.3": hashes.SHA512(), } class OCSPResponderEncoding(Enum): HASH = "By Hash" NAME = "By Name" class OCSPResponseStatus(Enum): SUCCESSFUL = 0 MALFORMED_REQUEST = 1 INTERNAL_ERROR = 2 TRY_LATER = 3 SIG_REQUIRED = 5 UNAUTHORIZED = 6 _RESPONSE_STATUS_TO_ENUM = dict((x.value, x) for x in OCSPResponseStatus) _ALLOWED_HASHES = ( hashes.SHA1, hashes.SHA224, hashes.SHA256, hashes.SHA384, hashes.SHA512 ) def _verify_algorithm(algorithm): if not isinstance(algorithm, _ALLOWED_HASHES): raise ValueError( "Algorithm must be SHA1, SHA224, SHA256, SHA384, or SHA512" ) class OCSPCertStatus(Enum): GOOD = 0 REVOKED = 1 UNKNOWN = 2 _CERT_STATUS_TO_ENUM = dict((x.value, x) for x in OCSPCertStatus) def load_der_ocsp_request(data): from cryptography.hazmat.backends.openssl.backend import backend return backend.load_der_ocsp_request(data) def load_der_ocsp_response(data): from cryptography.hazmat.backends.openssl.backend import backend return backend.load_der_ocsp_response(data) class OCSPRequestBuilder(object): def __init__(self, request=None, extensions=[]): self._request = request self._extensions = extensions def add_certificate(self, cert, issuer, algorithm): if self._request is not None: raise ValueError("Only one certificate can be added to a request") _verify_algorithm(algorithm) if ( not isinstance(cert, x509.Certificate) or not isinstance(issuer, x509.Certificate) ): raise TypeError("cert and issuer must be a Certificate") return OCSPRequestBuilder((cert, issuer, algorithm), self._extensions) def add_extension(self, extension, critical): if not isinstance(extension, x509.ExtensionType): raise TypeError("extension must be an ExtensionType") extension = x509.Extension(extension.oid, critical, extension) _reject_duplicate_extension(extension, self._extensions) return OCSPRequestBuilder( self._request, self._extensions + [extension] ) def build(self): from cryptography.hazmat.backends.openssl.backend import backend if self._request is None: raise ValueError("You must add a certificate before building") return backend.create_ocsp_request(self) class _SingleResponse(object): def __init__(self, cert, issuer, algorithm, cert_status, this_update, next_update, revocation_time, revocation_reason): if ( not isinstance(cert, x509.Certificate) or not isinstance(issuer, x509.Certificate) ): raise TypeError("cert and issuer must be a Certificate") _verify_algorithm(algorithm) if not isinstance(this_update, datetime.datetime): raise TypeError("this_update must be a datetime object") if ( next_update is not None and not isinstance(next_update, datetime.datetime) ): raise TypeError("next_update must be a datetime object or None") self._cert = cert self._issuer = issuer self._algorithm = algorithm self._this_update = this_update self._next_update = next_update if not isinstance(cert_status, OCSPCertStatus): raise TypeError( "cert_status must be an item from the OCSPCertStatus enum" ) if cert_status is not OCSPCertStatus.REVOKED: if revocation_time is not None: raise ValueError( "revocation_time can only be provided if the certificate " "is revoked" ) if revocation_reason is not None: raise ValueError( "revocation_reason can only be provided if the certificate" " is revoked" ) else: if not isinstance(revocation_time, datetime.datetime): raise TypeError("revocation_time must be a datetime object") revocation_time = _convert_to_naive_utc_time(revocation_time) if revocation_time < _EARLIEST_UTC_TIME: raise ValueError('The revocation_time must be on or after' ' 1950 January 1.') if ( revocation_reason is not None and not isinstance(revocation_reason, x509.ReasonFlags) ): raise TypeError( "revocation_reason must be an item from the ReasonFlags " "enum or None" ) self._cert_status = cert_status self._revocation_time = revocation_time self._revocation_reason = revocation_reason class OCSPResponseBuilder(object): def __init__(self, response=None, responder_id=None, certs=None, extensions=[]): self._response = response self._responder_id = responder_id self._certs = certs self._extensions = extensions def add_response(self, cert, issuer, algorithm, cert_status, this_update, next_update, revocation_time, revocation_reason): if self._response is not None: raise ValueError("Only one response per OCSPResponse.") singleresp = _SingleResponse( cert, issuer, algorithm, cert_status, this_update, next_update, revocation_time, revocation_reason ) return OCSPResponseBuilder( singleresp, self._responder_id, self._certs, self._extensions, ) def responder_id(self, encoding, responder_cert): if self._responder_id is not None: raise ValueError("responder_id can only be set once") if not isinstance(responder_cert, x509.Certificate): raise TypeError("responder_cert must be a Certificate") if not isinstance(encoding, OCSPResponderEncoding): raise TypeError( "encoding must be an element from OCSPResponderEncoding" ) return OCSPResponseBuilder( self._response, (responder_cert, encoding), self._certs, self._extensions, ) def certificates(self, certs): if self._certs is not None: raise ValueError("certificates may only be set once") certs = list(certs) if len(certs) == 0: raise ValueError("certs must not be an empty list") if not all(isinstance(x, x509.Certificate) for x in certs): raise TypeError("certs must be a list of Certificates") return OCSPResponseBuilder( self._response, self._responder_id, certs, self._extensions, ) def add_extension(self, extension, critical): if not isinstance(extension, x509.ExtensionType): raise TypeError("extension must be an ExtensionType") extension = x509.Extension(extension.oid, critical, extension) _reject_duplicate_extension(extension, self._extensions) return OCSPResponseBuilder( self._response, self._responder_id, self._certs, self._extensions + [extension], ) def sign(self, private_key, algorithm): from cryptography.hazmat.backends.openssl.backend import backend if self._response is None: raise ValueError("You must add a response before signing") if self._responder_id is None: raise ValueError("You must add a responder_id before signing") if isinstance(private_key, (ed25519.Ed25519PrivateKey, ed448.Ed448PrivateKey)): if algorithm is not None: raise ValueError( "algorithm must be None when signing via ed25519 or ed448" ) elif not isinstance(algorithm, hashes.HashAlgorithm): raise TypeError("Algorithm must be a registered hash algorithm.") return backend.create_ocsp_response( OCSPResponseStatus.SUCCESSFUL, self, private_key, algorithm ) @classmethod def build_unsuccessful(cls, response_status): from cryptography.hazmat.backends.openssl.backend import backend if not isinstance(response_status, OCSPResponseStatus): raise TypeError( "response_status must be an item from OCSPResponseStatus" ) if response_status is OCSPResponseStatus.SUCCESSFUL: raise ValueError("response_status cannot be SUCCESSFUL") return backend.create_ocsp_response(response_status, None, None, None) @six.add_metaclass(abc.ABCMeta) class OCSPRequest(object): @abc.abstractproperty def issuer_key_hash(self): """ The hash of the issuer public key """ @abc.abstractproperty def issuer_name_hash(self): """ The hash of the issuer name """ @abc.abstractproperty def hash_algorithm(self): """ The hash algorithm used in the issuer name and key hashes """ @abc.abstractproperty def serial_number(self): """ The serial number of the cert whose status is being checked """ @abc.abstractmethod def public_bytes(self, encoding): """ Serializes the request to DER """ @abc.abstractproperty def extensions(self): """ The list of request extensions. Not single request extensions. """ @six.add_metaclass(abc.ABCMeta) class OCSPResponse(object): @abc.abstractproperty def response_status(self): """ The status of the response. This is a value from the OCSPResponseStatus enumeration """ @abc.abstractproperty def signature_algorithm_oid(self): """ The ObjectIdentifier of the signature algorithm """ @abc.abstractproperty def signature_hash_algorithm(self): """ Returns a HashAlgorithm corresponding to the type of the digest signed """ @abc.abstractproperty def signature(self): """ The signature bytes """ @abc.abstractproperty def tbs_response_bytes(self): """ The tbsResponseData bytes """ @abc.abstractproperty def certificates(self): """ A list of certificates used to help build a chain to verify the OCSP response. This situation occurs when the OCSP responder uses a delegate certificate. """ @abc.abstractproperty def responder_key_hash(self): """ The responder's key hash or None """ @abc.abstractproperty def responder_name(self): """ The responder's Name or None """ @abc.abstractproperty def produced_at(self): """ The time the response was produced """ @abc.abstractproperty def certificate_status(self): """ The status of the certificate (an element from the OCSPCertStatus enum) """ @abc.abstractproperty def revocation_time(self): """ The date of when the certificate was revoked or None if not revoked. """ @abc.abstractproperty def revocation_reason(self): """ The reason the certificate was revoked or None if not specified or not revoked. """ @abc.abstractproperty def this_update(self): """ The most recent time at which the status being indicated is known by the responder to have been correct """ @abc.abstractproperty def next_update(self): """ The time when newer information will be available """ @abc.abstractproperty def issuer_key_hash(self): """ The hash of the issuer public key """ @abc.abstractproperty def issuer_name_hash(self): """ The hash of the issuer name """ @abc.abstractproperty def hash_algorithm(self): """ The hash algorithm used in the issuer name and key hashes """ @abc.abstractproperty def serial_number(self): """ The serial number of the cert whose status is being checked """ @abc.abstractproperty def extensions(self): """ The list of response extensions. Not single response extensions. """ ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/cryptography/x509/oid.py ================================================ # This file is dual licensed under the terms of the Apache License, Version # 2.0, and the BSD License. See the LICENSE file in the root of this repository # for complete details. from __future__ import absolute_import, division, print_function from cryptography.hazmat._oid import ObjectIdentifier from cryptography.hazmat.primitives import hashes class ExtensionOID(object): SUBJECT_DIRECTORY_ATTRIBUTES = ObjectIdentifier("2.5.29.9") SUBJECT_KEY_IDENTIFIER = ObjectIdentifier("2.5.29.14") KEY_USAGE = ObjectIdentifier("2.5.29.15") SUBJECT_ALTERNATIVE_NAME = ObjectIdentifier("2.5.29.17") ISSUER_ALTERNATIVE_NAME = ObjectIdentifier("2.5.29.18") BASIC_CONSTRAINTS = ObjectIdentifier("2.5.29.19") NAME_CONSTRAINTS = ObjectIdentifier("2.5.29.30") CRL_DISTRIBUTION_POINTS = ObjectIdentifier("2.5.29.31") CERTIFICATE_POLICIES = ObjectIdentifier("2.5.29.32") POLICY_MAPPINGS = ObjectIdentifier("2.5.29.33") AUTHORITY_KEY_IDENTIFIER = ObjectIdentifier("2.5.29.35") POLICY_CONSTRAINTS = ObjectIdentifier("2.5.29.36") EXTENDED_KEY_USAGE = ObjectIdentifier("2.5.29.37") FRESHEST_CRL = ObjectIdentifier("2.5.29.46") INHIBIT_ANY_POLICY = ObjectIdentifier("2.5.29.54") ISSUING_DISTRIBUTION_POINT = ObjectIdentifier("2.5.29.28") AUTHORITY_INFORMATION_ACCESS = ObjectIdentifier("1.3.6.1.5.5.7.1.1") SUBJECT_INFORMATION_ACCESS = ObjectIdentifier("1.3.6.1.5.5.7.1.11") OCSP_NO_CHECK = ObjectIdentifier("1.3.6.1.5.5.7.48.1.5") TLS_FEATURE = ObjectIdentifier("1.3.6.1.5.5.7.1.24") CRL_NUMBER = ObjectIdentifier("2.5.29.20") DELTA_CRL_INDICATOR = ObjectIdentifier("2.5.29.27") PRECERT_SIGNED_CERTIFICATE_TIMESTAMPS = ( ObjectIdentifier("1.3.6.1.4.1.11129.2.4.2") ) PRECERT_POISON = ( ObjectIdentifier("1.3.6.1.4.1.11129.2.4.3") ) class OCSPExtensionOID(object): NONCE = ObjectIdentifier("1.3.6.1.5.5.7.48.1.2") class CRLEntryExtensionOID(object): CERTIFICATE_ISSUER = ObjectIdentifier("2.5.29.29") CRL_REASON = ObjectIdentifier("2.5.29.21") INVALIDITY_DATE = ObjectIdentifier("2.5.29.24") class NameOID(object): COMMON_NAME = ObjectIdentifier("2.5.4.3") COUNTRY_NAME = ObjectIdentifier("2.5.4.6") LOCALITY_NAME = ObjectIdentifier("2.5.4.7") STATE_OR_PROVINCE_NAME = ObjectIdentifier("2.5.4.8") STREET_ADDRESS = ObjectIdentifier("2.5.4.9") ORGANIZATION_NAME = ObjectIdentifier("2.5.4.10") ORGANIZATIONAL_UNIT_NAME = ObjectIdentifier("2.5.4.11") SERIAL_NUMBER = ObjectIdentifier("2.5.4.5") SURNAME = ObjectIdentifier("2.5.4.4") GIVEN_NAME = ObjectIdentifier("2.5.4.42") TITLE = ObjectIdentifier("2.5.4.12") GENERATION_QUALIFIER = ObjectIdentifier("2.5.4.44") X500_UNIQUE_IDENTIFIER = ObjectIdentifier("2.5.4.45") DN_QUALIFIER = ObjectIdentifier("2.5.4.46") PSEUDONYM = ObjectIdentifier("2.5.4.65") USER_ID = ObjectIdentifier("0.9.2342.19200300.100.1.1") DOMAIN_COMPONENT = ObjectIdentifier("0.9.2342.19200300.100.1.25") EMAIL_ADDRESS = ObjectIdentifier("1.2.840.113549.1.9.1") JURISDICTION_COUNTRY_NAME = ObjectIdentifier("1.3.6.1.4.1.311.60.2.1.3") JURISDICTION_LOCALITY_NAME = ObjectIdentifier("1.3.6.1.4.1.311.60.2.1.1") JURISDICTION_STATE_OR_PROVINCE_NAME = ObjectIdentifier( "1.3.6.1.4.1.311.60.2.1.2" ) BUSINESS_CATEGORY = ObjectIdentifier("2.5.4.15") POSTAL_ADDRESS = ObjectIdentifier("2.5.4.16") POSTAL_CODE = ObjectIdentifier("2.5.4.17") class SignatureAlgorithmOID(object): RSA_WITH_MD5 = ObjectIdentifier("1.2.840.113549.1.1.4") RSA_WITH_SHA1 = ObjectIdentifier("1.2.840.113549.1.1.5") # This is an alternate OID for RSA with SHA1 that is occasionally seen _RSA_WITH_SHA1 = ObjectIdentifier("1.3.14.3.2.29") RSA_WITH_SHA224 = ObjectIdentifier("1.2.840.113549.1.1.14") RSA_WITH_SHA256 = ObjectIdentifier("1.2.840.113549.1.1.11") RSA_WITH_SHA384 = ObjectIdentifier("1.2.840.113549.1.1.12") RSA_WITH_SHA512 = ObjectIdentifier("1.2.840.113549.1.1.13") RSASSA_PSS = ObjectIdentifier("1.2.840.113549.1.1.10") ECDSA_WITH_SHA1 = ObjectIdentifier("1.2.840.10045.4.1") ECDSA_WITH_SHA224 = ObjectIdentifier("1.2.840.10045.4.3.1") ECDSA_WITH_SHA256 = ObjectIdentifier("1.2.840.10045.4.3.2") ECDSA_WITH_SHA384 = ObjectIdentifier("1.2.840.10045.4.3.3") ECDSA_WITH_SHA512 = ObjectIdentifier("1.2.840.10045.4.3.4") DSA_WITH_SHA1 = ObjectIdentifier("1.2.840.10040.4.3") DSA_WITH_SHA224 = ObjectIdentifier("2.16.840.1.101.3.4.3.1") DSA_WITH_SHA256 = ObjectIdentifier("2.16.840.1.101.3.4.3.2") ED25519 = ObjectIdentifier("1.3.101.112") ED448 = ObjectIdentifier("1.3.101.113") _SIG_OIDS_TO_HASH = { SignatureAlgorithmOID.RSA_WITH_MD5: hashes.MD5(), SignatureAlgorithmOID.RSA_WITH_SHA1: hashes.SHA1(), SignatureAlgorithmOID._RSA_WITH_SHA1: hashes.SHA1(), SignatureAlgorithmOID.RSA_WITH_SHA224: hashes.SHA224(), SignatureAlgorithmOID.RSA_WITH_SHA256: hashes.SHA256(), SignatureAlgorithmOID.RSA_WITH_SHA384: hashes.SHA384(), SignatureAlgorithmOID.RSA_WITH_SHA512: hashes.SHA512(), SignatureAlgorithmOID.ECDSA_WITH_SHA1: hashes.SHA1(), SignatureAlgorithmOID.ECDSA_WITH_SHA224: hashes.SHA224(), SignatureAlgorithmOID.ECDSA_WITH_SHA256: hashes.SHA256(), SignatureAlgorithmOID.ECDSA_WITH_SHA384: hashes.SHA384(), SignatureAlgorithmOID.ECDSA_WITH_SHA512: hashes.SHA512(), SignatureAlgorithmOID.DSA_WITH_SHA1: hashes.SHA1(), SignatureAlgorithmOID.DSA_WITH_SHA224: hashes.SHA224(), SignatureAlgorithmOID.DSA_WITH_SHA256: hashes.SHA256(), SignatureAlgorithmOID.ED25519: None, SignatureAlgorithmOID.ED448: None, } class ExtendedKeyUsageOID(object): SERVER_AUTH = ObjectIdentifier("1.3.6.1.5.5.7.3.1") CLIENT_AUTH = ObjectIdentifier("1.3.6.1.5.5.7.3.2") CODE_SIGNING = ObjectIdentifier("1.3.6.1.5.5.7.3.3") EMAIL_PROTECTION = ObjectIdentifier("1.3.6.1.5.5.7.3.4") TIME_STAMPING = ObjectIdentifier("1.3.6.1.5.5.7.3.8") OCSP_SIGNING = ObjectIdentifier("1.3.6.1.5.5.7.3.9") ANY_EXTENDED_KEY_USAGE = ObjectIdentifier("2.5.29.37.0") class AuthorityInformationAccessOID(object): CA_ISSUERS = ObjectIdentifier("1.3.6.1.5.5.7.48.2") OCSP = ObjectIdentifier("1.3.6.1.5.5.7.48.1") class CertificatePoliciesOID(object): CPS_QUALIFIER = ObjectIdentifier("1.3.6.1.5.5.7.2.1") CPS_USER_NOTICE = ObjectIdentifier("1.3.6.1.5.5.7.2.2") ANY_POLICY = ObjectIdentifier("2.5.29.32.0") _OID_NAMES = { NameOID.COMMON_NAME: "commonName", NameOID.COUNTRY_NAME: "countryName", NameOID.LOCALITY_NAME: "localityName", NameOID.STATE_OR_PROVINCE_NAME: "stateOrProvinceName", NameOID.STREET_ADDRESS: "streetAddress", NameOID.ORGANIZATION_NAME: "organizationName", NameOID.ORGANIZATIONAL_UNIT_NAME: "organizationalUnitName", NameOID.SERIAL_NUMBER: "serialNumber", NameOID.SURNAME: "surname", NameOID.GIVEN_NAME: "givenName", NameOID.TITLE: "title", NameOID.GENERATION_QUALIFIER: "generationQualifier", NameOID.X500_UNIQUE_IDENTIFIER: "x500UniqueIdentifier", NameOID.DN_QUALIFIER: "dnQualifier", NameOID.PSEUDONYM: "pseudonym", NameOID.USER_ID: "userID", NameOID.DOMAIN_COMPONENT: "domainComponent", NameOID.EMAIL_ADDRESS: "emailAddress", NameOID.JURISDICTION_COUNTRY_NAME: "jurisdictionCountryName", NameOID.JURISDICTION_LOCALITY_NAME: "jurisdictionLocalityName", NameOID.JURISDICTION_STATE_OR_PROVINCE_NAME: ( "jurisdictionStateOrProvinceName" ), NameOID.BUSINESS_CATEGORY: "businessCategory", NameOID.POSTAL_ADDRESS: "postalAddress", NameOID.POSTAL_CODE: "postalCode", SignatureAlgorithmOID.RSA_WITH_MD5: "md5WithRSAEncryption", SignatureAlgorithmOID.RSA_WITH_SHA1: "sha1WithRSAEncryption", SignatureAlgorithmOID.RSA_WITH_SHA224: "sha224WithRSAEncryption", SignatureAlgorithmOID.RSA_WITH_SHA256: "sha256WithRSAEncryption", SignatureAlgorithmOID.RSA_WITH_SHA384: "sha384WithRSAEncryption", SignatureAlgorithmOID.RSA_WITH_SHA512: "sha512WithRSAEncryption", SignatureAlgorithmOID.RSASSA_PSS: "RSASSA-PSS", SignatureAlgorithmOID.ECDSA_WITH_SHA1: "ecdsa-with-SHA1", SignatureAlgorithmOID.ECDSA_WITH_SHA224: "ecdsa-with-SHA224", SignatureAlgorithmOID.ECDSA_WITH_SHA256: "ecdsa-with-SHA256", SignatureAlgorithmOID.ECDSA_WITH_SHA384: "ecdsa-with-SHA384", SignatureAlgorithmOID.ECDSA_WITH_SHA512: "ecdsa-with-SHA512", SignatureAlgorithmOID.DSA_WITH_SHA1: "dsa-with-sha1", SignatureAlgorithmOID.DSA_WITH_SHA224: "dsa-with-sha224", SignatureAlgorithmOID.DSA_WITH_SHA256: "dsa-with-sha256", SignatureAlgorithmOID.ED25519: "ed25519", SignatureAlgorithmOID.ED448: "ed448", ExtendedKeyUsageOID.SERVER_AUTH: "serverAuth", ExtendedKeyUsageOID.CLIENT_AUTH: "clientAuth", ExtendedKeyUsageOID.CODE_SIGNING: "codeSigning", ExtendedKeyUsageOID.EMAIL_PROTECTION: "emailProtection", ExtendedKeyUsageOID.TIME_STAMPING: "timeStamping", ExtendedKeyUsageOID.OCSP_SIGNING: "OCSPSigning", ExtensionOID.SUBJECT_DIRECTORY_ATTRIBUTES: "subjectDirectoryAttributes", ExtensionOID.SUBJECT_KEY_IDENTIFIER: "subjectKeyIdentifier", ExtensionOID.KEY_USAGE: "keyUsage", ExtensionOID.SUBJECT_ALTERNATIVE_NAME: "subjectAltName", ExtensionOID.ISSUER_ALTERNATIVE_NAME: "issuerAltName", ExtensionOID.BASIC_CONSTRAINTS: "basicConstraints", ExtensionOID.PRECERT_SIGNED_CERTIFICATE_TIMESTAMPS: ( "signedCertificateTimestampList" ), ExtensionOID.PRECERT_POISON: "ctPoison", CRLEntryExtensionOID.CRL_REASON: "cRLReason", CRLEntryExtensionOID.INVALIDITY_DATE: "invalidityDate", CRLEntryExtensionOID.CERTIFICATE_ISSUER: "certificateIssuer", ExtensionOID.NAME_CONSTRAINTS: "nameConstraints", ExtensionOID.CRL_DISTRIBUTION_POINTS: "cRLDistributionPoints", ExtensionOID.CERTIFICATE_POLICIES: "certificatePolicies", ExtensionOID.POLICY_MAPPINGS: "policyMappings", ExtensionOID.AUTHORITY_KEY_IDENTIFIER: "authorityKeyIdentifier", ExtensionOID.POLICY_CONSTRAINTS: "policyConstraints", ExtensionOID.EXTENDED_KEY_USAGE: "extendedKeyUsage", ExtensionOID.FRESHEST_CRL: "freshestCRL", ExtensionOID.INHIBIT_ANY_POLICY: "inhibitAnyPolicy", ExtensionOID.ISSUING_DISTRIBUTION_POINT: ( "issuingDistributionPoint" ), ExtensionOID.AUTHORITY_INFORMATION_ACCESS: "authorityInfoAccess", ExtensionOID.SUBJECT_INFORMATION_ACCESS: "subjectInfoAccess", ExtensionOID.OCSP_NO_CHECK: "OCSPNoCheck", ExtensionOID.CRL_NUMBER: "cRLNumber", ExtensionOID.DELTA_CRL_INDICATOR: "deltaCRLIndicator", ExtensionOID.TLS_FEATURE: "TLSFeature", AuthorityInformationAccessOID.OCSP: "OCSP", AuthorityInformationAccessOID.CA_ISSUERS: "caIssuers", CertificatePoliciesOID.CPS_QUALIFIER: "id-qt-cps", CertificatePoliciesOID.CPS_USER_NOTICE: "id-qt-unotice", OCSPExtensionOID.NONCE: "OCSPNonce", } ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/cryptography-2.8.dist-info/AUTHORS.rst ================================================ AUTHORS ======= PGP key fingerprints are enclosed in parentheses. * Alex Gaynor (E27D 4AA0 1651 72CB C5D2 AF2B 125F 5C67 DFE9 4084) * Hynek Schlawack (C2A0 4F86 ACE2 8ADC F817 DBB7 AE25 3622 7F69 F181) * Donald Stufft * Laurens Van Houtven <_@lvh.io> (D9DC 4315 772F 8E91 DD22 B153 DFD1 3DF7 A8DD 569B) * Christian Heimes * Paul Kehrer (05FD 9FA1 6CF7 5735 0D91 A560 235A E5F1 29F9 ED98) * Jarret Raim * Alex Stapleton (A1C7 E50B 66DE 39ED C847 9665 8E3C 20D1 9BD9 5C4C) * David Reid (0F83 CC87 B32F 482B C726 B58A 9FBF D8F4 DA89 6D74) * Matthew Lefkowitz (06AB F638 E878 CD29 1264 18AB 7EC2 8125 0FBC 4A07) * Konstantinos Koukopoulos (D6BD 52B6 8C99 A91C E2C8 934D 3300 566B 3A46 726E) * Stephen Holsapple * Terry Chia * Matthew Iversen (2F04 3DCC D6E6 D5AC D262 2E0B C046 E8A8 7452 2973) * Mohammed Attia * Michael Hart * Mark Adams (A18A 7DD3 283C CF2A B0CE FE0E C7A0 5E3F C972 098C) * Gregory Haynes (6FB6 44BF 9FD0 EBA2 1CE9 471F B08F 42F9 0DC6 599F) * Chelsea Winfree * Steven Buss (1FB9 2EC1 CF93 DFD6 B47F F583 B1A5 6C22 290D A4C3) * Andre Caron * Jiangge Zhang (BBEC 782B 015F 71B1 5FF7 EACA 1A8C AA98 255F 5000) * Major Hayden (1BF9 9264 9596 0033 698C 252B 7370 51E0 C101 1FB1) * Phoebe Queen (10D4 7741 AB65 50F4 B264 3888 DA40 201A 072B C1FA) * Google Inc. * Amaury Forgeot d'Arc * Dirkjan Ochtman (25BB BAC1 13C1 BFD5 AA59 4A4C 9F96 B929 3038 0381) * Maximilian Hils * Simo Sorce * Thomas Sileo * Fraser Tweedale * Ofek Lev (FFB6 B92B 30B1 7848 546E 9912 972F E913 DAD5 A46E) * Erik Daguerre * Aviv Palivoda * Chris Wolfe * Jeremy Lainé * Denis Gladkikh * John Pacific (2CF6 0381 B5EF 29B7 D48C 2020 7BB9 71A0 E891 44D9) * Marti Raudsepp ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/cryptography-2.8.dist-info/INSTALLER ================================================ pip ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/cryptography-2.8.dist-info/LICENSE ================================================ This software is made available under the terms of *either* of the licenses found in LICENSE.APACHE or LICENSE.BSD. Contributions to cryptography are made under the terms of *both* these licenses. The code used in the OpenSSL locking callback and OS random engine is derived from CPython, and is licensed under the terms of the PSF License Agreement. ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/cryptography-2.8.dist-info/LICENSE.APACHE ================================================ Apache License Version 2.0, January 2004 https://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at https://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/cryptography-2.8.dist-info/LICENSE.BSD ================================================ Copyright (c) Individual contributors. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of PyCA Cryptography nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/cryptography-2.8.dist-info/LICENSE.PSF ================================================ 1. This LICENSE AGREEMENT is between the Python Software Foundation ("PSF"), and the Individual or Organization ("Licensee") accessing and otherwise using Python 2.7.12 software in source or binary form and its associated documentation. 2. Subject to the terms and conditions of this License Agreement, PSF hereby grants Licensee a nonexclusive, royalty-free, world-wide license to reproduce, analyze, test, perform and/or display publicly, prepare derivative works, distribute, and otherwise use Python 2.7.12 alone or in any derivative version, provided, however, that PSF's License Agreement and PSF's notice of copyright, i.e., "Copyright © 2001-2016 Python Software Foundation; All Rights Reserved" are retained in Python 2.7.12 alone or in any derivative version prepared by Licensee. 3. In the event Licensee prepares a derivative work that is based on or incorporates Python 2.7.12 or any part thereof, and wants to make the derivative work available to others as provided herein, then Licensee hereby agrees to include in any such work a brief summary of the changes made to Python 2.7.12. 4. PSF is making Python 2.7.12 available to Licensee on an "AS IS" basis. PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON 2.7.12 WILL NOT INFRINGE ANY THIRD PARTY RIGHTS. 5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON 2.7.12 FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON 2.7.12, OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. 6. This License Agreement will automatically terminate upon a material breach of its terms and conditions. 7. Nothing in this License Agreement shall be deemed to create any relationship of agency, partnership, or joint venture between PSF and Licensee. This License Agreement does not grant permission to use PSF trademarks or trade name in a trademark sense to endorse or promote products or services of Licensee, or any third party. 8. By copying, installing or otherwise using Python 2.7.12, Licensee agrees to be bound by the terms and conditions of this License Agreement. ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/cryptography-2.8.dist-info/METADATA ================================================ Metadata-Version: 2.1 Name: cryptography Version: 2.8 Summary: cryptography is a package which provides cryptographic recipes and primitives to Python developers. Home-page: https://github.com/pyca/cryptography Author: The cryptography developers Author-email: cryptography-dev@python.org License: BSD or Apache License, Version 2.0 Platform: UNKNOWN Classifier: Development Status :: 5 - Production/Stable Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: Apache Software License Classifier: License :: OSI Approved :: BSD License Classifier: Natural Language :: English Classifier: Operating System :: MacOS :: MacOS X Classifier: Operating System :: POSIX Classifier: Operating System :: POSIX :: BSD Classifier: Operating System :: POSIX :: Linux Classifier: Operating System :: Microsoft :: Windows Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 2 Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: 3.4 Classifier: Programming Language :: Python :: 3.5 Classifier: Programming Language :: Python :: 3.6 Classifier: Programming Language :: Python :: 3.7 Classifier: Programming Language :: Python :: 3.8 Classifier: Programming Language :: Python :: Implementation :: CPython Classifier: Programming Language :: Python :: Implementation :: PyPy Classifier: Topic :: Security :: Cryptography Requires-Python: >=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.* Description-Content-Type: text/x-rst Requires-Dist: six (>=1.4.1) Requires-Dist: cffi (!=1.11.3,>=1.8) Requires-Dist: enum34 ; python_version < '3' Requires-Dist: ipaddress ; python_version < '3' Provides-Extra: docs Requires-Dist: sphinx (!=1.8.0,>=1.6.5) ; extra == 'docs' Requires-Dist: sphinx-rtd-theme ; extra == 'docs' Provides-Extra: docstest Requires-Dist: doc8 ; extra == 'docstest' Requires-Dist: pyenchant (>=1.6.11) ; extra == 'docstest' Requires-Dist: twine (>=1.12.0) ; extra == 'docstest' Requires-Dist: sphinxcontrib-spelling (>=4.0.1) ; extra == 'docstest' Provides-Extra: idna Requires-Dist: idna (>=2.1) ; extra == 'idna' Provides-Extra: pep8test Requires-Dist: flake8 ; extra == 'pep8test' Requires-Dist: flake8-import-order ; extra == 'pep8test' Requires-Dist: pep8-naming ; extra == 'pep8test' Provides-Extra: test Requires-Dist: pytest (!=3.9.0,!=3.9.1,!=3.9.2,>=3.6.0) ; extra == 'test' Requires-Dist: pretend ; extra == 'test' Requires-Dist: iso8601 ; extra == 'test' Requires-Dist: pytz ; extra == 'test' Requires-Dist: hypothesis (!=3.79.2,>=1.11.4) ; extra == 'test' pyca/cryptography ================= .. image:: https://img.shields.io/pypi/v/cryptography.svg :target: https://pypi.org/project/cryptography/ :alt: Latest Version .. image:: https://readthedocs.org/projects/cryptography/badge/?version=latest :target: https://cryptography.io :alt: Latest Docs .. image:: https://travis-ci.org/pyca/cryptography.svg?branch=master :target: https://travis-ci.org/pyca/cryptography .. image:: https://dev.azure.com/pyca/cryptography/_apis/build/status/Azure%20CI?branchName=master :target: https://dev.azure.com/pyca/cryptography/_build/latest?definitionId=3&branchName=master .. image:: https://codecov.io/github/pyca/cryptography/coverage.svg?branch=master :target: https://codecov.io/github/pyca/cryptography?branch=master ``cryptography`` is a package which provides cryptographic recipes and primitives to Python developers. Our goal is for it to be your "cryptographic standard library". It supports Python 2.7, Python 3.4+, and PyPy 5.4+. ``cryptography`` includes both high level recipes and low level interfaces to common cryptographic algorithms such as symmetric ciphers, message digests, and key derivation functions. For example, to encrypt something with ``cryptography``'s high level symmetric encryption recipe: .. code-block:: pycon >>> from cryptography.fernet import Fernet >>> # Put this somewhere safe! >>> key = Fernet.generate_key() >>> f = Fernet(key) >>> token = f.encrypt(b"A really secret message. Not for prying eyes.") >>> token '...' >>> f.decrypt(token) 'A really secret message. Not for prying eyes.' You can find more information in the `documentation`_. You can install ``cryptography`` with: .. code-block:: console $ pip install cryptography For full details see `the installation documentation`_. Discussion ~~~~~~~~~~ If you run into bugs, you can file them in our `issue tracker`_. We maintain a `cryptography-dev`_ mailing list for development discussion. You can also join ``#cryptography-dev`` on Freenode to ask questions or get involved. Security ~~~~~~~~ Need to report a security issue? Please consult our `security reporting`_ documentation. .. _`documentation`: https://cryptography.io/ .. _`the installation documentation`: https://cryptography.io/en/latest/installation/ .. _`issue tracker`: https://github.com/pyca/cryptography/issues .. _`cryptography-dev`: https://mail.python.org/mailman/listinfo/cryptography-dev .. _`security reporting`: https://cryptography.io/en/latest/security/ ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/cryptography-2.8.dist-info/RECORD ================================================ cryptography-2.8.dist-info/AUTHORS.rst,sha256=MoKTlP6yOmnLC_KXarHVQP0sItBk11dtZ7LzV0VhNB0,2475 cryptography-2.8.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 cryptography-2.8.dist-info/LICENSE,sha256=NUUrVX-rDvsegNftucTlEYuThAgq2qBR3eNCECy53o0,352 cryptography-2.8.dist-info/LICENSE.APACHE,sha256=qsc7MUj20dcRHbyjIJn2jSbGRMaBOuHk8F9leaomY_4,11360 cryptography-2.8.dist-info/LICENSE.BSD,sha256=YCxMdILeZHndLpeTzaJ15eY9dz2s0eymiSMqtwCPtPs,1532 cryptography-2.8.dist-info/LICENSE.PSF,sha256=aT7ApmKzn5laTyUrA6YiKUVHDBtvEsoCkY5O_g32S58,2415 cryptography-2.8.dist-info/METADATA,sha256=DTs0WZ8nip9kDpwx2m_l-9t0E6gBmIPs-BuE_EJOtbg,5175 cryptography-2.8.dist-info/RECORD,, cryptography-2.8.dist-info/WHEEL,sha256=QMVol4obO-h_ZZLSvUyPjs3tbFnVOtWLzOTlaMWgEN8,111 cryptography-2.8.dist-info/top_level.txt,sha256=QCkYQE4HJBpqIr-aBqbOZ70NlfbejKnDE6ODbNgUwwg,46 cryptography/__about__.py,sha256=DfioEQ1oTJa9q9bA7yTTxFvxt_oik9bZQDZbgeU5XcE,814 cryptography/__init__.py,sha256=M7mQrfCHYuk7TpEPpfYxkhc95comqxOt41xYjLa5wiA,527 cryptography/__pycache__/__about__.cpython-36.pyc,, cryptography/__pycache__/__init__.cpython-36.pyc,, cryptography/__pycache__/exceptions.cpython-36.pyc,, cryptography/__pycache__/fernet.cpython-36.pyc,, cryptography/__pycache__/utils.cpython-36.pyc,, cryptography/exceptions.py,sha256=NPtDqIq1lsQ1Gb1BXkjsGIvbMrWMaKCaT8epiSgi010,1259 cryptography/fernet.py,sha256=CA4iWQvPDeF9EN0IWq8xyuBBqMvcpEE17Ii8VGbi19Y,5220 cryptography/hazmat/__init__.py,sha256=hEPNQw8dgjIPIn42qaLwXNRLCyTGNZeSvkQb57DPhbs,483 cryptography/hazmat/__pycache__/__init__.cpython-36.pyc,, cryptography/hazmat/__pycache__/_der.cpython-36.pyc,, cryptography/hazmat/__pycache__/_oid.cpython-36.pyc,, cryptography/hazmat/_der.py,sha256=9wV7usssA-_Ikxo0h5uVEJJcY6uRbw4UhlgjLhXYsk0,5205 cryptography/hazmat/_oid.py,sha256=F1RU1q8LPLrCoCxyBk_TZ5yJeFt1kYcPMqaIHu4sBRY,2178 cryptography/hazmat/backends/__init__.py,sha256=92UZdmqTyQPOYA2ui17tksyjxBnTmj1XDsxDCChLvxE,496 cryptography/hazmat/backends/__pycache__/__init__.cpython-36.pyc,, cryptography/hazmat/backends/__pycache__/interfaces.cpython-36.pyc,, cryptography/hazmat/backends/interfaces.py,sha256=MoNrfcaP5cpD0_wJH5v6vyGSXC8OsbAAHm4-9TZSIU0,10783 cryptography/hazmat/backends/openssl/__init__.py,sha256=k4DMe228_hTuB2kY3Lwk62JdI3EmCd7VkV01zJm57ps,336 cryptography/hazmat/backends/openssl/__pycache__/__init__.cpython-36.pyc,, cryptography/hazmat/backends/openssl/__pycache__/aead.cpython-36.pyc,, cryptography/hazmat/backends/openssl/__pycache__/backend.cpython-36.pyc,, cryptography/hazmat/backends/openssl/__pycache__/ciphers.cpython-36.pyc,, cryptography/hazmat/backends/openssl/__pycache__/cmac.cpython-36.pyc,, cryptography/hazmat/backends/openssl/__pycache__/decode_asn1.cpython-36.pyc,, cryptography/hazmat/backends/openssl/__pycache__/dh.cpython-36.pyc,, cryptography/hazmat/backends/openssl/__pycache__/dsa.cpython-36.pyc,, cryptography/hazmat/backends/openssl/__pycache__/ec.cpython-36.pyc,, cryptography/hazmat/backends/openssl/__pycache__/ed25519.cpython-36.pyc,, cryptography/hazmat/backends/openssl/__pycache__/ed448.cpython-36.pyc,, cryptography/hazmat/backends/openssl/__pycache__/encode_asn1.cpython-36.pyc,, cryptography/hazmat/backends/openssl/__pycache__/hashes.cpython-36.pyc,, cryptography/hazmat/backends/openssl/__pycache__/hmac.cpython-36.pyc,, cryptography/hazmat/backends/openssl/__pycache__/ocsp.cpython-36.pyc,, cryptography/hazmat/backends/openssl/__pycache__/poly1305.cpython-36.pyc,, cryptography/hazmat/backends/openssl/__pycache__/rsa.cpython-36.pyc,, cryptography/hazmat/backends/openssl/__pycache__/utils.cpython-36.pyc,, cryptography/hazmat/backends/openssl/__pycache__/x25519.cpython-36.pyc,, cryptography/hazmat/backends/openssl/__pycache__/x448.cpython-36.pyc,, cryptography/hazmat/backends/openssl/__pycache__/x509.cpython-36.pyc,, cryptography/hazmat/backends/openssl/aead.py,sha256=U0Ncw0z4-pqEWRxJu9GzZDPTvp8YBW5GHFebckaFLTs,5750 cryptography/hazmat/backends/openssl/backend.py,sha256=9ZcByUpQS8kwqLKeZoKUDZGj1dwCnrnAyEJ1ng__TUc,97231 cryptography/hazmat/backends/openssl/ciphers.py,sha256=glsURUBxfMqj0XYTcEosZx6oBL-FCadhIIuQA1cxmfU,9314 cryptography/hazmat/backends/openssl/cmac.py,sha256=wxCHffVAEFxcn6ATMPy7HATIjWZWMoKdTXHJCgeUf48,2855 cryptography/hazmat/backends/openssl/decode_asn1.py,sha256=kPsCTGczXnxkGP471kot8rw9CBFvcuyAtJX13caubDo,33303 cryptography/hazmat/backends/openssl/dh.py,sha256=kXH0LXLsgo7FLNan6V5BiidS30zVkWNwaWuVZ-n6Uog,10814 cryptography/hazmat/backends/openssl/dsa.py,sha256=YOFM_ml2J4q6TI5-oh8M9RPS3u2dcUWxT51Yxfpbs7o,10228 cryptography/hazmat/backends/openssl/ec.py,sha256=okZ87EcaOJRGmjEUvIPqDV7Jp6xcky4oFPSN6fXbGrs,12590 cryptography/hazmat/backends/openssl/ed25519.py,sha256=66dkJPZ6gvUCJSA0RPydi1-0Q2WjhiAcKwvD2R59Zzc,6081 cryptography/hazmat/backends/openssl/ed448.py,sha256=2W6KwzPQXPvvkaNZWFxI_L8rIP80vhBcdZVbIzS5MmY,6045 cryptography/hazmat/backends/openssl/encode_asn1.py,sha256=8XUOTdGreOYvWhiVeQtL7XVqlBpP-rnLuDrmM7bG4LQ,23593 cryptography/hazmat/backends/openssl/hashes.py,sha256=_uYcKjrWzCifz9uONPFBGba7QC3o66-KzxkSNf2uI_A,3196 cryptography/hazmat/backends/openssl/hmac.py,sha256=-5MsNq9-A7Is_nUjMdz0FnOpdy3MnowCWqDGGL67hyM,2998 cryptography/hazmat/backends/openssl/ocsp.py,sha256=lnCm5e37lLoqI_dTgf2dv5qS-vGo8CL3MQh6ojLFBA0,13654 cryptography/hazmat/backends/openssl/poly1305.py,sha256=WaQ3LyxPD2m9auySy4mzDMMoWxTT4pw_zhg55n1D6Gg,2356 cryptography/hazmat/backends/openssl/rsa.py,sha256=swgjJBJfxskdLzAiUJ_jJ9lAzkn83un5Tqvi4fV8p98,18021 cryptography/hazmat/backends/openssl/utils.py,sha256=LqzoMfLbO3385h-JgV8RiWQj0bvtRy76LzimRqjIT2Q,2339 cryptography/hazmat/backends/openssl/x25519.py,sha256=Soo-zS0WsXp6jwJgzVWjhhosMNWbZ6QR6kC-Splwd8I,5580 cryptography/hazmat/backends/openssl/x448.py,sha256=-vMoIJJ4X3HdB4LrWxxq0_xp0sDM69S6VM_P-dqie24,4526 cryptography/hazmat/backends/openssl/x509.py,sha256=Jjl-sJiQvtmM9CbnRCqGs3bxeyfW-TrDsUAX0GvHqrM,20099 cryptography/hazmat/bindings/__init__.py,sha256=0wGw2OF9R7fHX7NWENCmrsYigbXHU2ojgn-N4Rkjs9U,246 cryptography/hazmat/bindings/__pycache__/__init__.cpython-36.pyc,, cryptography/hazmat/bindings/_constant_time.abi3.so,sha256=F5VZJgeBmqhXqtR39Uf3-T3tZUwRx0Qcwm5XZL_MoXI,30048 cryptography/hazmat/bindings/_openssl.abi3.so,sha256=k2K7IN4Ao0OhMNPZY-GV3CgX0ie3f2WS3XzDZKltrSw,5627248 cryptography/hazmat/bindings/_padding.abi3.so,sha256=pT7wrkBNuG7Y-gm6XSqV7pq_Ni1nadb1rJAh7QUKQNM,33520 cryptography/hazmat/bindings/openssl/__init__.py,sha256=0wGw2OF9R7fHX7NWENCmrsYigbXHU2ojgn-N4Rkjs9U,246 cryptography/hazmat/bindings/openssl/__pycache__/__init__.cpython-36.pyc,, cryptography/hazmat/bindings/openssl/__pycache__/_conditional.cpython-36.pyc,, cryptography/hazmat/bindings/openssl/__pycache__/binding.cpython-36.pyc,, cryptography/hazmat/bindings/openssl/_conditional.py,sha256=HXtnoHgt5jIsEjWcKQFHJ47yBAVsBfLO2XMSbffd-JE,11233 cryptography/hazmat/bindings/openssl/binding.py,sha256=QCYFKaDiuYFhxK3l6Lkvr4V-PXuu26saC09AUNzUJvQ,7120 cryptography/hazmat/primitives/__init__.py,sha256=0wGw2OF9R7fHX7NWENCmrsYigbXHU2ojgn-N4Rkjs9U,246 cryptography/hazmat/primitives/__pycache__/__init__.cpython-36.pyc,, cryptography/hazmat/primitives/__pycache__/cmac.cpython-36.pyc,, cryptography/hazmat/primitives/__pycache__/constant_time.cpython-36.pyc,, cryptography/hazmat/primitives/__pycache__/hashes.cpython-36.pyc,, cryptography/hazmat/primitives/__pycache__/hmac.cpython-36.pyc,, cryptography/hazmat/primitives/__pycache__/keywrap.cpython-36.pyc,, cryptography/hazmat/primitives/__pycache__/padding.cpython-36.pyc,, cryptography/hazmat/primitives/__pycache__/poly1305.cpython-36.pyc,, cryptography/hazmat/primitives/asymmetric/__init__.py,sha256=WhUn3tGxoLAxGAsZHElJ2aOILXSh55AZi04MBudYmQA,1020 cryptography/hazmat/primitives/asymmetric/__pycache__/__init__.cpython-36.pyc,, cryptography/hazmat/primitives/asymmetric/__pycache__/dh.cpython-36.pyc,, cryptography/hazmat/primitives/asymmetric/__pycache__/dsa.cpython-36.pyc,, cryptography/hazmat/primitives/asymmetric/__pycache__/ec.cpython-36.pyc,, cryptography/hazmat/primitives/asymmetric/__pycache__/ed25519.cpython-36.pyc,, cryptography/hazmat/primitives/asymmetric/__pycache__/ed448.cpython-36.pyc,, cryptography/hazmat/primitives/asymmetric/__pycache__/padding.cpython-36.pyc,, cryptography/hazmat/primitives/asymmetric/__pycache__/rsa.cpython-36.pyc,, cryptography/hazmat/primitives/asymmetric/__pycache__/utils.cpython-36.pyc,, cryptography/hazmat/primitives/asymmetric/__pycache__/x25519.cpython-36.pyc,, cryptography/hazmat/primitives/asymmetric/__pycache__/x448.cpython-36.pyc,, cryptography/hazmat/primitives/asymmetric/dh.py,sha256=6Xl01bjTVHFCcdJr3Ph2cQ7hxkYYedqm-SekZpxnntY,5454 cryptography/hazmat/primitives/asymmetric/dsa.py,sha256=uzK7qpe0BtqHkgVLSrNGtska1w3JSUN_uZp6XAA5LMY,6891 cryptography/hazmat/primitives/asymmetric/ec.py,sha256=omk32C3oyISuzjH37lmzO2e95DU3qnkTPwzZAHXj4dw,13758 cryptography/hazmat/primitives/asymmetric/ed25519.py,sha256=K7dGHENDEmO0kS0fqeT6dcmMRo9IbKLus26WAfDDhjM,2395 cryptography/hazmat/primitives/asymmetric/ed448.py,sha256=eoRniA5yN3fgT0Vutuo-j6i1yeiKEKA_-4aErJPdl6w,2322 cryptography/hazmat/primitives/asymmetric/padding.py,sha256=aCZatU5-q_WW5vazBWeKPF8ZZa0AI8hWzbJaVRN3RWI,2261 cryptography/hazmat/primitives/asymmetric/rsa.py,sha256=V7MKK29BpNGF2f3uWEs3HPYbGuL3YtDFujvjFQrle0Q,10317 cryptography/hazmat/primitives/asymmetric/utils.py,sha256=Og5jZxYoCE9BMb3dmquMTantjsjzl0z2mqoc9s-0588,1184 cryptography/hazmat/primitives/asymmetric/x25519.py,sha256=LZ9dKxAjFdR-VE5OO0CijGUyJxiqFFynCeucTOYQUCk,2281 cryptography/hazmat/primitives/asymmetric/x448.py,sha256=gbZ_UdVIozeZV7FfdpI5qp4t31nWGUXiKwfgMYrF2iY,2249 cryptography/hazmat/primitives/ciphers/__init__.py,sha256=QxaxejeFfz6CPhI1c4iNq_7DsiB41Y_Q-uLfzOx7fv8,626 cryptography/hazmat/primitives/ciphers/__pycache__/__init__.cpython-36.pyc,, cryptography/hazmat/primitives/ciphers/__pycache__/aead.cpython-36.pyc,, cryptography/hazmat/primitives/ciphers/__pycache__/algorithms.cpython-36.pyc,, cryptography/hazmat/primitives/ciphers/__pycache__/base.cpython-36.pyc,, cryptography/hazmat/primitives/ciphers/__pycache__/modes.cpython-36.pyc,, cryptography/hazmat/primitives/ciphers/aead.py,sha256=XpXxKVAOznjEpFcPxa-sU_kJSowGjGljpp779Ob8W9g,6437 cryptography/hazmat/primitives/ciphers/algorithms.py,sha256=IXGUj-SRVKyHfDdyqUkRkVdySJ5s9qjIesjFd-EIbwI,4190 cryptography/hazmat/primitives/ciphers/base.py,sha256=hUe5MPVeWB-21ako6_yVGI7GBNCnROkkS53zy8oSO-o,7144 cryptography/hazmat/primitives/ciphers/modes.py,sha256=nUHeQ9I0AIs30Ni2w9TcU9w-AQIpeOA6wLdfA-zkTmI,6641 cryptography/hazmat/primitives/cmac.py,sha256=QgOXACkva7RUbVYvSq3ryw2RdZLOOJgt_zgyCKBmJF4,2075 cryptography/hazmat/primitives/constant_time.py,sha256=TYFSRknWvKlz68rCwfdMw93w0Jy1-3B5F9PQzxH0MbI,1139 cryptography/hazmat/primitives/hashes.py,sha256=hqAOjSu4l7ZOG0U7kJQn0kSHgFuI57o5nb4oTQ7vGnE,6206 cryptography/hazmat/primitives/hmac.py,sha256=MGsVrE_ghlZW0HUH70seV4vCWlIZNSUgB0v9n05vcGg,2196 cryptography/hazmat/primitives/kdf/__init__.py,sha256=nod5HjPswjZr8wFp6Tsu6en9blHYF3khgXI5R0zIcnM,771 cryptography/hazmat/primitives/kdf/__pycache__/__init__.cpython-36.pyc,, cryptography/hazmat/primitives/kdf/__pycache__/concatkdf.cpython-36.pyc,, cryptography/hazmat/primitives/kdf/__pycache__/hkdf.cpython-36.pyc,, cryptography/hazmat/primitives/kdf/__pycache__/kbkdf.cpython-36.pyc,, cryptography/hazmat/primitives/kdf/__pycache__/pbkdf2.cpython-36.pyc,, cryptography/hazmat/primitives/kdf/__pycache__/scrypt.cpython-36.pyc,, cryptography/hazmat/primitives/kdf/__pycache__/x963kdf.cpython-36.pyc,, cryptography/hazmat/primitives/kdf/concatkdf.py,sha256=MSb4abF8jrICg1v9NSr0QQMfQ1r23RDoUkU0X8rQrhE,3981 cryptography/hazmat/primitives/kdf/hkdf.py,sha256=lcqU0pI3HFKUC9L5LpO4gxPSRsES-x1lePDfryu5U4w,3463 cryptography/hazmat/primitives/kdf/kbkdf.py,sha256=EWeLFPINGl50hkSJj3z62WwePpzRiqGMo1nKm7at1_g,4905 cryptography/hazmat/primitives/kdf/pbkdf2.py,sha256=EK3xDD-Y29DLJulQjHraWrwX7psqCWs7NwSTto4YRxs,2088 cryptography/hazmat/primitives/kdf/scrypt.py,sha256=2BrGwbyk3VvY4szQY2EBvZMaf8AYPWlX84aSj-TXLXk,2155 cryptography/hazmat/primitives/kdf/x963kdf.py,sha256=YL88ILo4eBYP_LhlJcEgKnMqputkOmB-FBCsy6KZ2RA,2280 cryptography/hazmat/primitives/keywrap.py,sha256=LqjkVIs7ub5I5gwmYSb9Ia0VdXMqWWHmnKSdQ7HOGEA,5462 cryptography/hazmat/primitives/padding.py,sha256=CtKBj2nR50m4ZXFAonOxDcymW8Jkj0A9xxt7EMLbpJY,5644 cryptography/hazmat/primitives/poly1305.py,sha256=n7CbIXH3F3HwDsXIaaHJGC-RsSPUuLZG1MJeb1FqBv8,1668 cryptography/hazmat/primitives/serialization/__init__.py,sha256=R-4wUb_UMp3Wh_tWn8nIBJXWVR7Oo0ZRhgm1wEPCMjE,1046 cryptography/hazmat/primitives/serialization/__pycache__/__init__.cpython-36.pyc,, cryptography/hazmat/primitives/serialization/__pycache__/base.cpython-36.pyc,, cryptography/hazmat/primitives/serialization/__pycache__/pkcs12.cpython-36.pyc,, cryptography/hazmat/primitives/serialization/__pycache__/ssh.cpython-36.pyc,, cryptography/hazmat/primitives/serialization/base.py,sha256=CY8d3TjQ2wPotHpQpkZ-kyVkAwW95y6TFw0JN9KpbFM,1904 cryptography/hazmat/primitives/serialization/pkcs12.py,sha256=LWIA6SVMxc4nnAtSivs8rTpwG6Fy3ppSfHRDiJGdJUw,377 cryptography/hazmat/primitives/serialization/ssh.py,sha256=U94cOHI42BlgiqRXDlsPoqUa5C_Ww_uuu2Njr93d1fA,4381 cryptography/hazmat/primitives/twofactor/__init__.py,sha256=BWrm3DKDoAa281E7U_nzz8v44OmAiXmlIycFcsehwfE,288 cryptography/hazmat/primitives/twofactor/__pycache__/__init__.cpython-36.pyc,, cryptography/hazmat/primitives/twofactor/__pycache__/hotp.cpython-36.pyc,, cryptography/hazmat/primitives/twofactor/__pycache__/totp.cpython-36.pyc,, cryptography/hazmat/primitives/twofactor/__pycache__/utils.cpython-36.pyc,, cryptography/hazmat/primitives/twofactor/hotp.py,sha256=6_EnKl-zRs0yCXuHxQhs2TEkHaprWxZnfJGrQjs5RIg,2589 cryptography/hazmat/primitives/twofactor/totp.py,sha256=KL3A4bjpqaqynQYd9hfPVkvs5vYVqf1JVpucEX7_ddM,1594 cryptography/hazmat/primitives/twofactor/utils.py,sha256=71gX1bJeP9TQa-HbSPzeUUJwVY78ALYQNvuusknUO4U,954 cryptography/utils.py,sha256=2ml4dp8EPZ-1SNwmqy5vVVFhMWTeHVvHoDJo9QswlPc,5010 cryptography/x509/__init__.py,sha256=F01ZMHaefgsvMeSthFQEa1gz_q7553LMa_IqOq8tD7w,7305 cryptography/x509/__pycache__/__init__.cpython-36.pyc,, cryptography/x509/__pycache__/base.cpython-36.pyc,, cryptography/x509/__pycache__/certificate_transparency.cpython-36.pyc,, cryptography/x509/__pycache__/extensions.cpython-36.pyc,, cryptography/x509/__pycache__/general_name.cpython-36.pyc,, cryptography/x509/__pycache__/name.cpython-36.pyc,, cryptography/x509/__pycache__/ocsp.cpython-36.pyc,, cryptography/x509/__pycache__/oid.cpython-36.pyc,, cryptography/x509/base.py,sha256=HlnDQMCpOqZu_ARcysk6zjUNulMPP7nuQz57L8bW-HM,23939 cryptography/x509/certificate_transparency.py,sha256=eJ9lrITdyMn4XsrcVdrTaFVI_RR7mX_VzMZyiaEpbps,1000 cryptography/x509/extensions.py,sha256=T_Xo0Rugk4xZUwDVTtEaci7y2MDHeBXf5jXT3fB_8PU,50781 cryptography/x509/general_name.py,sha256=cwcI1Yez1K9OEdG0wukDWGfS_b6xN21eHOyPaCqjrGY,10462 cryptography/x509/name.py,sha256=f4lg9Ej5izBMHm2sv5OeviQpzmvjSA3951PMGWUF7ac,8131 cryptography/x509/ocsp.py,sha256=_Tbb3M2qe65r2MYlsjXH_vjLwDvaAZZ7-Y5GAXwuqxY,13310 cryptography/x509/oid.py,sha256=iN1TLtCuI1j-WebvLeQM_yni-Uu90nYOglGJAXCCYao,10936 ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/cryptography-2.8.dist-info/WHEEL ================================================ Wheel-Version: 1.0 Generator: bdist_wheel (0.33.6) Root-Is-Purelib: false Tag: cp34-abi3-manylinux2010_x86_64 ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/cryptography-2.8.dist-info/top_level.txt ================================================ _constant_time _openssl _padding cryptography ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/cssselect/__init__.py ================================================ # -*- coding: utf-8 -*- """ CSS Selectors based on XPath ============================ This module supports selecting XML/HTML elements based on CSS selectors. See the `CSSSelector` class for details. :copyright: (c) 2007-2012 Ian Bicking and contributors. See AUTHORS for more details. :license: BSD, see LICENSE for more details. """ from cssselect.parser import (parse, Selector, FunctionalPseudoElement, SelectorError, SelectorSyntaxError) from cssselect.xpath import GenericTranslator, HTMLTranslator, ExpressionError VERSION = '1.1.0' __version__ = VERSION ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/cssselect/parser.py ================================================ # -*- coding: utf-8 -*- """ cssselect.parser ================ Tokenizer, parser and parsed objects for CSS selectors. :copyright: (c) 2007-2012 Ian Bicking and contributors. See AUTHORS for more details. :license: BSD, see LICENSE for more details. """ import sys import re import operator if sys.version_info[0] < 3: _unicode = unicode _unichr = unichr else: _unicode = str _unichr = chr def ascii_lower(string): """Lower-case, but only in the ASCII range.""" return string.encode('utf8').lower().decode('utf8') class SelectorError(Exception): """Common parent for :class:`SelectorSyntaxError` and :class:`ExpressionError`. You can just use ``except SelectorError:`` when calling :meth:`~GenericTranslator.css_to_xpath` and handle both exceptions types. """ class SelectorSyntaxError(SelectorError, SyntaxError): """Parsing a selector that does not match the grammar.""" #### Parsed objects class Selector(object): """ Represents a parsed selector. :meth:`~GenericTranslator.selector_to_xpath` accepts this object, but ignores :attr:`pseudo_element`. It is the user’s responsibility to account for pseudo-elements and reject selectors with unknown or unsupported pseudo-elements. """ def __init__(self, tree, pseudo_element=None): self.parsed_tree = tree if pseudo_element is not None and not isinstance( pseudo_element, FunctionalPseudoElement): pseudo_element = ascii_lower(pseudo_element) #: A :class:`FunctionalPseudoElement`, #: or the identifier for the pseudo-element as a string, # or ``None``. #: #: +-------------------------+----------------+--------------------------------+ #: | | Selector | Pseudo-element | #: +=========================+================+================================+ #: | CSS3 syntax | ``a::before`` | ``'before'`` | #: +-------------------------+----------------+--------------------------------+ #: | Older syntax | ``a:before`` | ``'before'`` | #: +-------------------------+----------------+--------------------------------+ #: | From the Lists3_ draft, | ``li::marker`` | ``'marker'`` | #: | not in Selectors3 | | | #: +-------------------------+----------------+--------------------------------+ #: | Invalid pseudo-class | ``li:marker`` | ``None`` | #: +-------------------------+----------------+--------------------------------+ #: | Functional | ``a::foo(2)`` | ``FunctionalPseudoElement(…)`` | #: +-------------------------+----------------+--------------------------------+ #: #: .. _Lists3: http://www.w3.org/TR/2011/WD-css3-lists-20110524/#marker-pseudoelement self.pseudo_element = pseudo_element def __repr__(self): if isinstance(self.pseudo_element, FunctionalPseudoElement): pseudo_element = repr(self.pseudo_element) elif self.pseudo_element: pseudo_element = '::%s' % self.pseudo_element else: pseudo_element = '' return '%s[%r%s]' % ( self.__class__.__name__, self.parsed_tree, pseudo_element) def canonical(self): """Return a CSS representation for this selector (a string) """ if isinstance(self.pseudo_element, FunctionalPseudoElement): pseudo_element = '::%s' % self.pseudo_element.canonical() elif self.pseudo_element: pseudo_element = '::%s' % self.pseudo_element else: pseudo_element = '' res = '%s%s' % (self.parsed_tree.canonical(), pseudo_element) if len(res) > 1: res = res.lstrip('*') return res def specificity(self): """Return the specificity_ of this selector as a tuple of 3 integers. .. _specificity: http://www.w3.org/TR/selectors/#specificity """ a, b, c = self.parsed_tree.specificity() if self.pseudo_element: c += 1 return a, b, c class Class(object): """ Represents selector.class_name """ def __init__(self, selector, class_name): self.selector = selector self.class_name = class_name def __repr__(self): return '%s[%r.%s]' % ( self.__class__.__name__, self.selector, self.class_name) def canonical(self): return '%s.%s' % (self.selector.canonical(), self.class_name) def specificity(self): a, b, c = self.selector.specificity() b += 1 return a, b, c class FunctionalPseudoElement(object): """ Represents selector::name(arguments) .. attribute:: name The name (identifier) of the pseudo-element, as a string. .. attribute:: arguments The arguments of the pseudo-element, as a list of tokens. **Note:** tokens are not part of the public API, and may change between cssselect versions. Use at your own risks. """ def __init__(self, name, arguments): self.name = ascii_lower(name) self.arguments = arguments def __repr__(self): return '%s[::%s(%r)]' % ( self.__class__.__name__, self.name, [token.value for token in self.arguments]) def argument_types(self): return [token.type for token in self.arguments] def canonical(self): args = ''.join(token.css() for token in self.arguments) return '%s(%s)' % (self.name, args) def specificity(self): a, b, c = self.selector.specificity() b += 1 return a, b, c class Function(object): """ Represents selector:name(expr) """ def __init__(self, selector, name, arguments): self.selector = selector self.name = ascii_lower(name) self.arguments = arguments def __repr__(self): return '%s[%r:%s(%r)]' % ( self.__class__.__name__, self.selector, self.name, [token.value for token in self.arguments]) def argument_types(self): return [token.type for token in self.arguments] def canonical(self): args = ''.join(token.css() for token in self.arguments) return '%s:%s(%s)' % (self.selector.canonical(), self.name, args) def specificity(self): a, b, c = self.selector.specificity() b += 1 return a, b, c class Pseudo(object): """ Represents selector:ident """ def __init__(self, selector, ident): self.selector = selector self.ident = ascii_lower(ident) def __repr__(self): return '%s[%r:%s]' % ( self.__class__.__name__, self.selector, self.ident) def canonical(self): return '%s:%s' % (self.selector.canonical(), self.ident) def specificity(self): a, b, c = self.selector.specificity() b += 1 return a, b, c class Negation(object): """ Represents selector:not(subselector) """ def __init__(self, selector, subselector): self.selector = selector self.subselector = subselector def __repr__(self): return '%s[%r:not(%r)]' % ( self.__class__.__name__, self.selector, self.subselector) def canonical(self): subsel = self.subselector.canonical() if len(subsel) > 1: subsel = subsel.lstrip('*') return '%s:not(%s)' % (self.selector.canonical(), subsel) def specificity(self): a1, b1, c1 = self.selector.specificity() a2, b2, c2 = self.subselector.specificity() return a1 + a2, b1 + b2, c1 + c2 class Attrib(object): """ Represents selector[namespace|attrib operator value] """ def __init__(self, selector, namespace, attrib, operator, value): self.selector = selector self.namespace = namespace self.attrib = attrib self.operator = operator self.value = value def __repr__(self): if self.namespace: attrib = '%s|%s' % (self.namespace, self.attrib) else: attrib = self.attrib if self.operator == 'exists': return '%s[%r[%s]]' % ( self.__class__.__name__, self.selector, attrib) else: return '%s[%r[%s %s %r]]' % ( self.__class__.__name__, self.selector, attrib, self.operator, self.value.value) def canonical(self): if self.namespace: attrib = '%s|%s' % (self.namespace, self.attrib) else: attrib = self.attrib if self.operator == 'exists': op = attrib else: op = '%s%s%s' % (attrib, self.operator, self.value.css()) return '%s[%s]' % (self.selector.canonical(), op) def specificity(self): a, b, c = self.selector.specificity() b += 1 return a, b, c class Element(object): """ Represents namespace|element `None` is for the universal selector '*' """ def __init__(self, namespace=None, element=None): self.namespace = namespace self.element = element def __repr__(self): return '%s[%s]' % (self.__class__.__name__, self.canonical()) def canonical(self): element = self.element or '*' if self.namespace: element = '%s|%s' % (self.namespace, element) return element def specificity(self): if self.element: return 0, 0, 1 else: return 0, 0, 0 class Hash(object): """ Represents selector#id """ def __init__(self, selector, id): self.selector = selector self.id = id def __repr__(self): return '%s[%r#%s]' % ( self.__class__.__name__, self.selector, self.id) def canonical(self): return '%s#%s' % (self.selector.canonical(), self.id) def specificity(self): a, b, c = self.selector.specificity() a += 1 return a, b, c class CombinedSelector(object): def __init__(self, selector, combinator, subselector): assert selector is not None self.selector = selector self.combinator = combinator self.subselector = subselector def __repr__(self): if self.combinator == ' ': comb = '' else: comb = self.combinator return '%s[%r %s %r]' % ( self.__class__.__name__, self.selector, comb, self.subselector) def canonical(self): subsel = self.subselector.canonical() if len(subsel) > 1: subsel = subsel.lstrip('*') return '%s %s %s' % ( self.selector.canonical(), self.combinator, subsel) def specificity(self): a1, b1, c1 = self.selector.specificity() a2, b2, c2 = self.subselector.specificity() return a1 + a2, b1 + b2, c1 + c2 #### Parser # foo _el_re = re.compile(r'^[ \t\r\n\f]*([a-zA-Z]+)[ \t\r\n\f]*$') # foo#bar or #bar _id_re = re.compile(r'^[ \t\r\n\f]*([a-zA-Z]*)#([a-zA-Z0-9_-]+)[ \t\r\n\f]*$') # foo.bar or .bar _class_re = re.compile( r'^[ \t\r\n\f]*([a-zA-Z]*)\.([a-zA-Z][a-zA-Z0-9_-]*)[ \t\r\n\f]*$') def parse(css): """Parse a CSS *group of selectors*. If you don't care about pseudo-elements or selector specificity, you can skip this and use :meth:`~GenericTranslator.css_to_xpath`. :param css: A *group of selectors* as an Unicode string. :raises: :class:`SelectorSyntaxError` on invalid selectors. :returns: A list of parsed :class:`Selector` objects, one for each selector in the comma-separated group. """ # Fast path for simple cases match = _el_re.match(css) if match: return [Selector(Element(element=match.group(1)))] match = _id_re.match(css) if match is not None: return [Selector(Hash(Element(element=match.group(1) or None), match.group(2)))] match = _class_re.match(css) if match is not None: return [Selector(Class(Element(element=match.group(1) or None), match.group(2)))] stream = TokenStream(tokenize(css)) stream.source = css return list(parse_selector_group(stream)) # except SelectorSyntaxError: # e = sys.exc_info()[1] # message = "%s at %s -> %r" % ( # e, stream.used, stream.peek()) # e.msg = message # e.args = tuple([message]) # raise def parse_selector_group(stream): stream.skip_whitespace() while 1: yield Selector(*parse_selector(stream)) if stream.peek() == ('DELIM', ','): stream.next() stream.skip_whitespace() else: break def parse_selector(stream): result, pseudo_element = parse_simple_selector(stream) while 1: stream.skip_whitespace() peek = stream.peek() if peek in (('EOF', None), ('DELIM', ',')): break if pseudo_element: raise SelectorSyntaxError( 'Got pseudo-element ::%s not at the end of a selector' % pseudo_element) if peek.is_delim('+', '>', '~'): # A combinator combinator = stream.next().value stream.skip_whitespace() else: # By exclusion, the last parse_simple_selector() ended # at peek == ' ' combinator = ' ' next_selector, pseudo_element = parse_simple_selector(stream) result = CombinedSelector(result, combinator, next_selector) return result, pseudo_element def parse_simple_selector(stream, inside_negation=False): stream.skip_whitespace() selector_start = len(stream.used) peek = stream.peek() if peek.type == 'IDENT' or peek == ('DELIM', '*'): if peek.type == 'IDENT': namespace = stream.next().value else: stream.next() namespace = None if stream.peek() == ('DELIM', '|'): stream.next() element = stream.next_ident_or_star() else: element = namespace namespace = None else: element = namespace = None result = Element(namespace, element) pseudo_element = None while 1: peek = stream.peek() if peek.type in ('S', 'EOF') or peek.is_delim(',', '+', '>', '~') or ( inside_negation and peek == ('DELIM', ')')): break if pseudo_element: raise SelectorSyntaxError( 'Got pseudo-element ::%s not at the end of a selector' % pseudo_element) if peek.type == 'HASH': result = Hash(result, stream.next().value) elif peek == ('DELIM', '.'): stream.next() result = Class(result, stream.next_ident()) elif peek == ('DELIM', '|'): stream.next() result = Element(None, stream.next_ident()) elif peek == ('DELIM', '['): stream.next() result = parse_attrib(result, stream) elif peek == ('DELIM', ':'): stream.next() if stream.peek() == ('DELIM', ':'): stream.next() pseudo_element = stream.next_ident() if stream.peek() == ('DELIM', '('): stream.next() pseudo_element = FunctionalPseudoElement( pseudo_element, parse_arguments(stream)) continue ident = stream.next_ident() if ident.lower() in ('first-line', 'first-letter', 'before', 'after'): # Special case: CSS 2.1 pseudo-elements can have a single ':' # Any new pseudo-element must have two. pseudo_element = _unicode(ident) continue if stream.peek() != ('DELIM', '('): result = Pseudo(result, ident) if result.__repr__() == 'Pseudo[Element[*]:scope]': if not (len(stream.used) == 2 or (len(stream.used) == 3 and stream.used[0].type == 'S')): raise SelectorSyntaxError( 'Got immediate child pseudo-element ":scope" ' 'not at the start of a selector') continue stream.next() stream.skip_whitespace() if ident.lower() == 'not': if inside_negation: raise SelectorSyntaxError('Got nested :not()') argument, argument_pseudo_element = parse_simple_selector( stream, inside_negation=True) next = stream.next() if argument_pseudo_element: raise SelectorSyntaxError( 'Got pseudo-element ::%s inside :not() at %s' % (argument_pseudo_element, next.pos)) if next != ('DELIM', ')'): raise SelectorSyntaxError("Expected ')', got %s" % (next,)) result = Negation(result, argument) else: result = Function(result, ident, parse_arguments(stream)) else: raise SelectorSyntaxError( "Expected selector, got %s" % (peek,)) if len(stream.used) == selector_start: raise SelectorSyntaxError( "Expected selector, got %s" % (stream.peek(),)) return result, pseudo_element def parse_arguments(stream): arguments = [] while 1: stream.skip_whitespace() next = stream.next() if next.type in ('IDENT', 'STRING', 'NUMBER') or next in [ ('DELIM', '+'), ('DELIM', '-')]: arguments.append(next) elif next == ('DELIM', ')'): return arguments else: raise SelectorSyntaxError( "Expected an argument, got %s" % (next,)) def parse_attrib(selector, stream): stream.skip_whitespace() attrib = stream.next_ident_or_star() if attrib is None and stream.peek() != ('DELIM', '|'): raise SelectorSyntaxError( "Expected '|', got %s" % (stream.peek(),)) if stream.peek() == ('DELIM', '|'): stream.next() if stream.peek() == ('DELIM', '='): namespace = None stream.next() op = '|=' else: namespace = attrib attrib = stream.next_ident() op = None else: namespace = op = None if op is None: stream.skip_whitespace() next = stream.next() if next == ('DELIM', ']'): return Attrib(selector, namespace, attrib, 'exists', None) elif next == ('DELIM', '='): op = '=' elif next.is_delim('^', '$', '*', '~', '|', '!') and ( stream.peek() == ('DELIM', '=')): op = next.value + '=' stream.next() else: raise SelectorSyntaxError( "Operator expected, got %s" % (next,)) stream.skip_whitespace() value = stream.next() if value.type not in ('IDENT', 'STRING'): raise SelectorSyntaxError( "Expected string or ident, got %s" % (value,)) stream.skip_whitespace() next = stream.next() if next != ('DELIM', ']'): raise SelectorSyntaxError( "Expected ']', got %s" % (next,)) return Attrib(selector, namespace, attrib, op, value) def parse_series(tokens): """ Parses the arguments for :nth-child() and friends. :raises: A list of tokens :returns: :``(a, b)`` """ for token in tokens: if token.type == 'STRING': raise ValueError('String tokens not allowed in series.') s = ''.join(token.value for token in tokens).strip() if s == 'odd': return 2, 1 elif s == 'even': return 2, 0 elif s == 'n': return 1, 0 if 'n' not in s: # Just b return 0, int(s) a, b = s.split('n', 1) if not a: a = 1 elif a == '-' or a == '+': a = int(a+'1') else: a = int(a) if not b: b = 0 else: b = int(b) return a, b #### Token objects class Token(tuple): def __new__(cls, type_, value, pos): obj = tuple.__new__(cls, (type_, value)) obj.pos = pos return obj def __repr__(self): return "<%s '%s' at %i>" % (self.type, self.value, self.pos) def is_delim(self, *values): return self.type == 'DELIM' and self.value in values type = property(operator.itemgetter(0)) value = property(operator.itemgetter(1)) def css(self): if self.type == 'STRING': return repr(self.value) else: return self.value class EOFToken(Token): def __new__(cls, pos): return Token.__new__(cls, 'EOF', None, pos) def __repr__(self): return '<%s at %i>' % (self.type, self.pos) #### Tokenizer class TokenMacros: unicode_escape = r'\\([0-9a-f]{1,6})(?:\r\n|[ \n\r\t\f])?' escape = unicode_escape + r'|\\[^\n\r\f0-9a-f]' string_escape = r'\\(?:\n|\r\n|\r|\f)|' + escape nonascii = r'[^\0-\177]' nmchar = '[_a-z0-9-]|%s|%s' % (escape, nonascii) nmstart = '[_a-z]|%s|%s' % (escape, nonascii) def _compile(pattern): return re.compile(pattern % vars(TokenMacros), re.IGNORECASE).match _match_whitespace = _compile(r'[ \t\r\n\f]+') _match_number = _compile(r'[+-]?(?:[0-9]*\.[0-9]+|[0-9]+)') _match_hash = _compile('#(?:%(nmchar)s)+') _match_ident = _compile('-?(?:%(nmstart)s)(?:%(nmchar)s)*') _match_string_by_quote = { "'": _compile(r"([^\n\r\f\\']|%(string_escape)s)*"), '"': _compile(r'([^\n\r\f\\"]|%(string_escape)s)*'), } _sub_simple_escape = re.compile(r'\\(.)').sub _sub_unicode_escape = re.compile(TokenMacros.unicode_escape, re.I).sub _sub_newline_escape =re.compile(r'\\(?:\n|\r\n|\r|\f)').sub # Same as r'\1', but faster on CPython _replace_simple = operator.methodcaller('group', 1) def _replace_unicode(match): codepoint = int(match.group(1), 16) if codepoint > sys.maxunicode: codepoint = 0xFFFD return _unichr(codepoint) def unescape_ident(value): value = _sub_unicode_escape(_replace_unicode, value) value = _sub_simple_escape(_replace_simple, value) return value def tokenize(s): pos = 0 len_s = len(s) while pos < len_s: match = _match_whitespace(s, pos=pos) if match: yield Token('S', ' ', pos) pos = match.end() continue match = _match_ident(s, pos=pos) if match: value = _sub_simple_escape(_replace_simple, _sub_unicode_escape(_replace_unicode, match.group())) yield Token('IDENT', value, pos) pos = match.end() continue match = _match_hash(s, pos=pos) if match: value = _sub_simple_escape(_replace_simple, _sub_unicode_escape(_replace_unicode, match.group()[1:])) yield Token('HASH', value, pos) pos = match.end() continue quote = s[pos] if quote in _match_string_by_quote: match = _match_string_by_quote[quote](s, pos=pos + 1) assert match, 'Should have found at least an empty match' end_pos = match.end() if end_pos == len_s: raise SelectorSyntaxError('Unclosed string at %s' % pos) if s[end_pos] != quote: raise SelectorSyntaxError('Invalid string at %s' % pos) value = _sub_simple_escape(_replace_simple, _sub_unicode_escape(_replace_unicode, _sub_newline_escape('', match.group()))) yield Token('STRING', value, pos) pos = end_pos + 1 continue match = _match_number(s, pos=pos) if match: value = match.group() yield Token('NUMBER', value, pos) pos = match.end() continue pos2 = pos + 2 if s[pos:pos2] == '/*': pos = s.find('*/', pos2) if pos == -1: pos = len_s else: pos += 2 continue yield Token('DELIM', s[pos], pos) pos += 1 assert pos == len_s yield EOFToken(pos) class TokenStream(object): def __init__(self, tokens, source=None): self.used = [] self.tokens = iter(tokens) self.source = source self.peeked = None self._peeking = False try: self.next_token = self.tokens.next except AttributeError: # Python 3 self.next_token = self.tokens.__next__ def next(self): if self._peeking: self._peeking = False self.used.append(self.peeked) return self.peeked else: next = self.next_token() self.used.append(next) return next def peek(self): if not self._peeking: self.peeked = self.next_token() self._peeking = True return self.peeked def next_ident(self): next = self.next() if next.type != 'IDENT': raise SelectorSyntaxError('Expected ident, got %s' % (next,)) return next.value def next_ident_or_star(self): next = self.next() if next.type == 'IDENT': return next.value elif next == ('DELIM', '*'): return None else: raise SelectorSyntaxError( "Expected ident or '*', got %s" % (next,)) def skip_whitespace(self): peek = self.peek() if peek.type == 'S': self.next() ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/cssselect/xpath.py ================================================ # -*- coding: utf-8 -*- """ cssselect.xpath =============== Translation of parsed CSS selectors to XPath expressions. :copyright: (c) 2007-2012 Ian Bicking and contributors. See AUTHORS for more details. :license: BSD, see LICENSE for more details. """ import sys import re from cssselect.parser import parse, parse_series, SelectorError if sys.version_info[0] < 3: _basestring = basestring _unicode = unicode else: _basestring = str _unicode = str def _unicode_safe_getattr(obj, name, default=None): # getattr() with a non-ASCII name fails on Python 2.x name = name.encode('ascii', 'replace').decode('ascii') return getattr(obj, name, default) class ExpressionError(SelectorError, RuntimeError): """Unknown or unsupported selector (eg. pseudo-class).""" #### XPath Helpers class XPathExpr(object): def __init__(self, path='', element='*', condition='', star_prefix=False): self.path = path self.element = element self.condition = condition def __str__(self): path = _unicode(self.path) + _unicode(self.element) if self.condition: path += '[%s]' % self.condition return path def __repr__(self): return '%s[%s]' % (self.__class__.__name__, self) def add_condition(self, condition): if self.condition: self.condition = '%s and (%s)' % (self.condition, condition) else: self.condition = condition return self def add_name_test(self): if self.element == '*': # We weren't doing a test anyway return self.add_condition( "name() = %s" % GenericTranslator.xpath_literal(self.element)) self.element = '*' def add_star_prefix(self): """ Append '*/' to the path to keep the context constrained to a single parent. """ self.path += '*/' def join(self, combiner, other): path = _unicode(self) + combiner # Any "star prefix" is redundant when joining. if other.path != '*/': path += other.path self.path = path self.element = other.element self.condition = other.condition return self split_at_single_quotes = re.compile("('+)").split # The spec is actually more permissive than that, but don’t bother. # This is just for the fast path. # http://www.w3.org/TR/REC-xml/#NT-NameStartChar is_safe_name = re.compile('^[a-zA-Z_][a-zA-Z0-9_.-]*$').match # Test that the string is not empty and does not contain whitespace is_non_whitespace = re.compile(r'^[^ \t\r\n\f]+$').match #### Translation class GenericTranslator(object): """ Translator for "generic" XML documents. Everything is case-sensitive, no assumption is made on the meaning of element names and attribute names. """ #### #### HERE BE DRAGONS #### #### You are welcome to hook into this to change some behavior, #### but do so at your own risks. #### Until it has received a lot more work and review, #### I reserve the right to change this API in backward-incompatible ways #### with any minor version of cssselect. #### See https://github.com/scrapy/cssselect/pull/22 #### -- Simon Sapin. #### combinator_mapping = { ' ': 'descendant', '>': 'child', '+': 'direct_adjacent', '~': 'indirect_adjacent', } attribute_operator_mapping = { 'exists': 'exists', '=': 'equals', '~=': 'includes', '|=': 'dashmatch', '^=': 'prefixmatch', '$=': 'suffixmatch', '*=': 'substringmatch', '!=': 'different', # XXX Not in Level 3 but meh } #: The attribute used for ID selectors depends on the document language: #: http://www.w3.org/TR/selectors/#id-selectors id_attribute = 'id' #: The attribute used for ``:lang()`` depends on the document language: #: http://www.w3.org/TR/selectors/#lang-pseudo lang_attribute = 'xml:lang' #: The case sensitivity of document language element names, #: attribute names, and attribute values in selectors depends #: on the document language. #: http://www.w3.org/TR/selectors/#casesens #: #: When a document language defines one of these as case-insensitive, #: cssselect assumes that the document parser makes the parsed values #: lower-case. Making the selector lower-case too makes the comparaison #: case-insensitive. #: #: In HTML, element names and attributes names (but not attribute values) #: are case-insensitive. All of lxml.html, html5lib, BeautifulSoup4 #: and HTMLParser make them lower-case in their parse result, so #: the assumption holds. lower_case_element_names = False lower_case_attribute_names = False lower_case_attribute_values = False # class used to represent and xpath expression xpathexpr_cls = XPathExpr def css_to_xpath(self, css, prefix='descendant-or-self::'): """Translate a *group of selectors* to XPath. Pseudo-elements are not supported here since XPath only knows about "real" elements. :param css: A *group of selectors* as an Unicode string. :param prefix: This string is prepended to the XPath expression for each selector. The default makes selectors scoped to the context node’s subtree. :raises: :class:`SelectorSyntaxError` on invalid selectors, :class:`ExpressionError` on unknown/unsupported selectors, including pseudo-elements. :returns: The equivalent XPath 1.0 expression as an Unicode string. """ return ' | '.join(self.selector_to_xpath(selector, prefix, translate_pseudo_elements=True) for selector in parse(css)) def selector_to_xpath(self, selector, prefix='descendant-or-self::', translate_pseudo_elements=False): """Translate a parsed selector to XPath. :param selector: A parsed :class:`Selector` object. :param prefix: This string is prepended to the resulting XPath expression. The default makes selectors scoped to the context node’s subtree. :param translate_pseudo_elements: Unless this is set to ``True`` (as :meth:`css_to_xpath` does), the :attr:`~Selector.pseudo_element` attribute of the selector is ignored. It is the caller's responsibility to reject selectors with pseudo-elements, or to account for them somehow. :raises: :class:`ExpressionError` on unknown/unsupported selectors. :returns: The equivalent XPath 1.0 expression as an Unicode string. """ tree = getattr(selector, 'parsed_tree', None) if not tree: raise TypeError('Expected a parsed selector, got %r' % (selector,)) xpath = self.xpath(tree) assert isinstance(xpath, self.xpathexpr_cls) # help debug a missing 'return' if translate_pseudo_elements and selector.pseudo_element: xpath = self.xpath_pseudo_element(xpath, selector.pseudo_element) return (prefix or '') + _unicode(xpath) def xpath_pseudo_element(self, xpath, pseudo_element): """Translate a pseudo-element. Defaults to not supporting pseudo-elements at all, but can be overridden by sub-classes. """ raise ExpressionError('Pseudo-elements are not supported.') @staticmethod def xpath_literal(s): s = _unicode(s) if "'" not in s: s = "'%s'" % s elif '"' not in s: s = '"%s"' % s else: s = "concat(%s)" % ','.join([ (("'" in part) and '"%s"' or "'%s'") % part for part in split_at_single_quotes(s) if part ]) return s def xpath(self, parsed_selector): """Translate any parsed selector object.""" type_name = type(parsed_selector).__name__ method = getattr(self, 'xpath_%s' % type_name.lower(), None) if method is None: raise ExpressionError('%s is not supported.' % type_name) return method(parsed_selector) # Dispatched by parsed object type def xpath_combinedselector(self, combined): """Translate a combined selector.""" combinator = self.combinator_mapping[combined.combinator] method = getattr(self, 'xpath_%s_combinator' % combinator) return method(self.xpath(combined.selector), self.xpath(combined.subselector)) def xpath_negation(self, negation): xpath = self.xpath(negation.selector) sub_xpath = self.xpath(negation.subselector) sub_xpath.add_name_test() if sub_xpath.condition: return xpath.add_condition('not(%s)' % sub_xpath.condition) else: return xpath.add_condition('0') def xpath_function(self, function): """Translate a functional pseudo-class.""" method = 'xpath_%s_function' % function.name.replace('-', '_') method = _unicode_safe_getattr(self, method, None) if not method: raise ExpressionError( "The pseudo-class :%s() is unknown" % function.name) return method(self.xpath(function.selector), function) def xpath_pseudo(self, pseudo): """Translate a pseudo-class.""" method = 'xpath_%s_pseudo' % pseudo.ident.replace('-', '_') method = _unicode_safe_getattr(self, method, None) if not method: # TODO: better error message for pseudo-elements? raise ExpressionError( "The pseudo-class :%s is unknown" % pseudo.ident) return method(self.xpath(pseudo.selector)) def xpath_attrib(self, selector): """Translate an attribute selector.""" operator = self.attribute_operator_mapping[selector.operator] method = getattr(self, 'xpath_attrib_%s' % operator) if self.lower_case_attribute_names: name = selector.attrib.lower() else: name = selector.attrib safe = is_safe_name(name) if selector.namespace: name = '%s:%s' % (selector.namespace, name) safe = safe and is_safe_name(selector.namespace) if safe: attrib = '@' + name else: attrib = 'attribute::*[name() = %s]' % self.xpath_literal(name) if selector.value is None: value = None elif self.lower_case_attribute_values: value = selector.value.value.lower() else: value = selector.value.value return method(self.xpath(selector.selector), attrib, value) def xpath_class(self, class_selector): """Translate a class selector.""" # .foo is defined as [class~=foo] in the spec. xpath = self.xpath(class_selector.selector) return self.xpath_attrib_includes( xpath, '@class', class_selector.class_name) def xpath_hash(self, id_selector): """Translate an ID selector.""" xpath = self.xpath(id_selector.selector) return self.xpath_attrib_equals(xpath, '@id', id_selector.id) def xpath_element(self, selector): """Translate a type or universal selector.""" element = selector.element if not element: element = '*' safe = True else: safe = is_safe_name(element) if self.lower_case_element_names: element = element.lower() if selector.namespace: # Namespace prefixes are case-sensitive. # http://www.w3.org/TR/css3-namespace/#prefixes element = '%s:%s' % (selector.namespace, element) safe = safe and is_safe_name(selector.namespace) xpath = self.xpathexpr_cls(element=element) if not safe: xpath.add_name_test() return xpath # CombinedSelector: dispatch by combinator def xpath_descendant_combinator(self, left, right): """right is a child, grand-child or further descendant of left""" return left.join('/descendant-or-self::*/', right) def xpath_child_combinator(self, left, right): """right is an immediate child of left""" return left.join('/', right) def xpath_direct_adjacent_combinator(self, left, right): """right is a sibling immediately after left""" xpath = left.join('/following-sibling::', right) xpath.add_name_test() return xpath.add_condition('position() = 1') def xpath_indirect_adjacent_combinator(self, left, right): """right is a sibling after left, immediately or not""" return left.join('/following-sibling::', right) # Function: dispatch by function/pseudo-class name def xpath_nth_child_function(self, xpath, function, last=False, add_name_test=True): try: a, b = parse_series(function.arguments) except ValueError: raise ExpressionError("Invalid series: '%r'" % function.arguments) # From https://www.w3.org/TR/css3-selectors/#structural-pseudos: # # :nth-child(an+b) # an+b-1 siblings before # # :nth-last-child(an+b) # an+b-1 siblings after # # :nth-of-type(an+b) # an+b-1 siblings with the same expanded element name before # # :nth-last-of-type(an+b) # an+b-1 siblings with the same expanded element name after # # So, # for :nth-child and :nth-of-type # # count(preceding-sibling::) = an+b-1 # # for :nth-last-child and :nth-last-of-type # # count(following-sibling::) = an+b-1 # # therefore, # count(...) - (b-1) ≡ 0 (mod a) # # if a == 0: # ~~~~~~~~~~ # count(...) = b-1 # # if a < 0: # ~~~~~~~~~ # count(...) - b +1 <= 0 # -> count(...) <= b-1 # # if a > 0: # ~~~~~~~~~ # count(...) - b +1 >= 0 # -> count(...) >= b-1 # work with b-1 instead b_min_1 = b - 1 # early-exit condition 1: # ~~~~~~~~~~~~~~~~~~~~~~~ # for a == 1, nth-*(an+b) means n+b-1 siblings before/after, # and since n ∈ {0, 1, 2, ...}, if b-1<=0, # there is always an "n" matching any number of siblings (maybe none) if a == 1 and b_min_1 <=0: return xpath # early-exit condition 2: # ~~~~~~~~~~~~~~~~~~~~~~~ # an+b-1 siblings with a<0 and (b-1)<0 is not possible if a < 0 and b_min_1 < 0: return xpath.add_condition('0') # `add_name_test` boolean is inverted and somewhat counter-intuitive: # # nth_of_type() calls nth_child(add_name_test=False) if add_name_test: nodetest = '*' else: nodetest = '%s' % xpath.element # count siblings before or after the element if not last: siblings_count = 'count(preceding-sibling::%s)' % nodetest else: siblings_count = 'count(following-sibling::%s)' % nodetest # special case of fixed position: nth-*(0n+b) # if a == 0: # ~~~~~~~~~~ # count(***-sibling::***) = b-1 if a == 0: return xpath.add_condition('%s = %s' % (siblings_count, b_min_1)) expr = [] if a > 0: # siblings count, an+b-1, is always >= 0, # so if a>0, and (b-1)<=0, an "n" exists to satisfy this, # therefore, the predicate is only interesting if (b-1)>0 if b_min_1 > 0: expr.append('%s >= %s' % (siblings_count, b_min_1)) else: # if a<0, and (b-1)<0, no "n" satisfies this, # this is tested above as an early exist condition # otherwise, expr.append('%s <= %s' % (siblings_count, b_min_1)) # operations modulo 1 or -1 are simpler, one only needs to verify: # # - either: # count(***-sibling::***) - (b-1) = n = 0, 1, 2, 3, etc., # i.e. count(***-sibling::***) >= (b-1) # # - or: # count(***-sibling::***) - (b-1) = -n = 0, -1, -2, -3, etc., # i.e. count(***-sibling::***) <= (b-1) # we we just did above. # if abs(a) != 1: # count(***-sibling::***) - (b-1) ≡ 0 (mod a) left = siblings_count # apply "modulo a" on 2nd term, -(b-1), # to simplify things like "(... +6) % -3", # and also make it positive with |a| b_neg = (-b_min_1) % abs(a) if b_neg != 0: b_neg = '+%s' % b_neg left = '(%s %s)' % (left, b_neg) expr.append('%s mod %s = 0' % (left, a)) xpath.add_condition(' and '.join(expr)) return xpath def xpath_nth_last_child_function(self, xpath, function): return self.xpath_nth_child_function(xpath, function, last=True) def xpath_nth_of_type_function(self, xpath, function): if xpath.element == '*': raise ExpressionError( "*:nth-of-type() is not implemented") return self.xpath_nth_child_function(xpath, function, add_name_test=False) def xpath_nth_last_of_type_function(self, xpath, function): if xpath.element == '*': raise ExpressionError( "*:nth-of-type() is not implemented") return self.xpath_nth_child_function(xpath, function, last=True, add_name_test=False) def xpath_contains_function(self, xpath, function): # Defined there, removed in later drafts: # http://www.w3.org/TR/2001/CR-css3-selectors-20011113/#content-selectors if function.argument_types() not in (['STRING'], ['IDENT']): raise ExpressionError( "Expected a single string or ident for :contains(), got %r" % function.arguments) value = function.arguments[0].value return xpath.add_condition( 'contains(., %s)' % self.xpath_literal(value)) def xpath_lang_function(self, xpath, function): if function.argument_types() not in (['STRING'], ['IDENT']): raise ExpressionError( "Expected a single string or ident for :lang(), got %r" % function.arguments) value = function.arguments[0].value return xpath.add_condition( "lang(%s)" % (self.xpath_literal(value))) # Pseudo: dispatch by pseudo-class name def xpath_root_pseudo(self, xpath): return xpath.add_condition("not(parent::*)") # CSS immediate children (CSS ":scope > div" to XPath "child::div" or "./div") # Works only at the start of a selector # Needed to get immediate children of a processed selector in Scrapy # for product in response.css('.product'): # description = product.css(':scope > div::text').get() def xpath_scope_pseudo(self, xpath): return xpath.add_condition("1") def xpath_first_child_pseudo(self, xpath): return xpath.add_condition('count(preceding-sibling::*) = 0') def xpath_last_child_pseudo(self, xpath): return xpath.add_condition('count(following-sibling::*) = 0') def xpath_first_of_type_pseudo(self, xpath): if xpath.element == '*': raise ExpressionError( "*:first-of-type is not implemented") return xpath.add_condition('count(preceding-sibling::%s) = 0' % xpath.element) def xpath_last_of_type_pseudo(self, xpath): if xpath.element == '*': raise ExpressionError( "*:last-of-type is not implemented") return xpath.add_condition('count(following-sibling::%s) = 0' % xpath.element) def xpath_only_child_pseudo(self, xpath): return xpath.add_condition('count(parent::*/child::*) = 1') def xpath_only_of_type_pseudo(self, xpath): if xpath.element == '*': raise ExpressionError( "*:only-of-type is not implemented") return xpath.add_condition('count(parent::*/child::%s) = 1' % xpath.element) def xpath_empty_pseudo(self, xpath): return xpath.add_condition("not(*) and not(string-length())") def pseudo_never_matches(self, xpath): """Common implementation for pseudo-classes that never match.""" return xpath.add_condition("0") xpath_link_pseudo = pseudo_never_matches xpath_visited_pseudo = pseudo_never_matches xpath_hover_pseudo = pseudo_never_matches xpath_active_pseudo = pseudo_never_matches xpath_focus_pseudo = pseudo_never_matches xpath_target_pseudo = pseudo_never_matches xpath_enabled_pseudo = pseudo_never_matches xpath_disabled_pseudo = pseudo_never_matches xpath_checked_pseudo = pseudo_never_matches # Attrib: dispatch by attribute operator def xpath_attrib_exists(self, xpath, name, value): assert not value xpath.add_condition(name) return xpath def xpath_attrib_equals(self, xpath, name, value): xpath.add_condition('%s = %s' % (name, self.xpath_literal(value))) return xpath def xpath_attrib_different(self, xpath, name, value): # FIXME: this seems like a weird hack... if value: xpath.add_condition('not(%s) or %s != %s' % (name, name, self.xpath_literal(value))) else: xpath.add_condition('%s != %s' % (name, self.xpath_literal(value))) return xpath def xpath_attrib_includes(self, xpath, name, value): if is_non_whitespace(value): xpath.add_condition( "%s and contains(concat(' ', normalize-space(%s), ' '), %s)" % (name, name, self.xpath_literal(' '+value+' '))) else: xpath.add_condition('0') return xpath def xpath_attrib_dashmatch(self, xpath, name, value): # Weird, but true... xpath.add_condition('%s and (%s = %s or starts-with(%s, %s))' % ( name, name, self.xpath_literal(value), name, self.xpath_literal(value + '-'))) return xpath def xpath_attrib_prefixmatch(self, xpath, name, value): if value: xpath.add_condition('%s and starts-with(%s, %s)' % ( name, name, self.xpath_literal(value))) else: xpath.add_condition('0') return xpath def xpath_attrib_suffixmatch(self, xpath, name, value): if value: # Oddly there is a starts-with in XPath 1.0, but not ends-with xpath.add_condition( '%s and substring(%s, string-length(%s)-%s) = %s' % (name, name, name, len(value)-1, self.xpath_literal(value))) else: xpath.add_condition('0') return xpath def xpath_attrib_substringmatch(self, xpath, name, value): if value: # Attribute selectors are case sensitive xpath.add_condition('%s and contains(%s, %s)' % ( name, name, self.xpath_literal(value))) else: xpath.add_condition('0') return xpath class HTMLTranslator(GenericTranslator): """ Translator for (X)HTML documents. Has a more useful implementation of some pseudo-classes based on HTML-specific element names and attribute names, as described in the `HTML5 specification`_. It assumes no-quirks mode. The API is the same as :class:`GenericTranslator`. .. _HTML5 specification: http://www.w3.org/TR/html5/links.html#selectors :param xhtml: If false (the default), element names and attribute names are case-insensitive. """ lang_attribute = 'lang' def __init__(self, xhtml=False): self.xhtml = xhtml # Might be useful for sub-classes? if not xhtml: # See their definition in GenericTranslator. self.lower_case_element_names = True self.lower_case_attribute_names = True def xpath_checked_pseudo(self, xpath): # FIXME: is this really all the elements? return xpath.add_condition( "(@selected and name(.) = 'option') or " "(@checked " "and (name(.) = 'input' or name(.) = 'command')" "and (@type = 'checkbox' or @type = 'radio'))") def xpath_lang_function(self, xpath, function): if function.argument_types() not in (['STRING'], ['IDENT']): raise ExpressionError( "Expected a single string or ident for :lang(), got %r" % function.arguments) value = function.arguments[0].value return xpath.add_condition( "ancestor-or-self::*[@lang][1][starts-with(concat(" # XPath 1.0 has no lower-case function... "translate(@%s, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', " "'abcdefghijklmnopqrstuvwxyz'), " "'-'), %s)]" % (self.lang_attribute, self.xpath_literal(value.lower() + '-'))) def xpath_link_pseudo(self, xpath): return xpath.add_condition("@href and " "(name(.) = 'a' or name(.) = 'link' or name(.) = 'area')") # Links are never visited, the implementation for :visited is the same # as in GenericTranslator def xpath_disabled_pseudo(self, xpath): # http://www.w3.org/TR/html5/section-index.html#attributes-1 return xpath.add_condition(''' ( @disabled and ( (name(.) = 'input' and @type != 'hidden') or name(.) = 'button' or name(.) = 'select' or name(.) = 'textarea' or name(.) = 'command' or name(.) = 'fieldset' or name(.) = 'optgroup' or name(.) = 'option' ) ) or ( ( (name(.) = 'input' and @type != 'hidden') or name(.) = 'button' or name(.) = 'select' or name(.) = 'textarea' ) and ancestor::fieldset[@disabled] ) ''') # FIXME: in the second half, add "and is not a descendant of that # fieldset element's first legend element child, if any." def xpath_enabled_pseudo(self, xpath): # http://www.w3.org/TR/html5/section-index.html#attributes-1 return xpath.add_condition(''' ( @href and ( name(.) = 'a' or name(.) = 'link' or name(.) = 'area' ) ) or ( ( name(.) = 'command' or name(.) = 'fieldset' or name(.) = 'optgroup' ) and not(@disabled) ) or ( ( (name(.) = 'input' and @type != 'hidden') or name(.) = 'button' or name(.) = 'select' or name(.) = 'textarea' or name(.) = 'keygen' ) and not (@disabled or ancestor::fieldset[@disabled]) ) or ( name(.) = 'option' and not( @disabled or ancestor::optgroup[@disabled] ) ) ''') # FIXME: ... or "li elements that are children of menu elements, # and that have a child element that defines a command, if the first # such element's Disabled State facet is false (not disabled)". # FIXME: after ancestor::fieldset[@disabled], add "and is not a # descendant of that fieldset element's first legend element child, # if any." ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/cssselect-1.1.0.dist-info/AUTHORS ================================================ Daniel Graña Ian Bicking James Salter Laurence Rowe Mikhail Korobov Nik Nyby Paul Tremberth Simon Potter Simon Sapin Stefan Behnel Thomas Grainger Varialus Arthur Darcet ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/cssselect-1.1.0.dist-info/INSTALLER ================================================ pip ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/cssselect-1.1.0.dist-info/LICENSE ================================================ Copyright (c) 2007-2012 Ian Bicking and contributors. See AUTHORS for more details. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of Ian Bicking nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL IAN BICKING OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/cssselect-1.1.0.dist-info/METADATA ================================================ Metadata-Version: 2.1 Name: cssselect Version: 1.1.0 Summary: cssselect parses CSS3 Selectors and translates them to XPath 1.0 Home-page: https://github.com/scrapy/cssselect Author: Ian Bicking Author-email: ianb@colorstudy.com Maintainer: Paul Tremberth Maintainer-email: paul.tremberth@gmail.com License: BSD Platform: UNKNOWN Classifier: Development Status :: 4 - Beta Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: BSD License Classifier: Programming Language :: Python :: 2 Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: 3.4 Classifier: Programming Language :: Python :: 3.5 Classifier: Programming Language :: Python :: 3.6 Requires-Python: >=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.* =================================== cssselect: CSS Selectors for Python =================================== .. image:: https://img.shields.io/pypi/v/cssselect.svg :target: https://pypi.python.org/pypi/cssselect :alt: PyPI Version .. image:: https://img.shields.io/pypi/pyversions/cssselect.svg :target: https://pypi.python.org/pypi/cssselect :alt: Supported Python Versions .. image:: https://img.shields.io/travis/scrapy/cssselect/master.svg :target: https://travis-ci.org/scrapy/cssselect :alt: Build Status .. image:: https://img.shields.io/codecov/c/github/scrapy/cssselect/master.svg :target: https://codecov.io/github/scrapy/cssselect?branch=master :alt: Coverage report *cssselect* parses `CSS3 Selectors`_ and translate them to `XPath 1.0`_ expressions. Such expressions can be used in lxml_ or another XPath engine to find the matching elements in an XML or HTML document. This module used to live inside of lxml as ``lxml.cssselect`` before it was extracted as a stand-alone project. .. _CSS3 Selectors: https://www.w3.org/TR/css3-selectors/ .. _XPath 1.0: https://www.w3.org/TR/xpath/ .. _lxml: http://lxml.de/ Quick facts: * Free software: BSD licensed * Compatible with Python 2.7 and 3.4+ * Latest documentation `on Read the Docs `_ * Source, issues and pull requests `on GitHub `_ * Releases `on PyPI `_ * Install with ``pip install cssselect`` ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/cssselect-1.1.0.dist-info/RECORD ================================================ cssselect-1.1.0.dist-info/AUTHORS,sha256=0xOj3H8iII6M_KWmoDYQRuzTrYrLPbJ8K2kVSAoQ5zQ,171 cssselect-1.1.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 cssselect-1.1.0.dist-info/LICENSE,sha256=XI2p90Tgr7qBpIybXb5zBI95izKH1vGvigXuCOuxCJI,1517 cssselect-1.1.0.dist-info/METADATA,sha256=L1k9gxlz3quPBMPepkTOo0tPXV2l8cQl-yZGnO-gNUc,2332 cssselect-1.1.0.dist-info/RECORD,, cssselect-1.1.0.dist-info/WHEEL,sha256=h_aVn5OB2IERUjMbi2pucmR_zzWJtk303YXvhh60NJ8,110 cssselect-1.1.0.dist-info/top_level.txt,sha256=GKK3Utu_ceog6CK27VXNdbyiqGnoyJo3970FLo5JdUU,10 cssselect/__init__.py,sha256=fmdpKrz5-uYAzXUh3LMOrEPiJMENB1gf962v5Nq5yis,639 cssselect/__pycache__/__init__.cpython-36.pyc,, cssselect/__pycache__/parser.cpython-36.pyc,, cssselect/__pycache__/xpath.cpython-36.pyc,, cssselect/parser.py,sha256=jrlRxEpSFfiqYHKfUHjgERdMQwFbvsh3sONi_HiTDys,26145 cssselect/xpath.py,sha256=Izy4CXmK6zMHg13PP63bBp065eFZNBfPJeNyhjSsS7Q,28257 ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/cssselect-1.1.0.dist-info/WHEEL ================================================ Wheel-Version: 1.0 Generator: bdist_wheel (0.33.4) Root-Is-Purelib: true Tag: py2-none-any Tag: py3-none-any ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/cssselect-1.1.0.dist-info/top_level.txt ================================================ cssselect ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/easy-install.pth ================================================ ./setuptools-40.8.0-py3.6.egg ./pip-19.0.3-py3.6.egg ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/exampleproj/__init__.py ================================================ """ An example project. @added: exampleproj NEXT """ from incremental import Version from ._version import __version__ __all__ = ["__version__"] if Version("exampleproj", "NEXT", 0, 0) > __version__: print("Unreleased!") ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/exampleproj/_version.py ================================================ # This file is auto-generated! Do not edit! # Use `python -m incremental.update exampleproj` to change this file. from incremental import Version __version__ = Version('exampleproj', 1, 2, 3) __all__ = ["__version__"] ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/gridfs/__init__.py ================================================ # Copyright 2009-present MongoDB, Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """GridFS is a specification for storing large objects in Mongo. The :mod:`gridfs` package is an implementation of GridFS on top of :mod:`pymongo`, exposing a file-like interface. .. mongodoc:: gridfs """ from bson.py3compat import abc from gridfs.errors import NoFile from gridfs.grid_file import (GridIn, GridOut, GridOutCursor, DEFAULT_CHUNK_SIZE, _clear_entity_type_registry) from pymongo import (ASCENDING, DESCENDING) from pymongo.common import UNAUTHORIZED_CODES, validate_string from pymongo.database import Database from pymongo.errors import ConfigurationError, OperationFailure class GridFS(object): """An instance of GridFS on top of a single Database. """ def __init__(self, database, collection="fs", disable_md5=False): """Create a new instance of :class:`GridFS`. Raises :class:`TypeError` if `database` is not an instance of :class:`~pymongo.database.Database`. :Parameters: - `database`: database to use - `collection` (optional): root collection to use - `disable_md5` (optional): When True, MD5 checksums will not be computed for uploaded files. Useful in environments where MD5 cannot be used for regulatory or other reasons. Defaults to False. .. versionchanged:: 3.1 Indexes are only ensured on the first write to the DB. .. versionchanged:: 3.0 `database` must use an acknowledged :attr:`~pymongo.database.Database.write_concern` .. mongodoc:: gridfs """ if not isinstance(database, Database): raise TypeError("database must be an instance of Database") database = _clear_entity_type_registry(database) if not database.write_concern.acknowledged: raise ConfigurationError('database must use ' 'acknowledged write_concern') self.__database = database self.__collection = database[collection] self.__files = self.__collection.files self.__chunks = self.__collection.chunks self.__disable_md5 = disable_md5 def new_file(self, **kwargs): """Create a new file in GridFS. Returns a new :class:`~gridfs.grid_file.GridIn` instance to which data can be written. Any keyword arguments will be passed through to :meth:`~gridfs.grid_file.GridIn`. If the ``"_id"`` of the file is manually specified, it must not already exist in GridFS. Otherwise :class:`~gridfs.errors.FileExists` is raised. :Parameters: - `**kwargs` (optional): keyword arguments for file creation """ # No need for __ensure_index_files_id() here; GridIn ensures # the (files_id, n) index when needed. return GridIn( self.__collection, disable_md5=self.__disable_md5, **kwargs) def put(self, data, **kwargs): """Put data in GridFS as a new file. Equivalent to doing:: try: f = new_file(**kwargs) f.write(data) finally: f.close() `data` can be either an instance of :class:`str` (:class:`bytes` in python 3) or a file-like object providing a :meth:`read` method. If an `encoding` keyword argument is passed, `data` can also be a :class:`unicode` (:class:`str` in python 3) instance, which will be encoded as `encoding` before being written. Any keyword arguments will be passed through to the created file - see :meth:`~gridfs.grid_file.GridIn` for possible arguments. Returns the ``"_id"`` of the created file. If the ``"_id"`` of the file is manually specified, it must not already exist in GridFS. Otherwise :class:`~gridfs.errors.FileExists` is raised. :Parameters: - `data`: data to be written as a file. - `**kwargs` (optional): keyword arguments for file creation .. versionchanged:: 3.0 w=0 writes to GridFS are now prohibited. """ grid_file = GridIn( self.__collection, disable_md5=self.__disable_md5, **kwargs) try: grid_file.write(data) finally: grid_file.close() return grid_file._id def get(self, file_id, session=None): """Get a file from GridFS by ``"_id"``. Returns an instance of :class:`~gridfs.grid_file.GridOut`, which provides a file-like interface for reading. :Parameters: - `file_id`: ``"_id"`` of the file to get - `session` (optional): a :class:`~pymongo.client_session.ClientSession` .. versionchanged:: 3.6 Added ``session`` parameter. """ gout = GridOut(self.__collection, file_id, session=session) # Raise NoFile now, instead of on first attribute access. gout._ensure_file() return gout def get_version(self, filename=None, version=-1, session=None, **kwargs): """Get a file from GridFS by ``"filename"`` or metadata fields. Returns a version of the file in GridFS whose filename matches `filename` and whose metadata fields match the supplied keyword arguments, as an instance of :class:`~gridfs.grid_file.GridOut`. Version numbering is a convenience atop the GridFS API provided by MongoDB. If more than one file matches the query (either by `filename` alone, by metadata fields, or by a combination of both), then version ``-1`` will be the most recently uploaded matching file, ``-2`` the second most recently uploaded, etc. Version ``0`` will be the first version uploaded, ``1`` the second version, etc. So if three versions have been uploaded, then version ``0`` is the same as version ``-3``, version ``1`` is the same as version ``-2``, and version ``2`` is the same as version ``-1``. Raises :class:`~gridfs.errors.NoFile` if no such version of that file exists. :Parameters: - `filename`: ``"filename"`` of the file to get, or `None` - `version` (optional): version of the file to get (defaults to -1, the most recent version uploaded) - `session` (optional): a :class:`~pymongo.client_session.ClientSession` - `**kwargs` (optional): find files by custom metadata. .. versionchanged:: 3.6 Added ``session`` parameter. .. versionchanged:: 3.1 ``get_version`` no longer ensures indexes. """ query = kwargs if filename is not None: query["filename"] = filename cursor = self.__files.find(query, session=session) if version < 0: skip = abs(version) - 1 cursor.limit(-1).skip(skip).sort("uploadDate", DESCENDING) else: cursor.limit(-1).skip(version).sort("uploadDate", ASCENDING) try: doc = next(cursor) return GridOut( self.__collection, file_document=doc, session=session) except StopIteration: raise NoFile("no version %d for filename %r" % (version, filename)) def get_last_version(self, filename=None, session=None, **kwargs): """Get the most recent version of a file in GridFS by ``"filename"`` or metadata fields. Equivalent to calling :meth:`get_version` with the default `version` (``-1``). :Parameters: - `filename`: ``"filename"`` of the file to get, or `None` - `session` (optional): a :class:`~pymongo.client_session.ClientSession` - `**kwargs` (optional): find files by custom metadata. .. versionchanged:: 3.6 Added ``session`` parameter. """ return self.get_version(filename=filename, session=session, **kwargs) # TODO add optional safe mode for chunk removal? def delete(self, file_id, session=None): """Delete a file from GridFS by ``"_id"``. Deletes all data belonging to the file with ``"_id"``: `file_id`. .. warning:: Any processes/threads reading from the file while this method is executing will likely see an invalid/corrupt file. Care should be taken to avoid concurrent reads to a file while it is being deleted. .. note:: Deletes of non-existent files are considered successful since the end result is the same: no file with that _id remains. :Parameters: - `file_id`: ``"_id"`` of the file to delete - `session` (optional): a :class:`~pymongo.client_session.ClientSession` .. versionchanged:: 3.6 Added ``session`` parameter. .. versionchanged:: 3.1 ``delete`` no longer ensures indexes. """ self.__files.delete_one({"_id": file_id}, session=session) self.__chunks.delete_many({"files_id": file_id}, session=session) def list(self, session=None): """List the names of all files stored in this instance of :class:`GridFS`. :Parameters: - `session` (optional): a :class:`~pymongo.client_session.ClientSession` .. versionchanged:: 3.6 Added ``session`` parameter. .. versionchanged:: 3.1 ``list`` no longer ensures indexes. """ # With an index, distinct includes documents with no filename # as None. return [ name for name in self.__files.distinct("filename", session=session) if name is not None] def find_one(self, filter=None, session=None, *args, **kwargs): """Get a single file from gridfs. All arguments to :meth:`find` are also valid arguments for :meth:`find_one`, although any `limit` argument will be ignored. Returns a single :class:`~gridfs.grid_file.GridOut`, or ``None`` if no matching file is found. For example:: file = fs.find_one({"filename": "lisa.txt"}) :Parameters: - `filter` (optional): a dictionary specifying the query to be performing OR any other type to be used as the value for a query for ``"_id"`` in the file collection. - `*args` (optional): any additional positional arguments are the same as the arguments to :meth:`find`. - `session` (optional): a :class:`~pymongo.client_session.ClientSession` - `**kwargs` (optional): any additional keyword arguments are the same as the arguments to :meth:`find`. .. versionchanged:: 3.6 Added ``session`` parameter. """ if filter is not None and not isinstance(filter, abc.Mapping): filter = {"_id": filter} for f in self.find(filter, *args, session=session, **kwargs): return f return None def find(self, *args, **kwargs): """Query GridFS for files. Returns a cursor that iterates across files matching arbitrary queries on the files collection. Can be combined with other modifiers for additional control. For example:: for grid_out in fs.find({"filename": "lisa.txt"}, no_cursor_timeout=True): data = grid_out.read() would iterate through all versions of "lisa.txt" stored in GridFS. Note that setting no_cursor_timeout to True may be important to prevent the cursor from timing out during long multi-file processing work. As another example, the call:: most_recent_three = fs.find().sort("uploadDate", -1).limit(3) would return a cursor to the three most recently uploaded files in GridFS. Follows a similar interface to :meth:`~pymongo.collection.Collection.find` in :class:`~pymongo.collection.Collection`. If a :class:`~pymongo.client_session.ClientSession` is passed to :meth:`find`, all returned :class:`~gridfs.grid_file.GridOut` instances are associated with that session. :Parameters: - `filter` (optional): a SON object specifying elements which must be present for a document to be included in the result set - `skip` (optional): the number of files to omit (from the start of the result set) when returning the results - `limit` (optional): the maximum number of results to return - `no_cursor_timeout` (optional): if False (the default), any returned cursor is closed by the server after 10 minutes of inactivity. If set to True, the returned cursor will never time out on the server. Care should be taken to ensure that cursors with no_cursor_timeout turned on are properly closed. - `sort` (optional): a list of (key, direction) pairs specifying the sort order for this query. See :meth:`~pymongo.cursor.Cursor.sort` for details. Raises :class:`TypeError` if any of the arguments are of improper type. Returns an instance of :class:`~gridfs.grid_file.GridOutCursor` corresponding to this query. .. versionchanged:: 3.0 Removed the read_preference, tag_sets, and secondary_acceptable_latency_ms options. .. versionadded:: 2.7 .. mongodoc:: find """ return GridOutCursor(self.__collection, *args, **kwargs) def exists(self, document_or_id=None, session=None, **kwargs): """Check if a file exists in this instance of :class:`GridFS`. The file to check for can be specified by the value of its ``_id`` key, or by passing in a query document. A query document can be passed in as dictionary, or by using keyword arguments. Thus, the following three calls are equivalent: >>> fs.exists(file_id) >>> fs.exists({"_id": file_id}) >>> fs.exists(_id=file_id) As are the following two calls: >>> fs.exists({"filename": "mike.txt"}) >>> fs.exists(filename="mike.txt") And the following two: >>> fs.exists({"foo": {"$gt": 12}}) >>> fs.exists(foo={"$gt": 12}) Returns ``True`` if a matching file exists, ``False`` otherwise. Calls to :meth:`exists` will not automatically create appropriate indexes; application developers should be sure to create indexes if needed and as appropriate. :Parameters: - `document_or_id` (optional): query document, or _id of the document to check for - `session` (optional): a :class:`~pymongo.client_session.ClientSession` - `**kwargs` (optional): keyword arguments are used as a query document, if they're present. .. versionchanged:: 3.6 Added ``session`` parameter. """ if kwargs: f = self.__files.find_one(kwargs, ["_id"], session=session) else: f = self.__files.find_one(document_or_id, ["_id"], session=session) return f is not None class GridFSBucket(object): """An instance of GridFS on top of a single Database.""" def __init__(self, db, bucket_name="fs", chunk_size_bytes=DEFAULT_CHUNK_SIZE, write_concern=None, read_preference=None, disable_md5=False): """Create a new instance of :class:`GridFSBucket`. Raises :exc:`TypeError` if `database` is not an instance of :class:`~pymongo.database.Database`. Raises :exc:`~pymongo.errors.ConfigurationError` if `write_concern` is not acknowledged. :Parameters: - `database`: database to use. - `bucket_name` (optional): The name of the bucket. Defaults to 'fs'. - `chunk_size_bytes` (optional): The chunk size in bytes. Defaults to 255KB. - `write_concern` (optional): The :class:`~pymongo.write_concern.WriteConcern` to use. If ``None`` (the default) db.write_concern is used. - `read_preference` (optional): The read preference to use. If ``None`` (the default) db.read_preference is used. - `disable_md5` (optional): When True, MD5 checksums will not be computed for uploaded files. Useful in environments where MD5 cannot be used for regulatory or other reasons. Defaults to False. .. versionadded:: 3.1 .. mongodoc:: gridfs """ if not isinstance(db, Database): raise TypeError("database must be an instance of Database") db = _clear_entity_type_registry(db) wtc = write_concern if write_concern is not None else db.write_concern if not wtc.acknowledged: raise ConfigurationError('write concern must be acknowledged') self._db = db self._bucket_name = bucket_name self._collection = db[bucket_name] self._disable_md5 = disable_md5 self._chunks = self._collection.chunks.with_options( write_concern=write_concern, read_preference=read_preference) self._files = self._collection.files.with_options( write_concern=write_concern, read_preference=read_preference) self._chunk_size_bytes = chunk_size_bytes def open_upload_stream(self, filename, chunk_size_bytes=None, metadata=None, session=None): """Opens a Stream that the application can write the contents of the file to. The user must specify the filename, and can choose to add any additional information in the metadata field of the file document or modify the chunk size. For example:: my_db = MongoClient().test fs = GridFSBucket(my_db) grid_in = fs.open_upload_stream( "test_file", chunk_size_bytes=4, metadata={"contentType": "text/plain"}) grid_in.write("data I want to store!") grid_in.close() # uploaded on close Returns an instance of :class:`~gridfs.grid_file.GridIn`. Raises :exc:`~gridfs.errors.NoFile` if no such version of that file exists. Raises :exc:`~ValueError` if `filename` is not a string. :Parameters: - `filename`: The name of the file to upload. - `chunk_size_bytes` (options): The number of bytes per chunk of this file. Defaults to the chunk_size_bytes in :class:`GridFSBucket`. - `metadata` (optional): User data for the 'metadata' field of the files collection document. If not provided the metadata field will be omitted from the files collection document. - `session` (optional): a :class:`~pymongo.client_session.ClientSession` .. versionchanged:: 3.6 Added ``session`` parameter. """ validate_string("filename", filename) opts = {"filename": filename, "chunk_size": (chunk_size_bytes if chunk_size_bytes is not None else self._chunk_size_bytes)} if metadata is not None: opts["metadata"] = metadata return GridIn( self._collection, session=session, disable_md5=self._disable_md5, **opts) def open_upload_stream_with_id( self, file_id, filename, chunk_size_bytes=None, metadata=None, session=None): """Opens a Stream that the application can write the contents of the file to. The user must specify the file id and filename, and can choose to add any additional information in the metadata field of the file document or modify the chunk size. For example:: my_db = MongoClient().test fs = GridFSBucket(my_db) grid_in = fs.open_upload_stream_with_id( ObjectId(), "test_file", chunk_size_bytes=4, metadata={"contentType": "text/plain"}) grid_in.write("data I want to store!") grid_in.close() # uploaded on close Returns an instance of :class:`~gridfs.grid_file.GridIn`. Raises :exc:`~gridfs.errors.NoFile` if no such version of that file exists. Raises :exc:`~ValueError` if `filename` is not a string. :Parameters: - `file_id`: The id to use for this file. The id must not have already been used for another file. - `filename`: The name of the file to upload. - `chunk_size_bytes` (options): The number of bytes per chunk of this file. Defaults to the chunk_size_bytes in :class:`GridFSBucket`. - `metadata` (optional): User data for the 'metadata' field of the files collection document. If not provided the metadata field will be omitted from the files collection document. - `session` (optional): a :class:`~pymongo.client_session.ClientSession` .. versionchanged:: 3.6 Added ``session`` parameter. """ validate_string("filename", filename) opts = {"_id": file_id, "filename": filename, "chunk_size": (chunk_size_bytes if chunk_size_bytes is not None else self._chunk_size_bytes)} if metadata is not None: opts["metadata"] = metadata return GridIn( self._collection, session=session, disable_md5=self._disable_md5, **opts) def upload_from_stream(self, filename, source, chunk_size_bytes=None, metadata=None, session=None): """Uploads a user file to a GridFS bucket. Reads the contents of the user file from `source` and uploads it to the file `filename`. Source can be a string or file-like object. For example:: my_db = MongoClient().test fs = GridFSBucket(my_db) file_id = fs.upload_from_stream( "test_file", "data I want to store!", chunk_size_bytes=4, metadata={"contentType": "text/plain"}) Returns the _id of the uploaded file. Raises :exc:`~gridfs.errors.NoFile` if no such version of that file exists. Raises :exc:`~ValueError` if `filename` is not a string. :Parameters: - `filename`: The name of the file to upload. - `source`: The source stream of the content to be uploaded. Must be a file-like object that implements :meth:`read` or a string. - `chunk_size_bytes` (options): The number of bytes per chunk of this file. Defaults to the chunk_size_bytes of :class:`GridFSBucket`. - `metadata` (optional): User data for the 'metadata' field of the files collection document. If not provided the metadata field will be omitted from the files collection document. - `session` (optional): a :class:`~pymongo.client_session.ClientSession` .. versionchanged:: 3.6 Added ``session`` parameter. """ with self.open_upload_stream( filename, chunk_size_bytes, metadata, session=session) as gin: gin.write(source) return gin._id def upload_from_stream_with_id(self, file_id, filename, source, chunk_size_bytes=None, metadata=None, session=None): """Uploads a user file to a GridFS bucket with a custom file id. Reads the contents of the user file from `source` and uploads it to the file `filename`. Source can be a string or file-like object. For example:: my_db = MongoClient().test fs = GridFSBucket(my_db) file_id = fs.upload_from_stream( ObjectId(), "test_file", "data I want to store!", chunk_size_bytes=4, metadata={"contentType": "text/plain"}) Raises :exc:`~gridfs.errors.NoFile` if no such version of that file exists. Raises :exc:`~ValueError` if `filename` is not a string. :Parameters: - `file_id`: The id to use for this file. The id must not have already been used for another file. - `filename`: The name of the file to upload. - `source`: The source stream of the content to be uploaded. Must be a file-like object that implements :meth:`read` or a string. - `chunk_size_bytes` (options): The number of bytes per chunk of this file. Defaults to the chunk_size_bytes of :class:`GridFSBucket`. - `metadata` (optional): User data for the 'metadata' field of the files collection document. If not provided the metadata field will be omitted from the files collection document. - `session` (optional): a :class:`~pymongo.client_session.ClientSession` .. versionchanged:: 3.6 Added ``session`` parameter. """ with self.open_upload_stream_with_id( file_id, filename, chunk_size_bytes, metadata, session=session) as gin: gin.write(source) def open_download_stream(self, file_id, session=None): """Opens a Stream from which the application can read the contents of the stored file specified by file_id. For example:: my_db = MongoClient().test fs = GridFSBucket(my_db) # get _id of file to read. file_id = fs.upload_from_stream("test_file", "data I want to store!") grid_out = fs.open_download_stream(file_id) contents = grid_out.read() Returns an instance of :class:`~gridfs.grid_file.GridOut`. Raises :exc:`~gridfs.errors.NoFile` if no file with file_id exists. :Parameters: - `file_id`: The _id of the file to be downloaded. - `session` (optional): a :class:`~pymongo.client_session.ClientSession` .. versionchanged:: 3.6 Added ``session`` parameter. """ gout = GridOut(self._collection, file_id, session=session) # Raise NoFile now, instead of on first attribute access. gout._ensure_file() return gout def download_to_stream(self, file_id, destination, session=None): """Downloads the contents of the stored file specified by file_id and writes the contents to `destination`. For example:: my_db = MongoClient().test fs = GridFSBucket(my_db) # Get _id of file to read file_id = fs.upload_from_stream("test_file", "data I want to store!") # Get file to write to file = open('myfile','wb+') fs.download_to_stream(file_id, file) file.seek(0) contents = file.read() Raises :exc:`~gridfs.errors.NoFile` if no file with file_id exists. :Parameters: - `file_id`: The _id of the file to be downloaded. - `destination`: a file-like object implementing :meth:`write`. - `session` (optional): a :class:`~pymongo.client_session.ClientSession` .. versionchanged:: 3.6 Added ``session`` parameter. """ with self.open_download_stream(file_id, session=session) as gout: for chunk in gout: destination.write(chunk) def delete(self, file_id, session=None): """Given an file_id, delete this stored file's files collection document and associated chunks from a GridFS bucket. For example:: my_db = MongoClient().test fs = GridFSBucket(my_db) # Get _id of file to delete file_id = fs.upload_from_stream("test_file", "data I want to store!") fs.delete(file_id) Raises :exc:`~gridfs.errors.NoFile` if no file with file_id exists. :Parameters: - `file_id`: The _id of the file to be deleted. - `session` (optional): a :class:`~pymongo.client_session.ClientSession` .. versionchanged:: 3.6 Added ``session`` parameter. """ res = self._files.delete_one({"_id": file_id}, session=session) self._chunks.delete_many({"files_id": file_id}, session=session) if not res.deleted_count: raise NoFile( "no file could be deleted because none matched %s" % file_id) def find(self, *args, **kwargs): """Find and return the files collection documents that match ``filter`` Returns a cursor that iterates across files matching arbitrary queries on the files collection. Can be combined with other modifiers for additional control. For example:: for grid_data in fs.find({"filename": "lisa.txt"}, no_cursor_timeout=True): data = grid_data.read() would iterate through all versions of "lisa.txt" stored in GridFS. Note that setting no_cursor_timeout to True may be important to prevent the cursor from timing out during long multi-file processing work. As another example, the call:: most_recent_three = fs.find().sort("uploadDate", -1).limit(3) would return a cursor to the three most recently uploaded files in GridFS. Follows a similar interface to :meth:`~pymongo.collection.Collection.find` in :class:`~pymongo.collection.Collection`. If a :class:`~pymongo.client_session.ClientSession` is passed to :meth:`find`, all returned :class:`~gridfs.grid_file.GridOut` instances are associated with that session. :Parameters: - `filter`: Search query. - `batch_size` (optional): The number of documents to return per batch. - `limit` (optional): The maximum number of documents to return. - `no_cursor_timeout` (optional): The server normally times out idle cursors after an inactivity period (10 minutes) to prevent excess memory use. Set this option to True prevent that. - `skip` (optional): The number of documents to skip before returning. - `sort` (optional): The order by which to sort results. Defaults to None. """ return GridOutCursor(self._collection, *args, **kwargs) def open_download_stream_by_name(self, filename, revision=-1, session=None): """Opens a Stream from which the application can read the contents of `filename` and optional `revision`. For example:: my_db = MongoClient().test fs = GridFSBucket(my_db) grid_out = fs.open_download_stream_by_name("test_file") contents = grid_out.read() Returns an instance of :class:`~gridfs.grid_file.GridOut`. Raises :exc:`~gridfs.errors.NoFile` if no such version of that file exists. Raises :exc:`~ValueError` filename is not a string. :Parameters: - `filename`: The name of the file to read from. - `revision` (optional): Which revision (documents with the same filename and different uploadDate) of the file to retrieve. Defaults to -1 (the most recent revision). - `session` (optional): a :class:`~pymongo.client_session.ClientSession` :Note: Revision numbers are defined as follows: - 0 = the original stored file - 1 = the first revision - 2 = the second revision - etc... - -2 = the second most recent revision - -1 = the most recent revision .. versionchanged:: 3.6 Added ``session`` parameter. """ validate_string("filename", filename) query = {"filename": filename} cursor = self._files.find(query, session=session) if revision < 0: skip = abs(revision) - 1 cursor.limit(-1).skip(skip).sort("uploadDate", DESCENDING) else: cursor.limit(-1).skip(revision).sort("uploadDate", ASCENDING) try: grid_file = next(cursor) return GridOut( self._collection, file_document=grid_file, session=session) except StopIteration: raise NoFile( "no version %d for filename %r" % (revision, filename)) def download_to_stream_by_name(self, filename, destination, revision=-1, session=None): """Write the contents of `filename` (with optional `revision`) to `destination`. For example:: my_db = MongoClient().test fs = GridFSBucket(my_db) # Get file to write to file = open('myfile','wb') fs.download_to_stream_by_name("test_file", file) Raises :exc:`~gridfs.errors.NoFile` if no such version of that file exists. Raises :exc:`~ValueError` if `filename` is not a string. :Parameters: - `filename`: The name of the file to read from. - `destination`: A file-like object that implements :meth:`write`. - `revision` (optional): Which revision (documents with the same filename and different uploadDate) of the file to retrieve. Defaults to -1 (the most recent revision). - `session` (optional): a :class:`~pymongo.client_session.ClientSession` :Note: Revision numbers are defined as follows: - 0 = the original stored file - 1 = the first revision - 2 = the second revision - etc... - -2 = the second most recent revision - -1 = the most recent revision .. versionchanged:: 3.6 Added ``session`` parameter. """ with self.open_download_stream_by_name( filename, revision, session=session) as gout: for chunk in gout: destination.write(chunk) def rename(self, file_id, new_filename, session=None): """Renames the stored file with the specified file_id. For example:: my_db = MongoClient().test fs = GridFSBucket(my_db) # Get _id of file to rename file_id = fs.upload_from_stream("test_file", "data I want to store!") fs.rename(file_id, "new_test_name") Raises :exc:`~gridfs.errors.NoFile` if no file with file_id exists. :Parameters: - `file_id`: The _id of the file to be renamed. - `new_filename`: The new name of the file. - `session` (optional): a :class:`~pymongo.client_session.ClientSession` .. versionchanged:: 3.6 Added ``session`` parameter. """ result = self._files.update_one({"_id": file_id}, {"$set": {"filename": new_filename}}, session=session) if not result.matched_count: raise NoFile("no files could be renamed %r because none " "matched file_id %i" % (new_filename, file_id)) ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/gridfs/errors.py ================================================ # Copyright 2009-2015 MongoDB, Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Exceptions raised by the :mod:`gridfs` package""" from pymongo.errors import PyMongoError class GridFSError(PyMongoError): """Base class for all GridFS exceptions.""" class CorruptGridFile(GridFSError): """Raised when a file in :class:`~gridfs.GridFS` is malformed.""" class NoFile(GridFSError): """Raised when trying to read from a non-existent file.""" class FileExists(GridFSError): """Raised when trying to create a file that already exists.""" ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/gridfs/grid_file.py ================================================ # Copyright 2009-present MongoDB, Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Tools for representing files stored in GridFS.""" import datetime import hashlib import io import math import os from bson.int64 import Int64 from bson.son import SON from bson.binary import Binary from bson.objectid import ObjectId from bson.py3compat import text_type, StringIO from gridfs.errors import CorruptGridFile, FileExists, NoFile from pymongo import ASCENDING from pymongo.collection import Collection from pymongo.cursor import Cursor from pymongo.errors import (ConfigurationError, CursorNotFound, DuplicateKeyError, OperationFailure) from pymongo.read_preferences import ReadPreference try: _SEEK_SET = os.SEEK_SET _SEEK_CUR = os.SEEK_CUR _SEEK_END = os.SEEK_END # before 2.5 except AttributeError: _SEEK_SET = 0 _SEEK_CUR = 1 _SEEK_END = 2 EMPTY = b"" NEWLN = b"\n" """Default chunk size, in bytes.""" # Slightly under a power of 2, to work well with server's record allocations. DEFAULT_CHUNK_SIZE = 255 * 1024 _C_INDEX = SON([("files_id", ASCENDING), ("n", ASCENDING)]) _F_INDEX = SON([("filename", ASCENDING), ("uploadDate", ASCENDING)]) def _grid_in_property(field_name, docstring, read_only=False, closed_only=False): """Create a GridIn property.""" def getter(self): if closed_only and not self._closed: raise AttributeError("can only get %r on a closed file" % field_name) # Protect against PHP-237 if field_name == 'length': return self._file.get(field_name, 0) return self._file.get(field_name, None) def setter(self, value): if self._closed: self._coll.files.update_one({"_id": self._file["_id"]}, {"$set": {field_name: value}}) self._file[field_name] = value if read_only: docstring += "\n\nThis attribute is read-only." elif closed_only: docstring = "%s\n\n%s" % (docstring, "This attribute is read-only and " "can only be read after :meth:`close` " "has been called.") if not read_only and not closed_only: return property(getter, setter, doc=docstring) return property(getter, doc=docstring) def _grid_out_property(field_name, docstring): """Create a GridOut property.""" def getter(self): self._ensure_file() # Protect against PHP-237 if field_name == 'length': return self._file.get(field_name, 0) return self._file.get(field_name, None) docstring += "\n\nThis attribute is read-only." return property(getter, doc=docstring) def _clear_entity_type_registry(entity, **kwargs): """Clear the given database/collection object's type registry.""" codecopts = entity.codec_options.with_options(type_registry=None) return entity.with_options(codec_options=codecopts, **kwargs) class GridIn(object): """Class to write data to GridFS. """ def __init__( self, root_collection, session=None, disable_md5=False, **kwargs): """Write a file to GridFS Application developers should generally not need to instantiate this class directly - instead see the methods provided by :class:`~gridfs.GridFS`. Raises :class:`TypeError` if `root_collection` is not an instance of :class:`~pymongo.collection.Collection`. Any of the file level options specified in the `GridFS Spec `_ may be passed as keyword arguments. Any additional keyword arguments will be set as additional fields on the file document. Valid keyword arguments include: - ``"_id"``: unique ID for this file (default: :class:`~bson.objectid.ObjectId`) - this ``"_id"`` must not have already been used for another file - ``"filename"``: human name for the file - ``"contentType"`` or ``"content_type"``: valid mime-type for the file - ``"chunkSize"`` or ``"chunk_size"``: size of each of the chunks, in bytes (default: 255 kb) - ``"encoding"``: encoding used for this file. In Python 2, any :class:`unicode` that is written to the file will be converted to a :class:`str`. In Python 3, any :class:`str` that is written to the file will be converted to :class:`bytes`. :Parameters: - `root_collection`: root collection to write to - `session` (optional): a :class:`~pymongo.client_session.ClientSession` to use for all commands - `disable_md5` (optional): When True, an MD5 checksum will not be computed for the uploaded file. Useful in environments where MD5 cannot be used for regulatory or other reasons. Defaults to False. - `**kwargs` (optional): file level options (see above) .. versionchanged:: 3.6 Added ``session`` parameter. .. versionchanged:: 3.0 `root_collection` must use an acknowledged :attr:`~pymongo.collection.Collection.write_concern` """ if not isinstance(root_collection, Collection): raise TypeError("root_collection must be an " "instance of Collection") if not root_collection.write_concern.acknowledged: raise ConfigurationError('root_collection must use ' 'acknowledged write_concern') # Handle alternative naming if "content_type" in kwargs: kwargs["contentType"] = kwargs.pop("content_type") if "chunk_size" in kwargs: kwargs["chunkSize"] = kwargs.pop("chunk_size") coll = _clear_entity_type_registry( root_collection, read_preference=ReadPreference.PRIMARY) if not disable_md5: kwargs["md5"] = hashlib.md5() # Defaults kwargs["_id"] = kwargs.get("_id", ObjectId()) kwargs["chunkSize"] = kwargs.get("chunkSize", DEFAULT_CHUNK_SIZE) object.__setattr__(self, "_session", session) object.__setattr__(self, "_coll", coll) object.__setattr__(self, "_chunks", coll.chunks) object.__setattr__(self, "_file", kwargs) object.__setattr__(self, "_buffer", StringIO()) object.__setattr__(self, "_position", 0) object.__setattr__(self, "_chunk_number", 0) object.__setattr__(self, "_closed", False) object.__setattr__(self, "_ensured_index", False) def __create_index(self, collection, index_key, unique): doc = collection.find_one(projection={"_id": 1}, session=self._session) if doc is None: try: index_keys = [index_spec['key'] for index_spec in collection.list_indexes(session=self._session)] except OperationFailure: index_keys = [] if index_key not in index_keys: collection.create_index( index_key.items(), unique=unique, session=self._session) def __ensure_indexes(self): if not object.__getattribute__(self, "_ensured_index"): self.__create_index(self._coll.files, _F_INDEX, False) self.__create_index(self._coll.chunks, _C_INDEX, True) object.__setattr__(self, "_ensured_index", True) def abort(self): """Remove all chunks/files that may have been uploaded and close. """ self._coll.chunks.delete_many( {"files_id": self._file['_id']}, session=self._session) self._coll.files.delete_one( {"_id": self._file['_id']}, session=self._session) object.__setattr__(self, "_closed", True) @property def closed(self): """Is this file closed? """ return self._closed _id = _grid_in_property("_id", "The ``'_id'`` value for this file.", read_only=True) filename = _grid_in_property("filename", "Name of this file.") name = _grid_in_property("filename", "Alias for `filename`.") content_type = _grid_in_property("contentType", "Mime-type for this file.") length = _grid_in_property("length", "Length (in bytes) of this file.", closed_only=True) chunk_size = _grid_in_property("chunkSize", "Chunk size for this file.", read_only=True) upload_date = _grid_in_property("uploadDate", "Date that this file was uploaded.", closed_only=True) md5 = _grid_in_property("md5", "MD5 of the contents of this file " "if an md5 sum was created.", closed_only=True) def __getattr__(self, name): if name in self._file: return self._file[name] raise AttributeError("GridIn object has no attribute '%s'" % name) def __setattr__(self, name, value): # For properties of this instance like _buffer, or descriptors set on # the class like filename, use regular __setattr__ if name in self.__dict__ or name in self.__class__.__dict__: object.__setattr__(self, name, value) else: # All other attributes are part of the document in db.fs.files. # Store them to be sent to server on close() or if closed, send # them now. self._file[name] = value if self._closed: self._coll.files.update_one({"_id": self._file["_id"]}, {"$set": {name: value}}) def __flush_data(self, data): """Flush `data` to a chunk. """ self.__ensure_indexes() if 'md5' in self._file: self._file['md5'].update(data) if not data: return assert(len(data) <= self.chunk_size) chunk = {"files_id": self._file["_id"], "n": self._chunk_number, "data": Binary(data)} try: self._chunks.insert_one(chunk, session=self._session) except DuplicateKeyError: self._raise_file_exists(self._file['_id']) self._chunk_number += 1 self._position += len(data) def __flush_buffer(self): """Flush the buffer contents out to a chunk. """ self.__flush_data(self._buffer.getvalue()) self._buffer.close() self._buffer = StringIO() def __flush(self): """Flush the file to the database. """ try: self.__flush_buffer() if "md5" in self._file: self._file["md5"] = self._file["md5"].hexdigest() # The GridFS spec says length SHOULD be an Int64. self._file["length"] = Int64(self._position) self._file["uploadDate"] = datetime.datetime.utcnow() return self._coll.files.insert_one( self._file, session=self._session) except DuplicateKeyError: self._raise_file_exists(self._id) def _raise_file_exists(self, file_id): """Raise a FileExists exception for the given file_id.""" raise FileExists("file with _id %r already exists" % file_id) def close(self): """Flush the file and close it. A closed file cannot be written any more. Calling :meth:`close` more than once is allowed. """ if not self._closed: self.__flush() object.__setattr__(self, "_closed", True) def read(self, size=-1): raise io.UnsupportedOperation('read') def readable(self): return False def seekable(self): return False def write(self, data): """Write data to the file. There is no return value. `data` can be either a string of bytes or a file-like object (implementing :meth:`read`). If the file has an :attr:`encoding` attribute, `data` can also be a :class:`unicode` (:class:`str` in python 3) instance, which will be encoded as :attr:`encoding` before being written. Due to buffering, the data may not actually be written to the database until the :meth:`close` method is called. Raises :class:`ValueError` if this file is already closed. Raises :class:`TypeError` if `data` is not an instance of :class:`str` (:class:`bytes` in python 3), a file-like object, or an instance of :class:`unicode` (:class:`str` in python 3). Unicode data is only allowed if the file has an :attr:`encoding` attribute. :Parameters: - `data`: string of bytes or file-like object to be written to the file """ if self._closed: raise ValueError("cannot write to a closed file") try: # file-like read = data.read except AttributeError: # string if not isinstance(data, (text_type, bytes)): raise TypeError("can only write strings or file-like objects") if isinstance(data, text_type): try: data = data.encode(self.encoding) except AttributeError: raise TypeError("must specify an encoding for file in " "order to write %s" % (text_type.__name__,)) read = StringIO(data).read if self._buffer.tell() > 0: # Make sure to flush only when _buffer is complete space = self.chunk_size - self._buffer.tell() if space: try: to_write = read(space) except: self.abort() raise self._buffer.write(to_write) if len(to_write) < space: return # EOF or incomplete self.__flush_buffer() to_write = read(self.chunk_size) while to_write and len(to_write) == self.chunk_size: self.__flush_data(to_write) to_write = read(self.chunk_size) self._buffer.write(to_write) def writelines(self, sequence): """Write a sequence of strings to the file. Does not add seperators. """ for line in sequence: self.write(line) def writeable(self): return True def __enter__(self): """Support for the context manager protocol. """ return self def __exit__(self, exc_type, exc_val, exc_tb): """Support for the context manager protocol. Close the file and allow exceptions to propagate. """ self.close() # propagate exceptions return False class GridOut(object): """Class to read data out of GridFS. """ def __init__(self, root_collection, file_id=None, file_document=None, session=None): """Read a file from GridFS Application developers should generally not need to instantiate this class directly - instead see the methods provided by :class:`~gridfs.GridFS`. Either `file_id` or `file_document` must be specified, `file_document` will be given priority if present. Raises :class:`TypeError` if `root_collection` is not an instance of :class:`~pymongo.collection.Collection`. :Parameters: - `root_collection`: root collection to read from - `file_id` (optional): value of ``"_id"`` for the file to read - `file_document` (optional): file document from `root_collection.files` - `session` (optional): a :class:`~pymongo.client_session.ClientSession` to use for all commands .. versionchanged:: 3.8 For better performance and to better follow the GridFS spec, :class:`GridOut` now uses a single cursor to read all the chunks in the file. .. versionchanged:: 3.6 Added ``session`` parameter. .. versionchanged:: 3.0 Creating a GridOut does not immediately retrieve the file metadata from the server. Metadata is fetched when first needed. """ if not isinstance(root_collection, Collection): raise TypeError("root_collection must be an " "instance of Collection") root_collection = _clear_entity_type_registry(root_collection) self.__chunks = root_collection.chunks self.__files = root_collection.files self.__file_id = file_id self.__buffer = EMPTY self.__chunk_iter = None self.__position = 0 self._file = file_document self._session = session _id = _grid_out_property("_id", "The ``'_id'`` value for this file.") filename = _grid_out_property("filename", "Name of this file.") name = _grid_out_property("filename", "Alias for `filename`.") content_type = _grid_out_property("contentType", "Mime-type for this file.") length = _grid_out_property("length", "Length (in bytes) of this file.") chunk_size = _grid_out_property("chunkSize", "Chunk size for this file.") upload_date = _grid_out_property("uploadDate", "Date that this file was first uploaded.") aliases = _grid_out_property("aliases", "List of aliases for this file.") metadata = _grid_out_property("metadata", "Metadata attached to this file.") md5 = _grid_out_property("md5", "MD5 of the contents of this file " "if an md5 sum was created.") def _ensure_file(self): if not self._file: self._file = self.__files.find_one({"_id": self.__file_id}, session=self._session) if not self._file: raise NoFile("no file in gridfs collection %r with _id %r" % (self.__files, self.__file_id)) def __getattr__(self, name): self._ensure_file() if name in self._file: return self._file[name] raise AttributeError("GridOut object has no attribute '%s'" % name) def readable(self): return True def readchunk(self): """Reads a chunk at a time. If the current position is within a chunk the remainder of the chunk is returned. """ received = len(self.__buffer) chunk_data = EMPTY chunk_size = int(self.chunk_size) if received > 0: chunk_data = self.__buffer elif self.__position < int(self.length): chunk_number = int((received + self.__position) / chunk_size) if self.__chunk_iter is None: self.__chunk_iter = _GridOutChunkIterator( self, self.__chunks, self._session, chunk_number) chunk = self.__chunk_iter.next() chunk_data = chunk["data"][self.__position % chunk_size:] if not chunk_data: raise CorruptGridFile("truncated chunk") self.__position += len(chunk_data) self.__buffer = EMPTY return chunk_data def read(self, size=-1): """Read at most `size` bytes from the file (less if there isn't enough data). The bytes are returned as an instance of :class:`str` (:class:`bytes` in python 3). If `size` is negative or omitted all data is read. :Parameters: - `size` (optional): the number of bytes to read .. versionchanged:: 3.8 This method now only checks for extra chunks after reading the entire file. Previously, this method would check for extra chunks on every call. """ self._ensure_file() remainder = int(self.length) - self.__position if size < 0 or size > remainder: size = remainder if size == 0: return EMPTY received = 0 data = StringIO() while received < size: chunk_data = self.readchunk() received += len(chunk_data) data.write(chunk_data) # Detect extra chunks after reading the entire file. if size == remainder and self.__chunk_iter: try: self.__chunk_iter.next() except StopIteration: pass self.__position -= received - size # Return 'size' bytes and store the rest. data.seek(size) self.__buffer = data.read() data.seek(0) return data.read(size) def readline(self, size=-1): """Read one line or up to `size` bytes from the file. :Parameters: - `size` (optional): the maximum number of bytes to read """ remainder = int(self.length) - self.__position if size < 0 or size > remainder: size = remainder if size == 0: return EMPTY received = 0 data = StringIO() while received < size: chunk_data = self.readchunk() pos = chunk_data.find(NEWLN, 0, size) if pos != -1: size = received + pos + 1 received += len(chunk_data) data.write(chunk_data) if pos != -1: break self.__position -= received - size # Return 'size' bytes and store the rest. data.seek(size) self.__buffer = data.read() data.seek(0) return data.read(size) def tell(self): """Return the current position of this file. """ return self.__position def seek(self, pos, whence=_SEEK_SET): """Set the current position of this file. :Parameters: - `pos`: the position (or offset if using relative positioning) to seek to - `whence` (optional): where to seek from. :attr:`os.SEEK_SET` (``0``) for absolute file positioning, :attr:`os.SEEK_CUR` (``1``) to seek relative to the current position, :attr:`os.SEEK_END` (``2``) to seek relative to the file's end. """ if whence == _SEEK_SET: new_pos = pos elif whence == _SEEK_CUR: new_pos = self.__position + pos elif whence == _SEEK_END: new_pos = int(self.length) + pos else: raise IOError(22, "Invalid value for `whence`") if new_pos < 0: raise IOError(22, "Invalid value for `pos` - must be positive") # Optimization, continue using the same buffer and chunk iterator. if new_pos == self.__position: return self.__position = new_pos self.__buffer = EMPTY if self.__chunk_iter: self.__chunk_iter.close() self.__chunk_iter = None def seekable(self): return True def __iter__(self): """Return an iterator over all of this file's data. The iterator will return chunk-sized instances of :class:`str` (:class:`bytes` in python 3). This can be useful when serving files using a webserver that handles such an iterator efficiently. .. note:: This is different from :py:class:`io.IOBase` which iterates over *lines* in the file. Use :meth:`GridOut.readline` to read line by line instead of chunk by chunk. .. versionchanged:: 3.8 The iterator now raises :class:`CorruptGridFile` when encountering any truncated, missing, or extra chunk in a file. The previous behavior was to only raise :class:`CorruptGridFile` on a missing chunk. """ return GridOutIterator(self, self.__chunks, self._session) def close(self): """Make GridOut more generically file-like.""" if self.__chunk_iter: self.__chunk_iter.close() self.__chunk_iter = None def write(self, value): raise io.UnsupportedOperation('write') def __enter__(self): """Makes it possible to use :class:`GridOut` files with the context manager protocol. """ return self def __exit__(self, exc_type, exc_val, exc_tb): """Makes it possible to use :class:`GridOut` files with the context manager protocol. """ self.close() return False class _GridOutChunkIterator(object): """Iterates over a file's chunks using a single cursor. Raises CorruptGridFile when encountering any truncated, missing, or extra chunk in a file. """ def __init__(self, grid_out, chunks, session, next_chunk): self._id = grid_out._id self._chunk_size = int(grid_out.chunk_size) self._length = int(grid_out.length) self._chunks = chunks self._session = session self._next_chunk = next_chunk self._num_chunks = math.ceil(float(self._length) / self._chunk_size) self._cursor = None def expected_chunk_length(self, chunk_n): if chunk_n < self._num_chunks - 1: return self._chunk_size return self._length - (self._chunk_size * (self._num_chunks - 1)) def __iter__(self): return self def _create_cursor(self): filter = {"files_id": self._id} if self._next_chunk > 0: filter["n"] = {"$gte": self._next_chunk} self._cursor = self._chunks.find(filter, sort=[("n", 1)], session=self._session) def _next_with_retry(self): """Return the next chunk and retry once on CursorNotFound. We retry on CursorNotFound to maintain backwards compatibility in cases where two calls to read occur more than 10 minutes apart (the server's default cursor timeout). """ if self._cursor is None: self._create_cursor() try: return self._cursor.next() except CursorNotFound: self._cursor.close() self._create_cursor() return self._cursor.next() def next(self): try: chunk = self._next_with_retry() except StopIteration: if self._next_chunk >= self._num_chunks: raise raise CorruptGridFile("no chunk #%d" % self._next_chunk) if chunk["n"] != self._next_chunk: self.close() raise CorruptGridFile( "Missing chunk: expected chunk #%d but found " "chunk with n=%d" % (self._next_chunk, chunk["n"])) if chunk["n"] >= self._num_chunks: # According to spec, ignore extra chunks if they are empty. if len(chunk["data"]): self.close() raise CorruptGridFile( "Extra chunk found: expected %d chunks but found " "chunk with n=%d" % (self._num_chunks, chunk["n"])) expected_length = self.expected_chunk_length(chunk["n"]) if len(chunk["data"]) != expected_length: self.close() raise CorruptGridFile( "truncated chunk #%d: expected chunk length to be %d but " "found chunk with length %d" % ( chunk["n"], expected_length, len(chunk["data"]))) self._next_chunk += 1 return chunk __next__ = next def close(self): if self._cursor: self._cursor.close() self._cursor = None class GridOutIterator(object): def __init__(self, grid_out, chunks, session): self.__chunk_iter = _GridOutChunkIterator(grid_out, chunks, session, 0) def __iter__(self): return self def next(self): chunk = self.__chunk_iter.next() return bytes(chunk["data"]) __next__ = next class GridOutCursor(Cursor): """A cursor / iterator for returning GridOut objects as the result of an arbitrary query against the GridFS files collection. """ def __init__(self, collection, filter=None, skip=0, limit=0, no_cursor_timeout=False, sort=None, batch_size=0, session=None): """Create a new cursor, similar to the normal :class:`~pymongo.cursor.Cursor`. Should not be called directly by application developers - see the :class:`~gridfs.GridFS` method :meth:`~gridfs.GridFS.find` instead. .. versionadded 2.7 .. mongodoc:: cursors """ collection = _clear_entity_type_registry(collection) # Hold on to the base "fs" collection to create GridOut objects later. self.__root_collection = collection super(GridOutCursor, self).__init__( collection.files, filter, skip=skip, limit=limit, no_cursor_timeout=no_cursor_timeout, sort=sort, batch_size=batch_size, session=session) def next(self): """Get next GridOut object from cursor. """ # Work around "super is not iterable" issue in Python 3.x next_file = super(GridOutCursor, self).next() return GridOut(self.__root_collection, file_document=next_file, session=self.session) __next__ = next def add_option(self, *args, **kwargs): raise NotImplementedError("Method does not exist for GridOutCursor") def remove_option(self, *args, **kwargs): raise NotImplementedError("Method does not exist for GridOutCursor") def _clone_base(self, session): """Creates an empty GridOutCursor for information to be copied into. """ return GridOutCursor(self.__root_collection, session=session) ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/hamcrest/__init__.py ================================================ from __future__ import absolute_import from hamcrest.core import * from hamcrest.library import * __version__ = "1.9.0" __author__ = "Chris Rose" __copyright__ = "Copyright 2015 hamcrest.org" __license__ = "BSD, see License.txt" ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/hamcrest/core/__init__.py ================================================ from __future__ import absolute_import from hamcrest.core.assert_that import assert_that from hamcrest.core.core import * __author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/hamcrest/core/assert_that.py ================================================ from __future__ import absolute_import from hamcrest.core.matcher import Matcher from hamcrest.core.string_description import StringDescription __author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" # unittest integration; hide these frames from tracebacks __unittest = True # py.test integration; hide these frames from tracebacks __tracebackhide__ = True def assert_that(arg1, arg2=None, arg3=''): """Asserts that actual value satisfies matcher. (Can also assert plain boolean condition.) :param actual: The object to evaluate as the actual value. :param matcher: The matcher to satisfy as the expected condition. :param reason: Optional explanation to include in failure description. ``assert_that`` passes the actual value to the matcher for evaluation. If the matcher is not satisfied, an exception is thrown describing the mismatch. ``assert_that`` is designed to integrate well with PyUnit and other unit testing frameworks. The exception raised for an unmet assertion is an :py:exc:`AssertionError`, which PyUnit reports as a test failure. With a different set of parameters, ``assert_that`` can also verify a boolean condition: .. function:: assert_that(assertion[, reason]) :param assertion: Boolean condition to verify. :param reason: Optional explanation to include in failure description. This is equivalent to the :py:meth:`~unittest.TestCase.assertTrue` method of :py:class:`unittest.TestCase`, but offers greater flexibility in test writing by being a standalone function. """ if isinstance(arg2, Matcher): _assert_match(actual=arg1, matcher=arg2, reason=arg3) else: _assert_bool(assertion=arg1, reason=arg2) def _assert_match(actual, matcher, reason): if not matcher.matches(actual): description = StringDescription() description.append_text(reason) \ .append_text('\nExpected: ') \ .append_description_of(matcher) \ .append_text('\n but: ') matcher.describe_mismatch(actual, description) description.append_text('\n') raise AssertionError(description) def _assert_bool(assertion, reason=None): if not assertion: if not reason: reason = 'Assertion failed' raise AssertionError(reason) ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/hamcrest/core/base_description.py ================================================ from __future__ import absolute_import __author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" import warnings import six from hamcrest.core.description import Description from hamcrest.core.selfdescribingvalue import SelfDescribingValue from hamcrest.core.helpers.hasmethod import hasmethod class BaseDescription(Description): """Base class for all :py:class:`~hamcrest.core.description.Description` implementations. """ def append_text(self, text): self.append(text) return self def append_description_of(self, value): if hasmethod(value, 'describe_to'): value.describe_to(self) elif six.PY3 and isinstance(value, six.text_type): self.append(repr(value)) elif six.PY2 and isinstance(value, six.binary_type): self.append_string_in_python_syntax(value) elif isinstance(value, six.text_type): self.append_string_in_python_syntax(value) else: description = str(value) if description[:1] == '<' and description[-1:] == '>': self.append(description) else: self.append('<') self.append(description) self.append('>') return self def append_value(self, value): warnings.warn('Call append_description_of instead of append_value', DeprecationWarning) if isinstance(value, str): self.append_string_in_python_syntax(value) else: self.append('<') self.append(str(value)) self.append('>') return self def append_value_list(self, start, separator, end, list): warnings.warn('Call append_list instead of append_value_list', DeprecationWarning) return self.append_list(start, separator, end, map(SelfDescribingValue, list)) def append_list(self, start, separator, end, list): separate = False self.append(start) for item in list: if separate: self.append(separator) self.append_description_of(item) separate = True self.append(end) return self def append(self, string): """Append the string to the description.""" raise NotImplementedError('append') def append_string_in_python_syntax(self, string): self.append("'") for ch in string: self.append(character_in_python_syntax(ch)) self.append("'") def character_in_python_syntax(ch): if ch == "'": return "\'" elif ch == '\n': return '\\n' elif ch == '\r': return '\\r' elif ch == '\t': return '\\t' else: return ch ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/hamcrest/core/base_matcher.py ================================================ from __future__ import absolute_import __author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" from hamcrest.core.matcher import Matcher from hamcrest.core.string_description import tostring class BaseMatcher(Matcher): """Base class for all :py:class:`~hamcrest.core.matcher.Matcher` implementations. Most implementations can just implement :py:obj:`_matches`, leaving the handling of any mismatch description to the ``matches`` method. But if it makes more sense to generate the mismatch description during the matching, override :py:meth:`~hamcrest.core.matcher.Matcher.matches` instead. """ def __str__(self): return tostring(self) def _matches(self, item): raise NotImplementedError('_matches') def matches(self, item, mismatch_description=None): match_result = self._matches(item) if not match_result and mismatch_description: self.describe_mismatch(item, mismatch_description) return match_result def describe_mismatch(self, item, mismatch_description): mismatch_description.append_text('was ').append_description_of(item) ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/hamcrest/core/compat.py ================================================ __author__ = "Per Fagrell" __copyright__ = "Copyright 2013 hamcrest.org" __license__ = "BSD, see License.txt" __all__ = ['is_callable'] import sys # callable was not part of py3k until 3.2, so we create this # generic is_callable to use callable if possible, otherwise # we use generic homebrew. if sys.version_info[0] == 3 and sys.version_info[1] < 2: def is_callable(function): """Return whether the object is callable (i.e., some kind of function).""" if function is None: return False return any("__call__" in klass.__dict__ for klass in type(function).__mro__) else: is_callable = callable ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/hamcrest/core/core/__init__.py ================================================ from __future__ import absolute_import """Fundamental matchers of objects and values, and composite matchers.""" from hamcrest.core.core.allof import all_of from hamcrest.core.core.anyof import any_of from hamcrest.core.core.described_as import described_as from hamcrest.core.core.is_ import is_ from hamcrest.core.core.isanything import anything from hamcrest.core.core.isequal import equal_to from hamcrest.core.core.isinstanceof import instance_of from hamcrest.core.core.isnone import none, not_none from hamcrest.core.core.isnot import is_not, not_ from hamcrest.core.core.issame import same_instance from hamcrest.core.core.raises import calling, raises __author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/hamcrest/core/core/allof.py ================================================ from hamcrest.core.base_matcher import BaseMatcher from hamcrest.core.helpers.wrap_matcher import wrap_matcher __author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" class AllOf(BaseMatcher): def __init__(self, *matchers): self.matchers = matchers def matches(self, item, mismatch_description=None): for matcher in self.matchers: if not matcher.matches(item): if mismatch_description: mismatch_description.append_description_of(matcher) \ .append_text(' ') matcher.describe_mismatch(item, mismatch_description) return False return True def describe_mismatch(self, item, mismatch_description): self.matches(item, mismatch_description) def describe_to(self, description): description.append_list('(', ' and ', ')', self.matchers) def all_of(*items): """Matches if all of the given matchers evaluate to ``True``. :param matcher1,...: A comma-separated list of matchers. The matchers are evaluated from left to right using short-circuit evaluation, so evaluation stops as soon as a matcher returns ``False``. Any argument that is not a matcher is implicitly wrapped in an :py:func:`~hamcrest.core.core.isequal.equal_to` matcher to check for equality. """ return AllOf(*[wrap_matcher(item) for item in items]) ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/hamcrest/core/core/anyof.py ================================================ from hamcrest.core.base_matcher import BaseMatcher from hamcrest.core.helpers.wrap_matcher import wrap_matcher __author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" class AnyOf(BaseMatcher): def __init__(self, *matchers): self.matchers = matchers def _matches(self, item): for matcher in self.matchers: if matcher.matches(item): return True return False def describe_to(self, description): description.append_list('(', ' or ', ')', self.matchers) def any_of(*items): """Matches if any of the given matchers evaluate to ``True``. :param matcher1,...: A comma-separated list of matchers. The matchers are evaluated from left to right using short-circuit evaluation, so evaluation stops as soon as a matcher returns ``True``. Any argument that is not a matcher is implicitly wrapped in an :py:func:`~hamcrest.core.core.isequal.equal_to` matcher to check for equality. """ return AnyOf(*[wrap_matcher(item) for item in items]) ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/hamcrest/core/core/described_as.py ================================================ from hamcrest.core.base_matcher import BaseMatcher import re __author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" ARG_PATTERN = re.compile('%([0-9]+)') class DescribedAs(BaseMatcher): def __init__(self, description_template, matcher, *values): self.template = description_template self.matcher = matcher self.values = values def matches(self, item, mismatch_description=None): return self.matcher.matches(item, mismatch_description) def describe_mismatch(self, item, mismatch_description): self.matcher.describe_mismatch(item, mismatch_description) def describe_to(self, description): text_start = 0 for match in re.finditer(ARG_PATTERN, self.template): description.append_text(self.template[text_start:match.start()]) arg_index = int(match.group()[1:]) description.append_description_of(self.values[arg_index]) text_start = match.end() if text_start < len(self.template): description.append_text(self.template[text_start:]) def described_as(description, matcher, *values): """Adds custom failure description to a given matcher. :param description: Overrides the matcher's description. :param matcher: The matcher to satisfy. :param value1,...: Optional comma-separated list of substitution values. The description may contain substitution placeholders %0, %1, etc. These will be replaced by any values that follow the matcher. """ return DescribedAs(description, matcher, *values) ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/hamcrest/core/core/is_.py ================================================ from __future__ import absolute_import __author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" from hamcrest.core.base_matcher import BaseMatcher from hamcrest.core.helpers.wrap_matcher import wrap_matcher, is_matchable_type from .isinstanceof import instance_of class Is(BaseMatcher): def __init__(self, matcher): self.matcher = matcher def matches(self, item, mismatch_description=None): return self.matcher.matches(item, mismatch_description) def describe_mismatch(self, item, mismatch_description): return self.matcher.describe_mismatch(item, mismatch_description) def describe_to(self, description): description.append_description_of(self.matcher) def wrap_value_or_type(x): if is_matchable_type(x): return instance_of(x) else: return wrap_matcher(x) def is_(x): """Decorates another matcher, or provides shortcuts to the frequently used ``is(equal_to(x))`` and ``is(instance_of(x))``. :param x: The matcher to satisfy, or a type for :py:func:`~hamcrest.core.core.isinstanceof.instance_of` matching, or an expected value for :py:func:`~hamcrest.core.core.isequal.equal_to` matching. This matcher compares the evaluated object to the given matcher. .. note:: PyHamcrest's ``is_`` matcher is unrelated to Python's ``is`` operator. The matcher for object identity is :py:func:`~hamcrest.core.core.issame.same_instance`. If the ``x`` argument is a matcher, its behavior is retained, but the test may be more expressive. For example:: assert_that(value, less_than(5)) assert_that(value, is_(less_than(5))) If the ``x`` argument is a type, it is wrapped in an :py:func:`~hamcrest.core.core.isinstanceof.instance_of` matcher. This makes the following statements equivalent:: assert_that(cheese, instance_of(Cheddar)) assert_that(cheese, is_(instance_of(Cheddar))) assert_that(cheese, is_(Cheddar)) Otherwise, if the ``x`` argument is not a matcher, it is wrapped in an :py:func:`~hamcrest.core.core.isequal.equal_to` matcher. This makes the following statements equivalent:: assert_that(cheese, equal_to(smelly)) assert_that(cheese, is_(equal_to(smelly))) assert_that(cheese, is_(smelly)) Choose the style that makes your expression most readable. This will vary depending on context. """ return Is(wrap_value_or_type(x)) ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/hamcrest/core/core/isanything.py ================================================ from hamcrest.core.base_matcher import BaseMatcher __author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" class IsAnything(BaseMatcher): def __init__(self, description): self.description = description if not description: self.description = 'ANYTHING' def _matches(self, item): return True def describe_to(self, description): description.append_text(self.description) def anything(description=None): """Matches anything. :param description: Optional string used to describe this matcher. This matcher always evaluates to ``True``. Specify this in composite matchers when the value of a particular element is unimportant. """ return IsAnything(description) ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/hamcrest/core/core/isequal.py ================================================ __author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" from hamcrest.core.base_matcher import BaseMatcher from hamcrest.core.matcher import Matcher class IsEqual(BaseMatcher): def __init__(self, equals): self.object = equals def _matches(self, item): return item == self.object def describe_to(self, description): nested_matcher = isinstance(self.object, Matcher) if nested_matcher: description.append_text('<') description.append_description_of(self.object) if nested_matcher: description.append_text('>') def equal_to(obj): """Matches if object is equal to a given object. :param obj: The object to compare against as the expected value. This matcher compares the evaluated object to ``obj`` for equality.""" return IsEqual(obj) ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/hamcrest/core/core/isinstanceof.py ================================================ from hamcrest.core.base_matcher import BaseMatcher from hamcrest.core.helpers.wrap_matcher import is_matchable_type __author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" import types class IsInstanceOf(BaseMatcher): def __init__(self, expected_type): if not is_matchable_type(expected_type): raise TypeError('IsInstanceOf requires type or a tuple of classes and types') self.expected_type = expected_type def _matches(self, item): return isinstance(item, self.expected_type) def describe_to(self, description): try: type_description = self.expected_type.__name__ except AttributeError: type_description = "one of %s" % ",".join(str(e) for e in self.expected_type) description.append_text('an instance of ') \ .append_text(type_description) def instance_of(atype): """Matches if object is an instance of, or inherits from, a given type. :param atype: The type to compare against as the expected type or a tuple of types. This matcher checks whether the evaluated object is an instance of ``atype`` or an instance of any class that inherits from ``atype``. Example:: instance_of(str) """ return IsInstanceOf(atype) ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/hamcrest/core/core/isnone.py ================================================ from __future__ import absolute_import __author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" from hamcrest.core.base_matcher import BaseMatcher from .isnot import is_not class IsNone(BaseMatcher): def _matches(self, item): return item is None def describe_to(self, description): description.append_text('None') def none(): """Matches if object is ``None``.""" return IsNone() def not_none(): """Matches if object is not ``None``.""" return is_not(none()) ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/hamcrest/core/core/isnot.py ================================================ from __future__ import absolute_import __author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" from hamcrest.core.base_matcher import BaseMatcher, Matcher from hamcrest.core.helpers.wrap_matcher import wrap_matcher, is_matchable_type from .isequal import equal_to from .isinstanceof import instance_of class IsNot(BaseMatcher): def __init__(self, matcher): self.matcher = matcher def _matches(self, item): return not self.matcher.matches(item) def describe_to(self, description): description.append_text('not ').append_description_of(self.matcher) def wrap_value_or_type(x): if is_matchable_type(x): return instance_of(x) else: return wrap_matcher(x) def is_not(match): """Inverts the given matcher to its logical negation. :param match: The matcher to negate. This matcher compares the evaluated object to the negation of the given matcher. If the ``match`` argument is not a matcher, it is implicitly wrapped in an :py:func:`~hamcrest.core.core.isequal.equal_to` matcher to check for equality, and thus matches for inequality. Examples:: assert_that(cheese, is_not(equal_to(smelly))) assert_that(cheese, is_not(smelly)) """ return IsNot(wrap_value_or_type(match)) def not_(match): """Alias of :py:func:`is_not` for better readability of negations. Examples:: assert_that(alist, not_(has_item(item))) """ return is_not(match) ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/hamcrest/core/core/issame.py ================================================ __author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" from hamcrest.core.base_matcher import BaseMatcher class IsSame(BaseMatcher): def __init__(self, object): self.object = object def _matches(self, item): return item is self.object def describe_to(self, description): description.append_text('same instance as ') \ .append_text(hex(id(self.object))) \ .append_text(' ') \ .append_description_of(self.object) def describe_mismatch(self, item, mismatch_description): mismatch_description.append_text('was ') if item is not None: mismatch_description.append_text(hex(id(item))) \ .append_text(' ') mismatch_description.append_description_of(item) def same_instance(obj): """Matches if evaluated object is the same instance as a given object. :param obj: The object to compare against as the expected value. This matcher invokes the ``is`` identity operator to determine if the evaluated object is the the same object as ``obj``. """ return IsSame(obj) ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/hamcrest/core/core/raises.py ================================================ from weakref import ref import re import sys from hamcrest.core.base_matcher import BaseMatcher from hamcrest.core.compat import is_callable __author__ = "Per Fagrell" __copyright__ = "Copyright 2013 hamcrest.org" __license__ = "BSD, see License.txt" class Raises(BaseMatcher): def __init__(self, expected, pattern=None): self.pattern = pattern self.expected = expected self.actual = None self.function = None def _matches(self, function): if not is_callable(function): return False self.function = ref(function) return self._call_function(function) def _call_function(self, function): self.actual = None try: function() except Exception: self.actual = sys.exc_info()[1] if isinstance(self.actual, self.expected): if self.pattern is not None: return re.search(self.pattern, str(self.actual)) is not None return True return False def describe_to(self, description): description.append_text('Expected a callable raising %s' % self.expected) def describe_mismatch(self, item, description): if not is_callable(item): description.append_text('%s is not callable' % item) return function = None if self.function is None else self.function() if function is None or function is not item: self.function = ref(item) if not self._call_function(item): return if self.actual is None: description.append_text('No exception raised.') elif isinstance(self.actual, self.expected) and self.pattern is not None: description.append_text('Correct assertion type raised, but the expected pattern ("%s") not found.' % self.pattern) description.append_text('\n message was: "%s"' % str(self.actual)) else: description.append_text('%s was raised instead' % type(self.actual)) def raises(exception, pattern=None): """Matches if the called function raised the expected exception. :param exception: The class of the expected exception :param pattern: Optional regular expression to match exception message. Expects the actual to be wrapped by using :py:func:`~hamcrest.core.core.raises.calling`, or a callable taking no arguments. Optional argument pattern should be a string containing a regular expression. If provided, the string representation of the actual exception - e.g. `str(actual)` - must match pattern. Examples:: assert_that(calling(int).with_args('q'), raises(TypeError)) assert_that(calling(parse, broken_input), raises(ValueError)) """ return Raises(exception, pattern) class DeferredCallable(object): def __init__(self, func): self.func = func self.args = tuple() self.kwargs = {} def __call__(self): return self.func(*self.args, **self.kwargs) def with_args(self, *args, **kwargs): self.args = args self.kwargs = kwargs return self def calling(func): """Wrapper for function call that delays the actual execution so that :py:func:`~hamcrest.core.core.raises.raises` matcher can catch any thrown exception. :param func: The function or method to be called The arguments can be provided with a call to the `with_args` function on the returned object:: calling(my_method).with_args(arguments, and_='keywords') """ return DeferredCallable(func) ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/hamcrest/core/description.py ================================================ __author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" class Description(object): """A description of a :py:class:`~hamcrest.core.matcher.Matcher`. A :py:class:`~hamcrest.core.matcher.Matcher` will describe itself to a description which can later be used for reporting. """ def append_text(self, text): """Appends some plain text to the description. :returns: ``self``, for chaining """ raise NotImplementedError('append_text') def append_description_of(self, value): """Appends description of given value to this description. If the value implements :py:meth:`~hamcrest.core.selfdescribing.SelfDescribing.describe_to`, then it will be used. :returns: ``self``, for chaining """ raise NotImplementedError('append_description_of') def append_value(self, value): """Appends an arbitary value to the description. **Deprecated:** Call :py:meth:`~hamcrest.core.description.Description.append_description_of` instead. :returns: ``self``, for chaining """ raise NotImplementedError('append_value') def append_list(self, start, separator, end, list): """Appends a list of objects to the description. :param start: String that will begin the list description. :param separator: String that will separate each object in the description. :param end: String that will end the list description. :param list: List of objects to be described. :returns: ``self``, for chaining """ raise NotImplementedError('append_list') ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/hamcrest/core/helpers/__init__.py ================================================ """Utilities for writing Matchers.""" __author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/hamcrest/core/helpers/hasmethod.py ================================================ __author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" def hasmethod(obj, methodname): """Does ``obj`` have a method named ``methodname``?""" if not hasattr(obj, methodname): return False method = getattr(obj, methodname) return callable(method) ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/hamcrest/core/helpers/wrap_matcher.py ================================================ import six from hamcrest.core.base_matcher import Matcher from hamcrest.core.core.isequal import equal_to __author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" import types def wrap_matcher(x): """Wraps argument in a matcher, if necessary. :returns: the argument as-is if it is already a matcher, otherwise wrapped in an :py:func:`~hamcrest.core.core.isequal.equal_to` matcher. """ if isinstance(x, Matcher): return x else: return equal_to(x) def is_matchable_type(expected_type): if isinstance(expected_type, type): return True if isinstance(expected_type, six.class_types): return True if isinstance(expected_type, tuple) and \ expected_type and \ all(map(is_matchable_type, expected_type)): return True return False ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/hamcrest/core/matcher.py ================================================ from __future__ import absolute_import from .selfdescribing import SelfDescribing __author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" class Matcher(SelfDescribing): """A matcher over acceptable values. A matcher is able to describe itself to give feedback when it fails. Matcher implementations should *not* directly implement this protocol. Instead, *extend* the :py:class:`~hamcrest.core.base_matcher.BaseMatcher` class, which will ensure that the :py:class:`~hamcrest.core.matcher.Matcher` API can grow to support new features and remain compatible with all :py:class:`~hamcrest.core.matcher.Matcher` implementations. """ def matches(self, item, mismatch_description=None): """Evaluates the matcher for argument item. If a mismatch is detected and argument ``mismatch_description`` is provided, it will generate a description of why the matcher has not accepted the item. :param item: The object against which the matcher is evaluated. :returns: ``True`` if ``item`` matches, otherwise ``False``. """ raise NotImplementedError('matches') def describe_mismatch(self, item, mismatch_description): """Generates a description of why the matcher has not accepted the item. The description will be part of a larger description of why a matching failed, so it should be concise. This method assumes that ``matches(item)`` is ``False``, but will not check this. :param item: The item that the :py:class:`~hamcrest.core.matcher.Matcher` has rejected. :param mismatch_description: The description to be built or appended to. """ raise NotImplementedError('describe_mismatch') ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/hamcrest/core/selfdescribing.py ================================================ __author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" class SelfDescribing(object): """The ability of an object to describe itself.""" def describe_to(self, description): """Generates a description of the object. The description may be part of a description of a larger object of which this is just a component, so it should be worded appropriately. :param description: The description to be built or appended to. """ raise NotImplementedError('describe_to') ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/hamcrest/core/selfdescribingvalue.py ================================================ from hamcrest.core.selfdescribing import SelfDescribing import warnings __author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" class SelfDescribingValue(SelfDescribing): """Wrap any value in a ``SelfDescribingValue`` to satisfy the :py:class:`~hamcrest.core.selfdescribing.SelfDescribing` interface. **Deprecated:** No need for this class now that :py:meth:`~hamcrest.core.description.Description.append_description_of` handles any type of value. """ def __init__(self, value): warnings.warn('SelfDescribingValue no longer needed', DeprecationWarning) self.value = value def describe_to(self, description): """Generates a description of the value.""" description.append_value(self.value) ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/hamcrest/core/string_description.py ================================================ from __future__ import absolute_import import codecs import six from .base_description import BaseDescription __author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" def tostring(selfdescribing): """Returns the description of a :py:class:`~hamcrest.core.selfdescribing.SelfDescribing` object as a string. :param selfdescribing: The object to be described. :returns: The description of the object. """ return str(StringDescription().append_description_of(selfdescribing)) class StringDescription(BaseDescription): """A :py:class:`~hamcrest.core.description.Description` that is stored as a string. """ def __init__(self): self.out = '' def __str__(self): """Returns the description.""" return self.out def append(self, string): self.out += six.text_type(string) ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/hamcrest/library/__init__.py ================================================ from __future__ import absolute_import """Library of Matcher implementations.""" from hamcrest.core import * from hamcrest.library.collection import * from hamcrest.library.integration import * from hamcrest.library.number import * from hamcrest.library.object import * from hamcrest.library.text import * __author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" __all__ = [ 'has_entry', 'has_entries', 'has_key', 'has_value', 'is_in', 'empty', 'has_item', 'has_items', 'contains_inanyorder', 'contains', 'only_contains', 'match_equality', 'matches_regexp', 'close_to', 'greater_than', 'greater_than_or_equal_to', 'less_than', 'less_than_or_equal_to', 'has_length', 'has_property', 'has_properties', 'has_string', 'equal_to_ignoring_case', 'equal_to_ignoring_whitespace', 'contains_string', 'ends_with', 'starts_with', 'string_contains_in_order', ] ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/hamcrest/library/collection/__init__.py ================================================ """Matchers of collections.""" from __future__ import absolute_import from .isdict_containing import has_entry from .isdict_containingentries import has_entries from .isdict_containingkey import has_key from .isdict_containingvalue import has_value from .isin import is_in from .issequence_containing import has_item, has_items from .issequence_containinginanyorder import contains_inanyorder from .issequence_containinginorder import contains from .issequence_onlycontaining import only_contains from .is_empty import empty __author__ = "Chris Rose" __copyright__ = "Copyright 2013 hamcrest.org" __license__ = "BSD, see License.txt" ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/hamcrest/library/collection/is_empty.py ================================================ from hamcrest.core.base_matcher import BaseMatcher __author__ = "Chris Rose" __copyright__ = "Copyright 2012 hamcrest.org" __license__ = "BSD, see License.txt" class IsEmpty(BaseMatcher): def matches(self, item, mismatch_description=None): try: if len(item) == 0: return True if mismatch_description: mismatch_description \ .append_text('has %d item(s)' % len(item)) except TypeError: if mismatch_description: mismatch_description \ .append_text('does not support length') return False def describe_to(self, description): description.append_text('an empty collection') def empty(): """ This matcher matches any collection-like object that responds to the __len__ method, and has a length of 0. """ return IsEmpty() ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/hamcrest/library/collection/isdict_containing.py ================================================ from hamcrest.core.base_matcher import BaseMatcher from hamcrest.core.helpers.hasmethod import hasmethod from hamcrest.core.helpers.wrap_matcher import wrap_matcher __author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" class IsDictContaining(BaseMatcher): def __init__(self, key_matcher, value_matcher): self.key_matcher = key_matcher self.value_matcher = value_matcher def _matches(self, dictionary): if hasmethod(dictionary, 'items'): for key, value in dictionary.items(): if self.key_matcher.matches(key) and self.value_matcher.matches(value): return True return False def describe_to(self, description): description.append_text('a dictionary containing [') \ .append_description_of(self.key_matcher) \ .append_text(': ') \ .append_description_of(self.value_matcher) \ .append_text(']') def has_entry(key_match, value_match): """Matches if dictionary contains key-value entry satisfying a given pair of matchers. :param key_match: The matcher to satisfy for the key, or an expected value for :py:func:`~hamcrest.core.core.isequal.equal_to` matching. :param value_match: The matcher to satisfy for the value, or an expected value for :py:func:`~hamcrest.core.core.isequal.equal_to` matching. This matcher iterates the evaluated dictionary, searching for any key-value entry that satisfies ``key_match`` and ``value_match``. If a matching entry is found, ``has_entry`` is satisfied. Any argument that is not a matcher is implicitly wrapped in an :py:func:`~hamcrest.core.core.isequal.equal_to` matcher to check for equality. Examples:: has_entry(equal_to('foo'), equal_to(1)) has_entry('foo', 1) """ return IsDictContaining(wrap_matcher(key_match), wrap_matcher(value_match)) ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/hamcrest/library/collection/isdict_containingentries.py ================================================ from hamcrest.core.base_matcher import BaseMatcher from hamcrest.core.helpers.hasmethod import hasmethod from hamcrest.core.helpers.wrap_matcher import wrap_matcher __author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" class IsDictContainingEntries(BaseMatcher): def __init__(self, value_matchers): self.value_matchers = sorted(value_matchers.items()) def _not_a_dictionary(self, dictionary, mismatch_description): if mismatch_description: mismatch_description.append_description_of(dictionary) \ .append_text(' is not a mapping object') return False def matches(self, dictionary, mismatch_description=None): for key, value_matcher in self.value_matchers: try: if not key in dictionary: if mismatch_description: mismatch_description.append_text('no ') \ .append_description_of(key) \ .append_text(' key in ') \ .append_description_of(dictionary) return False except TypeError: return self._not_a_dictionary(dictionary, mismatch_description) try: actual_value = dictionary[key] except TypeError: return self._not_a_dictionary(dictionary, mismatch_description) if not value_matcher.matches(actual_value): if mismatch_description: mismatch_description.append_text('value for ') \ .append_description_of(key) \ .append_text(' ') value_matcher.describe_mismatch(actual_value, mismatch_description) return False return True def describe_mismatch(self, item, mismatch_description): self.matches(item, mismatch_description) def describe_keyvalue(self, index, value, description): """Describes key-value pair at given index.""" description.append_description_of(index) \ .append_text(': ') \ .append_description_of(value) def describe_to(self, description): description.append_text('a dictionary containing {') first = True for key, value in self.value_matchers: if not first: description.append_text(', ') self.describe_keyvalue(key, value, description) first = False description.append_text('}') def has_entries(*keys_valuematchers, **kv_args): """Matches if dictionary contains entries satisfying a dictionary of keys and corresponding value matchers. :param matcher_dict: A dictionary mapping keys to associated value matchers, or to expected values for :py:func:`~hamcrest.core.core.isequal.equal_to` matching. Note that the keys must be actual keys, not matchers. Any value argument that is not a matcher is implicitly wrapped in an :py:func:`~hamcrest.core.core.isequal.equal_to` matcher to check for equality. Examples:: has_entries({'foo':equal_to(1), 'bar':equal_to(2)}) has_entries({'foo':1, 'bar':2}) ``has_entries`` also accepts a list of keyword arguments: .. function:: has_entries(keyword1=value_matcher1[, keyword2=value_matcher2[, ...]]) :param keyword1: A keyword to look up. :param valueMatcher1: The matcher to satisfy for the value, or an expected value for :py:func:`~hamcrest.core.core.isequal.equal_to` matching. Examples:: has_entries(foo=equal_to(1), bar=equal_to(2)) has_entries(foo=1, bar=2) Finally, ``has_entries`` also accepts a list of alternating keys and their value matchers: .. function:: has_entries(key1, value_matcher1[, ...]) :param key1: A key (not a matcher) to look up. :param valueMatcher1: The matcher to satisfy for the value, or an expected value for :py:func:`~hamcrest.core.core.isequal.equal_to` matching. Examples:: has_entries('foo', equal_to(1), 'bar', equal_to(2)) has_entries('foo', 1, 'bar', 2) """ if len(keys_valuematchers) == 1: try: base_dict = keys_valuematchers[0].copy() for key in base_dict: base_dict[key] = wrap_matcher(base_dict[key]) except AttributeError: raise ValueError('single-argument calls to has_entries must pass a dict as the argument') else: if len(keys_valuematchers) % 2: raise ValueError('has_entries requires key-value pairs') base_dict = {} for index in range(int(len(keys_valuematchers) / 2)): base_dict[keys_valuematchers[2 * index]] = wrap_matcher(keys_valuematchers[2 * index + 1]) for key, value in kv_args.items(): base_dict[key] = wrap_matcher(value) return IsDictContainingEntries(base_dict) ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/hamcrest/library/collection/isdict_containingkey.py ================================================ from hamcrest.core.base_matcher import BaseMatcher from hamcrest.core.helpers.hasmethod import hasmethod from hamcrest.core.helpers.wrap_matcher import wrap_matcher __author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" class IsDictContainingKey(BaseMatcher): def __init__(self, key_matcher): self.key_matcher = key_matcher def _matches(self, dictionary): if hasmethod(dictionary, 'keys'): for key in dictionary.keys(): if self.key_matcher.matches(key): return True return False def describe_to(self, description): description.append_text('a dictionary containing key ') \ .append_description_of(self.key_matcher) def has_key(key_match): """Matches if dictionary contains an entry whose key satisfies a given matcher. :param key_match: The matcher to satisfy for the key, or an expected value for :py:func:`~hamcrest.core.core.isequal.equal_to` matching. This matcher iterates the evaluated dictionary, searching for any key-value entry whose key satisfies the given matcher. If a matching entry is found, ``has_key`` is satisfied. Any argument that is not a matcher is implicitly wrapped in an :py:func:`~hamcrest.core.core.isequal.equal_to` matcher to check for equality. Examples:: has_key(equal_to('foo')) has_key('foo') """ return IsDictContainingKey(wrap_matcher(key_match)) ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/hamcrest/library/collection/isdict_containingvalue.py ================================================ from hamcrest.core.base_matcher import BaseMatcher from hamcrest.core.helpers.hasmethod import hasmethod from hamcrest.core.helpers.wrap_matcher import wrap_matcher __author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" class IsDictContainingValue(BaseMatcher): def __init__(self, value_matcher): self.value_matcher = value_matcher def _matches(self, dictionary): if hasmethod(dictionary, 'values'): for value in dictionary.values(): if self.value_matcher.matches(value): return True return False def describe_to(self, description): description.append_text('a dictionary containing value ') \ .append_description_of(self.value_matcher) def has_value(value): """Matches if dictionary contains an entry whose value satisfies a given matcher. :param value_match: The matcher to satisfy for the value, or an expected value for :py:func:`~hamcrest.core.core.isequal.equal_to` matching. This matcher iterates the evaluated dictionary, searching for any key-value entry whose value satisfies the given matcher. If a matching entry is found, ``has_value`` is satisfied. Any argument that is not a matcher is implicitly wrapped in an :py:func:`~hamcrest.core.core.isequal.equal_to` matcher to check for equality. Examples:: has_value(equal_to('bar')) has_value('bar') """ return IsDictContainingValue(wrap_matcher(value)) ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/hamcrest/library/collection/isin.py ================================================ from hamcrest.core.base_matcher import BaseMatcher __author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" class IsIn(BaseMatcher): def __init__(self, sequence): self.sequence = sequence def _matches(self, item): return item in self.sequence def describe_to(self, description): description.append_text('one of ') \ .append_list('(', ', ', ')', self.sequence) def is_in(sequence): """Matches if evaluated object is present in a given sequence. :param sequence: The sequence to search. This matcher invokes the ``in`` membership operator to determine if the evaluated object is a member of the sequence. """ return IsIn(sequence) ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/hamcrest/library/collection/issequence_containing.py ================================================ __author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" from hamcrest.core.base_matcher import BaseMatcher from hamcrest.core.core.allof import all_of from hamcrest.core.helpers.hasmethod import hasmethod from hamcrest.core.helpers.wrap_matcher import wrap_matcher class IsSequenceContaining(BaseMatcher): def __init__(self, element_matcher): self.element_matcher = element_matcher def _matches(self, sequence): try: for item in sequence: if self.element_matcher.matches(item): return True except TypeError: # not a sequence return False def describe_to(self, description): description.append_text('a sequence containing ') \ .append_description_of(self.element_matcher) # It'd be great to make use of all_of, but we can't be sure we won't # be seeing a one-time sequence here (like a generator); see issue #20 # Instead, we wrap it inside a class that will convert the sequence into # a concrete list and then hand it off to the all_of matcher. class IsSequenceContainingEvery(BaseMatcher): def __init__(self, *element_matchers): delegates = [has_item(e) for e in element_matchers] self.matcher = all_of(*delegates) def _matches(self, sequence): try: return self.matcher.matches(list(sequence)) except TypeError: return False def describe_mismatch(self, item, mismatch_description): self.matcher.describe_mismatch(item, mismatch_description) def describe_to(self, description): self.matcher.describe_to(description) def has_item(match): """Matches if any element of sequence satisfies a given matcher. :param match: The matcher to satisfy, or an expected value for :py:func:`~hamcrest.core.core.isequal.equal_to` matching. This matcher iterates the evaluated sequence, searching for any element that satisfies a given matcher. If a matching element is found, ``has_item`` is satisfied. If the ``match`` argument is not a matcher, it is implicitly wrapped in an :py:func:`~hamcrest.core.core.isequal.equal_to` matcher to check for equality. """ return IsSequenceContaining(wrap_matcher(match)) def has_items(*items): """Matches if all of the given matchers are satisfied by any elements of the sequence. :param match1,...: A comma-separated list of matchers. This matcher iterates the given matchers, searching for any elements in the evaluated sequence that satisfy them. If each matcher is satisfied, then ``has_items`` is satisfied. Any argument that is not a matcher is implicitly wrapped in an :py:func:`~hamcrest.core.core.isequal.equal_to` matcher to check for equality. """ matchers = [] for item in items: matchers.append(wrap_matcher(item)) return IsSequenceContainingEvery(*matchers) ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/hamcrest/library/collection/issequence_containinginanyorder.py ================================================ from hamcrest.core.base_matcher import BaseMatcher from hamcrest.core.helpers.hasmethod import hasmethod from hamcrest.core.helpers.wrap_matcher import wrap_matcher __author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" class MatchInAnyOrder(object): def __init__(self, matchers, mismatch_description): self.matchers = matchers[:] self.mismatch_description = mismatch_description def matches(self, item): return self.isnotsurplus(item) and self.ismatched(item) def isfinished(self, sequence): if not self.matchers: return True if self.mismatch_description: self.mismatch_description.append_text('no item matches: ') \ .append_list('', ', ', '', self.matchers) \ .append_text(' in ') \ .append_list('[', ', ', ']', sequence) return False def isnotsurplus(self, item): if not self.matchers: if self.mismatch_description: self.mismatch_description.append_text('not matched: ') \ .append_description_of(item) return False return True def ismatched(self, item): for index, matcher in enumerate(self.matchers): if matcher.matches(item): del self.matchers[index] return True if self.mismatch_description: self.mismatch_description.append_text('not matched: ') \ .append_description_of(item) return False class IsSequenceContainingInAnyOrder(BaseMatcher): def __init__(self, matchers): self.matchers = matchers def matches(self, sequence, mismatch_description=None): try: sequence = list(sequence) matchsequence = MatchInAnyOrder(self.matchers, mismatch_description) for item in sequence: if not matchsequence.matches(item): return False return matchsequence.isfinished(sequence) except TypeError: if mismatch_description: super(IsSequenceContainingInAnyOrder, self) \ .describe_mismatch(sequence, mismatch_description) return False def describe_mismatch(self, item, mismatch_description): self.matches(item, mismatch_description) def describe_to(self, description): description.append_text('a sequence over ') \ .append_list('[', ', ', ']', self.matchers) \ .append_text(' in any order') def contains_inanyorder(*items): """Matches if sequences's elements, in any order, satisfy a given list of matchers. :param match1,...: A comma-separated list of matchers. This matcher iterates the evaluated sequence, seeing if each element satisfies any of the given matchers. The matchers are tried from left to right, and when a satisfied matcher is found, it is no longer a candidate for the remaining elements. If a one-to-one correspondence is established between elements and matchers, ``contains_inanyorder`` is satisfied. Any argument that is not a matcher is implicitly wrapped in an :py:func:`~hamcrest.core.core.isequal.equal_to` matcher to check for equality. """ matchers = [] for item in items: matchers.append(wrap_matcher(item)) return IsSequenceContainingInAnyOrder(matchers) ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/hamcrest/library/collection/issequence_containinginorder.py ================================================ __author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" from hamcrest.core.base_matcher import BaseMatcher from hamcrest.core.helpers.hasmethod import hasmethod from hamcrest.core.helpers.wrap_matcher import wrap_matcher class MatchingInOrder(object): def __init__(self, matchers, mismatch_description): self.matchers = matchers self.mismatch_description = mismatch_description self.next_match_index = 0 def matches(self, item): return self.isnotsurplus(item) and self.ismatched(item) def isfinished(self): if self.next_match_index < len(self.matchers): if self.mismatch_description: self.mismatch_description.append_text('No item matched: ') \ .append_description_of(self.matchers[self.next_match_index]) return False return True def ismatched(self, item): matcher = self.matchers[self.next_match_index] if not matcher.matches(item): if self.mismatch_description: self.mismatch_description.append_text('item ' + str(self.next_match_index) + ': ') matcher.describe_mismatch(item, self.mismatch_description) return False self.next_match_index += 1 return True def isnotsurplus(self, item): if len(self.matchers) <= self.next_match_index: if self.mismatch_description: self.mismatch_description.append_text('Not matched: ') \ .append_description_of(item) return False return True class IsSequenceContainingInOrder(BaseMatcher): def __init__(self, matchers): self.matchers = matchers def matches(self, sequence, mismatch_description=None): try: matchsequence = MatchingInOrder(self.matchers, mismatch_description) for item in sequence: if not matchsequence.matches(item): return False return matchsequence.isfinished() except TypeError: if mismatch_description: super(IsSequenceContainingInOrder, self) \ .describe_mismatch(sequence, mismatch_description) return False def describe_mismatch(self, item, mismatch_description): self.matches(item, mismatch_description) def describe_to(self, description): description.append_text('a sequence containing ') \ .append_list('[', ', ', ']', self.matchers) def contains(*items): """Matches if sequence's elements satisfy a given list of matchers, in order. :param match1,...: A comma-separated list of matchers. This matcher iterates the evaluated sequence and a given list of matchers, seeing if each element satisfies its corresponding matcher. Any argument that is not a matcher is implicitly wrapped in an :py:func:`~hamcrest.core.core.isequal.equal_to` matcher to check for equality. """ matchers = [] for item in items: matchers.append(wrap_matcher(item)) return IsSequenceContainingInOrder(matchers) ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/hamcrest/library/collection/issequence_onlycontaining.py ================================================ from hamcrest.core.base_matcher import BaseMatcher from hamcrest.core.core.anyof import any_of from hamcrest.core.helpers.hasmethod import hasmethod from hamcrest.core.helpers.wrap_matcher import wrap_matcher __author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" class IsSequenceOnlyContaining(BaseMatcher): def __init__(self, matcher): self.matcher = matcher def _matches(self, sequence): try: sequence = list(sequence) if len(sequence) == 0: return False for item in sequence: if not self.matcher.matches(item): return False return True except TypeError: return False def describe_to(self, description): description.append_text('a sequence containing items matching ') \ .append_description_of(self.matcher) def only_contains(*items): """Matches if each element of sequence satisfies any of the given matchers. :param match1,...: A comma-separated list of matchers. This matcher iterates the evaluated sequence, confirming whether each element satisfies any of the given matchers. Example:: only_contains(less_than(4)) will match ``[3,1,2]``. Any argument that is not a matcher is implicitly wrapped in an :py:func:`~hamcrest.core.core.isequal.equal_to` matcher to check for equality. """ matchers = [] for item in items: matchers.append(wrap_matcher(item)) return IsSequenceOnlyContaining(any_of(*matchers)) ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/hamcrest/library/integration/__init__.py ================================================ from __future__ import absolute_import """Utilities for integrating Hamcrest with other libraries.""" from .match_equality import match_equality __author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/hamcrest/library/integration/match_equality.py ================================================ from hamcrest.core.string_description import tostring from hamcrest.core.helpers.wrap_matcher import wrap_matcher __author__ = "Chris Rose" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" __unittest = True class EqualityWrapper(object): def __init__(self, matcher): self.matcher = matcher def __eq__(self, object): return self.matcher.matches(object) def __str__(self): return repr(self) def __repr__(self): return tostring(self.matcher) def match_equality(matcher): """Wraps a matcher to define equality in terms of satisfying the matcher. ``match_equality`` allows Hamcrest matchers to be used in libraries that are not Hamcrest-aware. They might use the equality operator:: assert match_equality(matcher) == object Or they might provide a method that uses equality for its test:: library.method_that_tests_eq(match_equality(matcher)) One concrete example is integrating with the ``assert_called_with`` methods in Michael Foord's `mock `_ library. """ return EqualityWrapper(wrap_matcher(matcher)) ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/hamcrest/library/number/__init__.py ================================================ from __future__ import absolute_import """Matchers that perform numeric comparisons.""" from .iscloseto import close_to from .ordering_comparison import greater_than, greater_than_or_equal_to, less_than, less_than_or_equal_to __author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/hamcrest/library/number/iscloseto.py ================================================ import six from hamcrest.core.base_matcher import BaseMatcher from math import fabs __author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" def isnumeric(value): """Confirm that 'value' can be treated numerically; duck-test accordingly """ if isinstance(value, (float, complex) + six.integer_types): return True try: _ = (fabs(value) + 0 - 0) * 1 return True except ArithmeticError: return True except: return False return False class IsCloseTo(BaseMatcher): def __init__(self, value, delta): if not isnumeric(value): raise TypeError('IsCloseTo value must be numeric') if not isnumeric(delta): raise TypeError('IsCloseTo delta must be numeric') self.value = value self.delta = delta def _matches(self, item): if not isnumeric(item): return False return fabs(item - self.value) <= self.delta def describe_mismatch(self, item, mismatch_description): if not isnumeric(item): super(IsCloseTo, self).describe_mismatch(item, mismatch_description) else: actual_delta = fabs(item - self.value) mismatch_description.append_description_of(item) \ .append_text(' differed by ') \ .append_description_of(actual_delta) def describe_to(self, description): description.append_text('a numeric value within ') \ .append_description_of(self.delta) \ .append_text(' of ') \ .append_description_of(self.value) def close_to(value, delta): """Matches if object is a number close to a given value, within a given delta. :param value: The value to compare against as the expected value. :param delta: The maximum delta between the values for which the numbers are considered close. This matcher compares the evaluated object against ``value`` to see if the difference is within a positive ``delta``. Example:: close_to(3.0, 0.25) """ return IsCloseTo(value, delta) ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/hamcrest/library/number/ordering_comparison.py ================================================ from hamcrest.core.base_matcher import BaseMatcher import operator __author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" class OrderingComparison(BaseMatcher): def __init__(self, value, comparison_function, comparison_description): self.value = value self.comparison_function = comparison_function self.comparison_description = comparison_description def _matches(self, item): return self.comparison_function(item, self.value) def describe_to(self, description): description.append_text('a value ') \ .append_text(self.comparison_description) \ .append_text(' ') \ .append_description_of(self.value) def greater_than(value): """Matches if object is greater than a given value. :param value: The value to compare against. """ return OrderingComparison(value, operator.gt, 'greater than') def greater_than_or_equal_to(value): """Matches if object is greater than or equal to a given value. :param value: The value to compare against. """ return OrderingComparison(value, operator.ge, 'greater than or equal to') def less_than(value): """Matches if object is less than a given value. :param value: The value to compare against. """ return OrderingComparison(value, operator.lt, 'less than') def less_than_or_equal_to(value): """Matches if object is less than or equal to a given value. :param value: The value to compare against. """ return OrderingComparison(value, operator.le, 'less than or equal to') ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/hamcrest/library/object/__init__.py ================================================ from __future__ import absolute_import """Matchers that inspect objects and classes.""" from .haslength import has_length from .hasproperty import has_property, has_properties from .hasstring import has_string __author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/hamcrest/library/object/haslength.py ================================================ from hamcrest.core.base_matcher import BaseMatcher from hamcrest.core.helpers.hasmethod import hasmethod from hamcrest.core.helpers.wrap_matcher import wrap_matcher __author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" class HasLength(BaseMatcher): def __init__(self, len_matcher): self.len_matcher = len_matcher def _matches(self, item): if not hasmethod(item, '__len__'): return False return self.len_matcher.matches(len(item)) def describe_mismatch(self, item, mismatch_description): super(HasLength, self).describe_mismatch(item, mismatch_description) if hasmethod(item, '__len__'): mismatch_description.append_text(' with length of ') \ .append_description_of(len(item)) def describe_to(self, description): description.append_text('an object with length of ') \ .append_description_of(self.len_matcher) def has_length(match): """Matches if ``len(item)`` satisfies a given matcher. :param match: The matcher to satisfy, or an expected value for :py:func:`~hamcrest.core.core.isequal.equal_to` matching. This matcher invokes the :py:func:`len` function on the evaluated object to get its length, passing the result to a given matcher for evaluation. If the ``match`` argument is not a matcher, it is implicitly wrapped in an :py:func:`~hamcrest.core.core.isequal.equal_to` matcher to check for :equality. Examples:: has_length(greater_than(6)) has_length(5) """ return HasLength(wrap_matcher(match)) ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/hamcrest/library/object/hasproperty.py ================================================ from hamcrest.core.base_matcher import BaseMatcher from hamcrest.core import anything from hamcrest.core.core.allof import all_of from hamcrest.core.string_description import StringDescription from hamcrest.core.helpers.hasmethod import hasmethod from hamcrest.core.helpers.wrap_matcher import wrap_matcher as wrap_shortcut __author__ = "Chris Rose" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" class IsObjectWithProperty(BaseMatcher): def __init__(self, property_name, value_matcher): self.property_name = property_name self.value_matcher = value_matcher def _matches(self, o): if o is None: return False if not hasattr(o, self.property_name): return False value = getattr(o, self.property_name) return self.value_matcher.matches(value) def describe_to(self, description): description.append_text("an object with a property '") \ .append_text(self.property_name) \ .append_text("' matching ") \ .append_description_of(self.value_matcher) def describe_mismatch(self, item, mismatch_description): if item is None: mismatch_description.append_text('was None') return if not hasattr(item, self.property_name): mismatch_description.append_value(item) \ .append_text(' did not have the ') \ .append_value(self.property_name) \ .append_text(' property') return mismatch_description.append_text('property ').append_value(self.property_name).append_text(' ') value = getattr(item, self.property_name) self.value_matcher.describe_mismatch(value, mismatch_description) def __str__(self): d = StringDescription() self.describe_to(d) return str(d) def has_property(name, match=None): """Matches if object has a property with a given name whose value satisfies a given matcher. :param name: The name of the property. :param match: Optional matcher to satisfy. This matcher determines if the evaluated object has a property with a given name. If no such property is found, ``has_property`` is not satisfied. If the property is found, its value is passed to a given matcher for evaluation. If the ``match`` argument is not a matcher, it is implicitly wrapped in an :py:func:`~hamcrest.core.core.isequal.equal_to` matcher to check for equality. If the ``match`` argument is not provided, the :py:func:`~hamcrest.core.core.isanything.anything` matcher is used so that ``has_property`` is satisfied if a matching property is found. Examples:: has_property('name', starts_with('J')) has_property('name', 'Jon') has_property('name') """ if match is None: match = anything() return IsObjectWithProperty(name, wrap_shortcut(match)) def has_properties(*keys_valuematchers, **kv_args): """Matches if an object has properties satisfying all of a dictionary of string property names and corresponding value matchers. :param matcher_dict: A dictionary mapping keys to associated value matchers, or to expected values for :py:func:`~hamcrest.core.core.isequal.equal_to` matching. Note that the keys must be actual keys, not matchers. Any value argument that is not a matcher is implicitly wrapped in an :py:func:`~hamcrest.core.core.isequal.equal_to` matcher to check for equality. Examples:: has_properties({'foo':equal_to(1), 'bar':equal_to(2)}) has_properties({'foo':1, 'bar':2}) ``has_properties`` also accepts a list of keyword arguments: .. function:: has_properties(keyword1=value_matcher1[, keyword2=value_matcher2[, ...]]) :param keyword1: A keyword to look up. :param valueMatcher1: The matcher to satisfy for the value, or an expected value for :py:func:`~hamcrest.core.core.isequal.equal_to` matching. Examples:: has_properties(foo=equal_to(1), bar=equal_to(2)) has_properties(foo=1, bar=2) Finally, ``has_properties`` also accepts a list of alternating keys and their value matchers: .. function:: has_properties(key1, value_matcher1[, ...]) :param key1: A key (not a matcher) to look up. :param valueMatcher1: The matcher to satisfy for the value, or an expected value for :py:func:`~hamcrest.core.core.isequal.equal_to` matching. Examples:: has_properties('foo', equal_to(1), 'bar', equal_to(2)) has_properties('foo', 1, 'bar', 2) """ if len(keys_valuematchers) == 1: try: base_dict = keys_valuematchers[0].copy() for key in base_dict: base_dict[key] = wrap_shortcut(base_dict[key]) except AttributeError: raise ValueError('single-argument calls to has_properties must pass a dict as the argument') else: if len(keys_valuematchers) % 2: raise ValueError('has_properties requires key-value pairs') base_dict = {} for index in range(int(len(keys_valuematchers) / 2)): base_dict[keys_valuematchers[2 * index]] = wrap_shortcut(keys_valuematchers[2 * index + 1]) for key, value in kv_args.items(): base_dict[key] = wrap_shortcut(value) return all_of(*[has_property(property_name, property_value_matcher) for \ property_name, property_value_matcher in base_dict.items()]) ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/hamcrest/library/object/hasstring.py ================================================ from hamcrest.core.base_matcher import BaseMatcher from hamcrest.core.helpers.wrap_matcher import wrap_matcher __author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" class HasString(BaseMatcher): def __init__(self, str_matcher): self.str_matcher = str_matcher def _matches(self, item): return self.str_matcher.matches(str(item)) def describe_to(self, description): description.append_text('an object with str ') \ .append_description_of(self.str_matcher) def has_string(match): """Matches if ``str(item)`` satisfies a given matcher. :param match: The matcher to satisfy, or an expected value for :py:func:`~hamcrest.core.core.isequal.equal_to` matching. This matcher invokes the :py:func:`str` function on the evaluated object to get its length, passing the result to a given matcher for evaluation. If the ``match`` argument is not a matcher, it is implicitly wrapped in an :py:func:`~hamcrest.core.core.isequal.equal_to` matcher to check for equality. Examples:: has_string(starts_with('foo')) has_string('bar') """ return HasString(wrap_matcher(match)) ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/hamcrest/library/text/__init__.py ================================================ from __future__ import absolute_import """Matchers that perform text comparisons.""" from .isequal_ignoring_case import equal_to_ignoring_case from .isequal_ignoring_whitespace import equal_to_ignoring_whitespace from .stringcontains import contains_string from .stringendswith import ends_with from .stringstartswith import starts_with from .stringmatches import matches_regexp from .stringcontainsinorder import string_contains_in_order __author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/hamcrest/library/text/isequal_ignoring_case.py ================================================ __author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" from hamcrest.core.base_matcher import BaseMatcher import six class IsEqualIgnoringCase(BaseMatcher): def __init__(self, string): if not isinstance(string, six.string_types): raise TypeError('IsEqualIgnoringCase requires string') self.original_string = string self.lowered_string = string.lower() def _matches(self, item): if not isinstance(item, six.string_types): return False return self.lowered_string == item.lower() def describe_to(self, description): description.append_description_of(self.original_string) \ .append_text(' ignoring case') def equal_to_ignoring_case(string): """Matches if object is a string equal to a given string, ignoring case differences. :param string: The string to compare against as the expected value. This matcher first checks whether the evaluated object is a string. If so, it compares it with ``string``, ignoring differences of case. Example:: equal_to_ignoring_case("hello world") will match "heLLo WorlD". """ return IsEqualIgnoringCase(string) ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/hamcrest/library/text/isequal_ignoring_whitespace.py ================================================ __author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" from hamcrest.core.base_matcher import BaseMatcher import six def stripspace(string): result = '' last_was_space = True for character in string: if character.isspace(): if not last_was_space: result += ' ' last_was_space = True else: result += character last_was_space = False return result.strip() class IsEqualIgnoringWhiteSpace(BaseMatcher): def __init__(self, string): if not isinstance(string, six.string_types): raise TypeError('IsEqualIgnoringWhiteSpace requires string') self.original_string = string self.stripped_string = stripspace(string) def _matches(self, item): if not isinstance(item, six.string_types): return False return self.stripped_string == stripspace(item) def describe_to(self, description): description.append_description_of(self.original_string) \ .append_text(' ignoring whitespace') def equal_to_ignoring_whitespace(string): """Matches if object is a string equal to a given string, ignoring differences in whitespace. :param string: The string to compare against as the expected value. This matcher first checks whether the evaluated object is a string. If so, it compares it with ``string``, ignoring differences in runs of whitespace. Example:: equal_to_ignoring_whitespace("hello world") will match ``"hello world"``. """ return IsEqualIgnoringWhiteSpace(string) ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/hamcrest/library/text/stringcontains.py ================================================ from hamcrest.library.text.substringmatcher import SubstringMatcher from hamcrest.core.helpers.hasmethod import hasmethod __author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" class StringContains(SubstringMatcher): def __init__(self, substring): super(StringContains, self).__init__(substring) def _matches(self, item): if not hasmethod(item, 'find'): return False return item.find(self.substring) >= 0 def relationship(self): return 'containing' def contains_string(substring): """Matches if object is a string containing a given string. :param string: The string to search for. This matcher first checks whether the evaluated object is a string. If so, it checks whether it contains ``string``. Example:: contains_string("def") will match "abcdefg". """ return StringContains(substring) ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/hamcrest/library/text/stringcontainsinorder.py ================================================ __author__ = "Romilly Cocking" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" from hamcrest.core.base_matcher import BaseMatcher from hamcrest.core.helpers.hasmethod import hasmethod import six class StringContainsInOrder(BaseMatcher): def __init__(self, *substrings): for substring in substrings: if not isinstance(substring, six.string_types): raise TypeError(self.__class__.__name__ + ' requires string arguments') self.substrings = substrings def _matches(self, item): if not hasmethod(item, 'find'): return False from_index = 0 for substring in self.substrings: from_index = item.find(substring, from_index) if from_index == -1: return False return True def describe_to(self, description): description.append_list('a string containing ', ', ', ' in order', self.substrings) def string_contains_in_order(*substrings): """Matches if object is a string containing a given list of substrings in relative order. :param string1,...: A comma-separated list of strings. This matcher first checks whether the evaluated object is a string. If so, it checks whether it contains a given list of strings, in relative order to each other. The searches are performed starting from the beginning of the evaluated string. Example:: string_contains_in_order("bc", "fg", "jkl") will match "abcdefghijklm". """ return StringContainsInOrder(*substrings) ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/hamcrest/library/text/stringendswith.py ================================================ from hamcrest.library.text.substringmatcher import SubstringMatcher from hamcrest.core.helpers.hasmethod import hasmethod __author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" class StringEndsWith(SubstringMatcher): def __init__(self, substring): super(StringEndsWith, self).__init__(substring) def _matches(self, item): if not hasmethod(item, 'endswith'): return False return item.endswith(self.substring) def relationship(self): return 'ending with' def ends_with(string): """Matches if object is a string ending with a given string. :param string: The string to search for. This matcher first checks whether the evaluated object is a string. If so, it checks if ``string`` matches the ending characters of the evaluated object. Example:: ends_with("bar") will match "foobar". """ return StringEndsWith(string) ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/hamcrest/library/text/stringmatches.py ================================================ __author__ = "Chris Rose" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" import re import six from hamcrest.core.base_matcher import BaseMatcher from hamcrest.core.helpers.hasmethod import hasmethod class StringMatchesPattern(BaseMatcher): def __init__(self, pattern): self.pattern = pattern def describe_to(self, description): description.append_text("a string matching '") \ .append_text(self.pattern.pattern) \ .append_text("'") def _matches(self, item): return self.pattern.search(item) is not None def matches_regexp(pattern): """Matches if object is a string containing a match for a given regular expression. :param pattern: The regular expression to search for. This matcher first checks whether the evaluated object is a string. If so, it checks if the regular expression ``pattern`` matches anywhere within the evaluated object. """ if isinstance(pattern, six.string_types): pattern = re.compile(pattern) return StringMatchesPattern(pattern) ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/hamcrest/library/text/stringstartswith.py ================================================ __author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" from hamcrest.library.text.substringmatcher import SubstringMatcher from hamcrest.core.helpers.hasmethod import hasmethod class StringStartsWith(SubstringMatcher): def __init__(self, substring): super(StringStartsWith, self).__init__(substring) def _matches(self, item): if not hasmethod(item, 'startswith'): return False return item.startswith(self.substring) def relationship(self): return 'starting with' def starts_with(substring): """Matches if object is a string starting with a given string. :param string: The string to search for. This matcher first checks whether the evaluated object is a string. If so, it checks if ``string`` matches the beginning characters of the evaluated object. Example:: starts_with("foo") will match "foobar". """ return StringStartsWith(substring) ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/hamcrest/library/text/substringmatcher.py ================================================ __author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" from hamcrest.core.base_matcher import BaseMatcher import six class SubstringMatcher(BaseMatcher): def __init__(self, substring): if not isinstance(substring, six.string_types): raise TypeError(self.__class__.__name__ + ' requires string') self.substring = substring def describe_to(self, description): description.append_text('a string ') \ .append_text(self.relationship()) \ .append_text(' ') \ .append_description_of(self.substring) ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/hyperlink/__init__.py ================================================ from ._url import (URL, parse, EncodedURL, DecodedURL, URLParseError, register_scheme) __all__ = [ "URL", "parse", "EncodedURL", "DecodedURL", "URLParseError", "register_scheme", ] ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/hyperlink/_url.py ================================================ # -*- coding: utf-8 -*- u"""Hyperlink provides Pythonic URL parsing, construction, and rendering. Usage is straightforward:: >>> from hyperlink import URL >>> url = URL.from_text(u'http://github.com/mahmoud/hyperlink?utm_source=docs') >>> url.host u'github.com' >>> secure_url = url.replace(scheme=u'https') >>> secure_url.get('utm_source')[0] u'docs' As seen here, the API revolves around the lightweight and immutable :class:`URL` type, documented below. """ import re import sys import string import socket from unicodedata import normalize try: from socket import inet_pton except ImportError: inet_pton = None # defined below try: from collections.abc import Mapping except ImportError: # Python 2 from collections import Mapping # Note: IDNAError is a subclass of UnicodeError from idna import encode as idna_encode, decode as idna_decode, IDNAError if inet_pton is None: # based on https://gist.github.com/nnemkin/4966028 # this code only applies on Windows Python 2.7 import ctypes class _sockaddr(ctypes.Structure): _fields_ = [("sa_family", ctypes.c_short), ("__pad1", ctypes.c_ushort), ("ipv4_addr", ctypes.c_byte * 4), ("ipv6_addr", ctypes.c_byte * 16), ("__pad2", ctypes.c_ulong)] WSAStringToAddressA = ctypes.windll.ws2_32.WSAStringToAddressA WSAAddressToStringA = ctypes.windll.ws2_32.WSAAddressToStringA def inet_pton(address_family, ip_string): addr = _sockaddr() ip_string = ip_string.encode('ascii') addr.sa_family = address_family addr_size = ctypes.c_int(ctypes.sizeof(addr)) if WSAStringToAddressA(ip_string, address_family, None, ctypes.byref(addr), ctypes.byref(addr_size)) != 0: raise socket.error(ctypes.FormatError()) if address_family == socket.AF_INET: return ctypes.string_at(addr.ipv4_addr, 4) if address_family == socket.AF_INET6: return ctypes.string_at(addr.ipv6_addr, 16) raise socket.error('unknown address family') PY2 = (sys.version_info[0] == 2) unicode = type(u'') try: unichr except NameError: unichr = chr # py3 NoneType = type(None) # from boltons.typeutils def make_sentinel(name='_MISSING', var_name=None): """Creates and returns a new **instance** of a new class, suitable for usage as a "sentinel", a kind of singleton often used to indicate a value is missing when ``None`` is a valid input. Args: name (str): Name of the Sentinel var_name (str): Set this name to the name of the variable in its respective module enable pickleability. >>> make_sentinel(var_name='_MISSING') _MISSING The most common use cases here in boltons are as default values for optional function arguments, partly because of its less-confusing appearance in automatically generated documentation. Sentinels also function well as placeholders in queues and linked lists. .. note:: By design, additional calls to ``make_sentinel`` with the same values will not produce equivalent objects. >>> make_sentinel('TEST') == make_sentinel('TEST') False >>> type(make_sentinel('TEST')) == type(make_sentinel('TEST')) False """ class Sentinel(object): def __init__(self): self.name = name self.var_name = var_name def __repr__(self): if self.var_name: return self.var_name return '%s(%r)' % (self.__class__.__name__, self.name) if var_name: def __reduce__(self): return self.var_name def __nonzero__(self): return False __bool__ = __nonzero__ return Sentinel() _unspecified = _UNSET = make_sentinel('_UNSET') # RFC 3986 Section 2.3, Unreserved URI Characters # https://tools.ietf.org/html/rfc3986#section-2.3 _UNRESERVED_CHARS = frozenset('~-._0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz') # URL parsing regex (based on RFC 3986 Appendix B, with modifications) _URL_RE = re.compile(r'^((?P[^:/?#]+):)?' r'((?P<_netloc_sep>//)' r'(?P[^/?#]*))?' r'(?P[^?#]*)' r'(\?(?P[^#]*))?' r'(#(?P.*))?$') _SCHEME_RE = re.compile(r'^[a-zA-Z0-9+-.]*$') _AUTHORITY_RE = re.compile(r'^(?:(?P[^@/?#]*)@)?' r'(?P' r'(?:\[(?P[^[\]/?#]*)\])' r'|(?P[^:/?#[\]]*)' r'|(?P.*?))?' r'(?::(?P.*))?$') _HEX_CHAR_MAP = dict([((a + b).encode('ascii'), unichr(int(a + b, 16)).encode('charmap')) for a in string.hexdigits for b in string.hexdigits]) _ASCII_RE = re.compile('([\x00-\x7f]+)') # RFC 3986 section 2.2, Reserved Characters # https://tools.ietf.org/html/rfc3986#section-2.2 _GEN_DELIMS = frozenset(u':/?#[]@') _SUB_DELIMS = frozenset(u"!$&'()*+,;=") _ALL_DELIMS = _GEN_DELIMS | _SUB_DELIMS _USERINFO_SAFE = _UNRESERVED_CHARS | _SUB_DELIMS | set(u'%') _USERINFO_DELIMS = _ALL_DELIMS - _USERINFO_SAFE _PATH_SAFE = _USERINFO_SAFE | set(u':@') _PATH_DELIMS = _ALL_DELIMS - _PATH_SAFE _SCHEMELESS_PATH_SAFE = _PATH_SAFE - set(':') _SCHEMELESS_PATH_DELIMS = _ALL_DELIMS - _SCHEMELESS_PATH_SAFE _FRAGMENT_SAFE = _UNRESERVED_CHARS | _PATH_SAFE | set(u'/?') _FRAGMENT_DELIMS = _ALL_DELIMS - _FRAGMENT_SAFE _QUERY_VALUE_SAFE = _UNRESERVED_CHARS | _FRAGMENT_SAFE - set(u'&+') _QUERY_VALUE_DELIMS = _ALL_DELIMS - _QUERY_VALUE_SAFE _QUERY_KEY_SAFE = _UNRESERVED_CHARS | _QUERY_VALUE_SAFE - set(u'=') _QUERY_KEY_DELIMS = _ALL_DELIMS - _QUERY_KEY_SAFE def _make_decode_map(delims, allow_percent=False): ret = dict(_HEX_CHAR_MAP) if not allow_percent: delims = set(delims) | set([u'%']) for delim in delims: _hexord = '{0:02X}'.format(ord(delim)).encode('ascii') _hexord_lower = _hexord.lower() ret.pop(_hexord) if _hexord != _hexord_lower: ret.pop(_hexord_lower) return ret def _make_quote_map(safe_chars): ret = {} # v is included in the dict for py3 mostly, because bytestrings # are iterables of ints, of course! for i, v in zip(range(256), range(256)): c = chr(v) if c in safe_chars: ret[c] = ret[v] = c else: ret[c] = ret[v] = '%{0:02X}'.format(i) return ret _USERINFO_PART_QUOTE_MAP = _make_quote_map(_USERINFO_SAFE) _USERINFO_DECODE_MAP = _make_decode_map(_USERINFO_DELIMS) _PATH_PART_QUOTE_MAP = _make_quote_map(_PATH_SAFE) _SCHEMELESS_PATH_PART_QUOTE_MAP = _make_quote_map(_SCHEMELESS_PATH_SAFE) _PATH_DECODE_MAP = _make_decode_map(_PATH_DELIMS) _QUERY_KEY_QUOTE_MAP = _make_quote_map(_QUERY_KEY_SAFE) _QUERY_KEY_DECODE_MAP = _make_decode_map(_QUERY_KEY_DELIMS) _QUERY_VALUE_QUOTE_MAP = _make_quote_map(_QUERY_VALUE_SAFE) _QUERY_VALUE_DECODE_MAP = _make_decode_map(_QUERY_VALUE_DELIMS) _FRAGMENT_QUOTE_MAP = _make_quote_map(_FRAGMENT_SAFE) _FRAGMENT_DECODE_MAP = _make_decode_map(_FRAGMENT_DELIMS) _UNRESERVED_QUOTE_MAP = _make_quote_map(_UNRESERVED_CHARS) _UNRESERVED_DECODE_MAP = dict([(k, v) for k, v in _HEX_CHAR_MAP.items() if v.decode('ascii', 'replace') in _UNRESERVED_CHARS]) _ROOT_PATHS = frozenset(((), (u'',))) def _encode_reserved(text, maximal=True): """A very comprehensive percent encoding for encoding all delimiters. Used for arguments to DecodedURL, where a % means a percent sign, and not the character used by URLs for escaping bytes. """ if maximal: bytestr = normalize('NFC', text).encode('utf8') return u''.join([_UNRESERVED_QUOTE_MAP[b] for b in bytestr]) return u''.join([_UNRESERVED_QUOTE_MAP[t] if t in _UNRESERVED_CHARS else t for t in text]) def _encode_path_part(text, maximal=True): "Percent-encode a single segment of a URL path." if maximal: bytestr = normalize('NFC', text).encode('utf8') return u''.join([_PATH_PART_QUOTE_MAP[b] for b in bytestr]) return u''.join([_PATH_PART_QUOTE_MAP[t] if t in _PATH_DELIMS else t for t in text]) def _encode_schemeless_path_part(text, maximal=True): """Percent-encode the first segment of a URL path for a URL without a scheme specified. """ if maximal: bytestr = normalize('NFC', text).encode('utf8') return u''.join([_SCHEMELESS_PATH_PART_QUOTE_MAP[b] for b in bytestr]) return u''.join([_SCHEMELESS_PATH_PART_QUOTE_MAP[t] if t in _SCHEMELESS_PATH_DELIMS else t for t in text]) def _encode_path_parts(text_parts, rooted=False, has_scheme=True, has_authority=True, joined=True, maximal=True): """ Percent-encode a tuple of path parts into a complete path. Setting *maximal* to False percent-encodes only the reserved characters that are syntactically necessary for serialization, preserving any IRI-style textual data. Leaving *maximal* set to its default True percent-encodes everything required to convert a portion of an IRI to a portion of a URI. RFC 3986 3.3: If a URI contains an authority component, then the path component must either be empty or begin with a slash ("/") character. If a URI does not contain an authority component, then the path cannot begin with two slash characters ("//"). In addition, a URI reference (Section 4.1) may be a relative-path reference, in which case the first path segment cannot contain a colon (":") character. """ if not text_parts: return u'' if joined else text_parts if rooted: text_parts = (u'',) + text_parts # elif has_authority and text_parts: # raise Exception('see rfc above') # TODO: too late to fail like this? encoded_parts = [] if has_scheme: encoded_parts = [_encode_path_part(part, maximal=maximal) if part else part for part in text_parts] else: encoded_parts = [_encode_schemeless_path_part(text_parts[0])] encoded_parts.extend([_encode_path_part(part, maximal=maximal) if part else part for part in text_parts[1:]]) if joined: return u'/'.join(encoded_parts) return tuple(encoded_parts) def _encode_query_key(text, maximal=True): """ Percent-encode a single query string key or value. """ if maximal: bytestr = normalize('NFC', text).encode('utf8') return u''.join([_QUERY_KEY_QUOTE_MAP[b] for b in bytestr]) return u''.join([_QUERY_KEY_QUOTE_MAP[t] if t in _QUERY_KEY_DELIMS else t for t in text]) def _encode_query_value(text, maximal=True): """ Percent-encode a single query string key or value. """ if maximal: bytestr = normalize('NFC', text).encode('utf8') return u''.join([_QUERY_VALUE_QUOTE_MAP[b] for b in bytestr]) return u''.join([_QUERY_VALUE_QUOTE_MAP[t] if t in _QUERY_VALUE_DELIMS else t for t in text]) def _encode_fragment_part(text, maximal=True): """Quote the fragment part of the URL. Fragments don't have subdelimiters, so the whole URL fragment can be passed. """ if maximal: bytestr = normalize('NFC', text).encode('utf8') return u''.join([_FRAGMENT_QUOTE_MAP[b] for b in bytestr]) return u''.join([_FRAGMENT_QUOTE_MAP[t] if t in _FRAGMENT_DELIMS else t for t in text]) def _encode_userinfo_part(text, maximal=True): """Quote special characters in either the username or password section of the URL. """ if maximal: bytestr = normalize('NFC', text).encode('utf8') return u''.join([_USERINFO_PART_QUOTE_MAP[b] for b in bytestr]) return u''.join([_USERINFO_PART_QUOTE_MAP[t] if t in _USERINFO_DELIMS else t for t in text]) # This port list painstakingly curated by hand searching through # https://www.iana.org/assignments/uri-schemes/uri-schemes.xhtml # and # https://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.xhtml SCHEME_PORT_MAP = {'acap': 674, 'afp': 548, 'dict': 2628, 'dns': 53, 'file': None, 'ftp': 21, 'git': 9418, 'gopher': 70, 'http': 80, 'https': 443, 'imap': 143, 'ipp': 631, 'ipps': 631, 'irc': 194, 'ircs': 6697, 'ldap': 389, 'ldaps': 636, 'mms': 1755, 'msrp': 2855, 'msrps': None, 'mtqp': 1038, 'nfs': 111, 'nntp': 119, 'nntps': 563, 'pop': 110, 'prospero': 1525, 'redis': 6379, 'rsync': 873, 'rtsp': 554, 'rtsps': 322, 'rtspu': 5005, 'sftp': 22, 'smb': 445, 'snmp': 161, 'ssh': 22, 'steam': None, 'svn': 3690, 'telnet': 23, 'ventrilo': 3784, 'vnc': 5900, 'wais': 210, 'ws': 80, 'wss': 443, 'xmpp': None} # This list of schemes that don't use authorities is also from the link above. NO_NETLOC_SCHEMES = set(['urn', 'about', 'bitcoin', 'blob', 'data', 'geo', 'magnet', 'mailto', 'news', 'pkcs11', 'sip', 'sips', 'tel']) # As of Mar 11, 2017, there were 44 netloc schemes, and 13 non-netloc def register_scheme(text, uses_netloc=True, default_port=None): """Registers new scheme information, resulting in correct port and slash behavior from the URL object. There are dozens of standard schemes preregistered, so this function is mostly meant for proprietary internal customizations or stopgaps on missing standards information. If a scheme seems to be missing, please `file an issue`_! Args: text (unicode): Text representing the scheme. (the 'http' in 'http://hatnote.com') uses_netloc (bool): Does the scheme support specifying a network host? For instance, "http" does, "mailto" does not. Defaults to True. default_port (int): The default port, if any, for netloc-using schemes. .. _file an issue: https://github.com/mahmoud/hyperlink/issues """ text = text.lower() if default_port is not None: try: default_port = int(default_port) except (ValueError, TypeError): raise ValueError('default_port expected integer or None, not %r' % (default_port,)) if uses_netloc is True: SCHEME_PORT_MAP[text] = default_port elif uses_netloc is False: if default_port is not None: raise ValueError('unexpected default port while specifying' ' non-netloc scheme: %r' % default_port) NO_NETLOC_SCHEMES.add(text) else: raise ValueError('uses_netloc expected bool, not: %r' % uses_netloc) return def scheme_uses_netloc(scheme, default=None): """Whether or not a URL uses :code:`:` or :code:`://` to separate the scheme from the rest of the URL depends on the scheme's own standard definition. There is no way to infer this behavior from other parts of the URL. A scheme either supports network locations or it does not. The URL type's approach to this is to check for explicitly registered schemes, with common schemes like HTTP preregistered. This is the same approach taken by :mod:`urlparse`. URL adds two additional heuristics if the scheme as a whole is not registered. First, it attempts to check the subpart of the scheme after the last ``+`` character. This adds intuitive behavior for schemes like ``git+ssh``. Second, if a URL with an unrecognized scheme is loaded, it will maintain the separator it sees. """ if not scheme: return False scheme = scheme.lower() if scheme in SCHEME_PORT_MAP: return True if scheme in NO_NETLOC_SCHEMES: return False if scheme.split('+')[-1] in SCHEME_PORT_MAP: return True return default class URLParseError(ValueError): """Exception inheriting from :exc:`ValueError`, raised when failing to parse a URL. Mostly raised on invalid ports and IPv6 addresses. """ pass def _optional(argument, default): if argument is _UNSET: return default else: return argument def _typecheck(name, value, *types): """ Check that the given *value* is one of the given *types*, or raise an exception describing the problem using *name*. """ if not types: raise ValueError('expected one or more types, maybe use _textcheck?') if not isinstance(value, types): raise TypeError("expected %s for %s, got %r" % (" or ".join([t.__name__ for t in types]), name, value)) return value def _textcheck(name, value, delims=frozenset(), nullable=False): if not isinstance(value, unicode): if nullable and value is None: return value # used by query string values else: str_name = "unicode" if PY2 else "str" exp = str_name + ' or NoneType' if nullable else str_name raise TypeError('expected %s for %s, got %r' % (exp, name, value)) if delims and set(value) & set(delims): # TODO: test caching into regexes raise ValueError('one or more reserved delimiters %s present in %s: %r' % (''.join(delims), name, value)) return value def iter_pairs(iterable): """ Iterate over the (key, value) pairs in ``iterable``. This handles dictionaries sensibly, and falls back to assuming the iterable yields (key, value) pairs. This behaviour is similar to what Python's ``dict()`` constructor does. """ if isinstance(iterable, Mapping): iterable = iterable.items() return iter(iterable) def _decode_unreserved(text, normalize_case=False, encode_stray_percents=False): return _percent_decode(text, normalize_case=normalize_case, encode_stray_percents=encode_stray_percents, _decode_map=_UNRESERVED_DECODE_MAP) def _decode_userinfo_part(text, normalize_case=False, encode_stray_percents=False): return _percent_decode(text, normalize_case=normalize_case, encode_stray_percents=encode_stray_percents, _decode_map=_USERINFO_DECODE_MAP) def _decode_path_part(text, normalize_case=False, encode_stray_percents=False): """ >>> _decode_path_part(u'%61%77%2f%7a') u'aw%2fz' >>> _decode_path_part(u'%61%77%2f%7a', normalize_case=True) u'aw%2Fz' """ return _percent_decode(text, normalize_case=normalize_case, encode_stray_percents=encode_stray_percents, _decode_map=_PATH_DECODE_MAP) def _decode_query_key(text, normalize_case=False, encode_stray_percents=False): return _percent_decode(text, normalize_case=normalize_case, encode_stray_percents=encode_stray_percents, _decode_map=_QUERY_KEY_DECODE_MAP) def _decode_query_value(text, normalize_case=False, encode_stray_percents=False): return _percent_decode(text, normalize_case=normalize_case, encode_stray_percents=encode_stray_percents, _decode_map=_QUERY_VALUE_DECODE_MAP) def _decode_fragment_part(text, normalize_case=False, encode_stray_percents=False): return _percent_decode(text, normalize_case=normalize_case, encode_stray_percents=encode_stray_percents, _decode_map=_FRAGMENT_DECODE_MAP) def _percent_decode(text, normalize_case=False, subencoding='utf-8', raise_subencoding_exc=False, encode_stray_percents=False, _decode_map=_HEX_CHAR_MAP): """Convert percent-encoded text characters to their normal, human-readable equivalents. All characters in the input text must be encodable by *subencoding*. All special characters underlying the values in the percent-encoding must be decodable as *subencoding*. If a non-*subencoding*-valid string is passed, the original text is returned with no changes applied. Only called by field-tailored variants, e.g., :func:`_decode_path_part`, as every percent-encodable part of the URL has characters which should not be percent decoded. >>> _percent_decode(u'abc%20def') u'abc def' Args: text (unicode): Text with percent-encoding present. normalize_case (bool): Whether undecoded percent segments, such as encoded delimiters, should be uppercased, per RFC 3986 Section 2.1. See :func:`_decode_path_part` for an example. subencoding (unicode): The name of the encoding underlying the percent-encoding. Pass `False` to get back raw bytes. raise_subencoding_exc (bool): Whether an error in decoding the bytes underlying the percent-decoding should be raised. Returns: unicode: The percent-decoded version of *text*, decoded by *subencoding*, unless `subencoding=False` which returns bytes. """ try: quoted_bytes = text.encode('utf-8' if subencoding is False else subencoding) except UnicodeEncodeError: return text bits = quoted_bytes.split(b'%') if len(bits) == 1: return text res = [bits[0]] append = res.append for item in bits[1:]: hexpair, rest = item[:2], item[2:] try: append(_decode_map[hexpair]) append(rest) except KeyError: pair_is_hex = hexpair in _HEX_CHAR_MAP if pair_is_hex or not encode_stray_percents: append(b'%') else: # if it's undecodable, treat as a real percent sign, # which is reserved (because it wasn't in the # context-aware _decode_map passed in), and should # stay in an encoded state. append(b'%25') if normalize_case and pair_is_hex: append(hexpair.upper()) append(rest) else: append(item) unquoted_bytes = b''.join(res) if subencoding is False: return unquoted_bytes try: return unquoted_bytes.decode(subencoding) except UnicodeDecodeError: if raise_subencoding_exc: raise return text def _decode_host(host): """Decode a host from ASCII-encodable text to IDNA-decoded text. If the host text is not ASCII, it is returned unchanged, as it is presumed that it is already IDNA-decoded. Some technical details: _decode_host is built on top of the "idna" package, which has some quirks: Capital letters are not valid IDNA2008. The idna package will raise an exception like this on capital letters: > idna.core.InvalidCodepoint: Codepoint U+004B at position 1 ... not allowed However, if a segment of a host (i.e., something in url.host.split('.')) is already ASCII, idna doesn't perform its usual checks. In fact, for capital letters it automatically lowercases them. This check and some other functionality can be bypassed by passing uts46=True to idna.encode/decode. This allows a more permissive and convenient interface. So far it seems like the balanced approach. Example output (from idna==2.6): >> idna.encode(u'mahmöud.io') 'xn--mahmud-zxa.io' >> idna.encode(u'Mahmöud.io') Traceback (most recent call last): File "", line 1, in File "/home/mahmoud/virtualenvs/hyperlink/local/lib/python2.7/site-packages/idna/core.py", line 355, in encode result.append(alabel(label)) File "/home/mahmoud/virtualenvs/hyperlink/local/lib/python2.7/site-packages/idna/core.py", line 276, in alabel check_label(label) File "/home/mahmoud/virtualenvs/hyperlink/local/lib/python2.7/site-packages/idna/core.py", line 253, in check_label raise InvalidCodepoint('Codepoint {0} at position {1} of {2} not allowed'.format(_unot(cp_value), pos+1, repr(label))) idna.core.InvalidCodepoint: Codepoint U+004D at position 1 of u'Mahm\xf6ud' not allowed >> idna.encode(u'Mahmoud.io') 'Mahmoud.io' # Similar behavior for decodes below >> idna.decode(u'Mahmoud.io') u'mahmoud.io >> idna.decode(u'Méhmoud.io', uts46=True) u'm\xe9hmoud.io' """ if not host: return u'' try: host_bytes = host.encode("ascii") except UnicodeEncodeError: host_text = host else: try: host_text = idna_decode(host_bytes, uts46=True) except ValueError: # only reached on "narrow" (UCS-2) Python builds <3.4, see #7 # NOTE: not going to raise here, because there's no # ambiguity in the IDNA, and the host is still # technically usable host_text = host return host_text def _resolve_dot_segments(path): """Normalize the URL path by resolving segments of '.' and '..'. For more details, see `RFC 3986 section 5.2.4, Remove Dot Segments`_. Args: path (list): path segments in string form Returns: list: a new list of path segments with the '.' and '..' elements removed and resolved. .. _RFC 3986 section 5.2.4, Remove Dot Segments: https://tools.ietf.org/html/rfc3986#section-5.2.4 """ segs = [] for seg in path: if seg == u'.': pass elif seg == u'..': if segs: segs.pop() else: segs.append(seg) if list(path[-1:]) in ([u'.'], [u'..']): segs.append(u'') return segs def parse_host(host): """Parse the host into a tuple of ``(family, host)``, where family is the appropriate :mod:`socket` module constant when the host is an IP address. Family is ``None`` when the host is not an IP. Will raise :class:`URLParseError` on invalid IPv6 constants. Returns: tuple: family (socket constant or None), host (string) >>> parse_host('googlewebsite.com') == (None, 'googlewebsite.com') True >>> parse_host('::1') == (socket.AF_INET6, '::1') True >>> parse_host('192.168.1.1') == (socket.AF_INET, '192.168.1.1') True """ if not host: return None, u'' if u':' in host: try: inet_pton(socket.AF_INET6, host) except socket.error as se: raise URLParseError('invalid IPv6 host: %r (%r)' % (host, se)) except UnicodeEncodeError: pass # TODO: this can't be a real host right? else: family = socket.AF_INET6 return family, host try: inet_pton(socket.AF_INET, host) except (socket.error, UnicodeEncodeError): family = None # not an IP else: family = socket.AF_INET return family, host class URL(object): """From blogs to billboards, URLs are so common, that it's easy to overlook their complexity and power. With hyperlink's :class:`URL` type, working with URLs doesn't have to be hard. URLs are made of many parts. Most of these parts are officially named in `RFC 3986`_ and this diagram may prove handy in identifying them:: foo://user:pass@example.com:8042/over/there?name=ferret#nose \_/ \_______/ \_________/ \__/\_________/ \_________/ \__/ | | | | | | | scheme userinfo host port path query fragment While :meth:`~URL.from_text` is used for parsing whole URLs, the :class:`URL` constructor builds a URL from the individual components, like so:: >>> from hyperlink import URL >>> url = URL(scheme=u'https', host=u'example.com', path=[u'hello', u'world']) >>> print(url.to_text()) https://example.com/hello/world The constructor runs basic type checks. All strings are expected to be decoded (:class:`unicode` in Python 2). All arguments are optional, defaulting to appropriately empty values. A full list of constructor arguments is below. Args: scheme (unicode): The text name of the scheme. host (unicode): The host portion of the network location port (int): The port part of the network location. If ``None`` or no port is passed, the port will default to the default port of the scheme, if it is known. See the ``SCHEME_PORT_MAP`` and :func:`register_default_port` for more info. path (tuple): A tuple of strings representing the slash-separated parts of the path. query (tuple): The query parameters, as a dictionary or as an iterable of key-value pairs. fragment (unicode): The fragment part of the URL. rooted (bool): Whether or not the path begins with a slash. userinfo (unicode): The username or colon-separated username:password pair. uses_netloc (bool): Indicates whether two slashes appear between the scheme and the host (``http://eg.com`` vs ``mailto:e@g.com``). Set automatically based on scheme. All of these parts are also exposed as read-only attributes of URL instances, along with several useful methods. .. _RFC 3986: https://tools.ietf.org/html/rfc3986 .. _RFC 3987: https://tools.ietf.org/html/rfc3987 """ def __init__(self, scheme=None, host=None, path=(), query=(), fragment=u'', port=None, rooted=None, userinfo=u'', uses_netloc=None): if host is not None and scheme is None: scheme = u'http' # TODO: why if port is None: port = SCHEME_PORT_MAP.get(scheme) if host and query and not path: # per RFC 3986 6.2.3, "a URI that uses the generic syntax # for authority with an empty path should be normalized to # a path of '/'." path = (u'',) # Now that we're done detecting whether they were passed, we can set # them to their defaults: if scheme is None: scheme = u'' if host is None: host = u'' if rooted is None: rooted = bool(host) # Set attributes. self._scheme = _textcheck("scheme", scheme) if self._scheme: if not _SCHEME_RE.match(self._scheme): raise ValueError('invalid scheme: %r. Only alphanumeric, "+",' ' "-", and "." allowed. Did you meant to call' ' %s.from_text()?' % (self._scheme, self.__class__.__name__)) _, self._host = parse_host(_textcheck('host', host, '/?#@')) if isinstance(path, unicode): raise TypeError("expected iterable of text for path, not: %r" % (path,)) self._path = tuple((_textcheck("path segment", segment, '/?#') for segment in path)) self._query = tuple( (_textcheck("query parameter name", k, '&=#'), _textcheck("query parameter value", v, '&#', nullable=True)) for k, v in iter_pairs(query)) self._fragment = _textcheck("fragment", fragment) self._port = _typecheck("port", port, int, NoneType) self._rooted = _typecheck("rooted", rooted, bool) self._userinfo = _textcheck("userinfo", userinfo, '/?#@') uses_netloc = scheme_uses_netloc(self._scheme, uses_netloc) self._uses_netloc = _typecheck("uses_netloc", uses_netloc, bool, NoneType) return def get_decoded_url(self, lazy=False): try: return self._decoded_url except AttributeError: self._decoded_url = DecodedURL(self, lazy=lazy) return self._decoded_url @property def scheme(self): """The scheme is a string, and the first part of an absolute URL, the part before the first colon, and the part which defines the semantics of the rest of the URL. Examples include "http", "https", "ssh", "file", "mailto", and many others. See :func:`~hyperlink.register_scheme()` for more info. """ return self._scheme @property def host(self): """The host is a string, and the second standard part of an absolute URL. When present, a valid host must be a domain name, or an IP (v4 or v6). It occurs before the first slash, or the second colon, if a :attr:`~hyperlink.URL.port` is provided. """ return self._host @property def port(self): """The port is an integer that is commonly used in connecting to the :attr:`host`, and almost never appears without it. When not present in the original URL, this attribute defaults to the scheme's default port. If the scheme's default port is not known, and the port is not provided, this attribute will be set to None. >>> URL.from_text(u'http://example.com/pa/th').port 80 >>> URL.from_text(u'foo://example.com/pa/th').port >>> URL.from_text(u'foo://example.com:8042/pa/th').port 8042 .. note:: Per the standard, when the port is the same as the schemes default port, it will be omitted in the text URL. """ return self._port @property def path(self): """A tuple of strings, created by splitting the slash-separated hierarchical path. Started by the first slash after the host, terminated by a "?", which indicates the start of the :attr:`~hyperlink.URL.query` string. """ return self._path @property def query(self): """Tuple of pairs, created by splitting the ampersand-separated mapping of keys and optional values representing non-hierarchical data used to identify the resource. Keys are always strings. Values are strings when present, or None when missing. For more operations on the mapping, see :meth:`~hyperlink.URL.get()`, :meth:`~hyperlink.URL.add()`, :meth:`~hyperlink.URL.set()`, and :meth:`~hyperlink.URL.delete()`. """ return self._query @property def fragment(self): """A string, the last part of the URL, indicated by the first "#" after the :attr:`~hyperlink.URL.path` or :attr:`~hyperlink.URL.query`. Enables indirect identification of a secondary resource, like an anchor within an HTML page. """ return self._fragment @property def rooted(self): """Whether or not the path starts with a forward slash (``/``). This is taken from the terminology in the BNF grammar, specifically the "path-rootless", rule, since "absolute path" and "absolute URI" are somewhat ambiguous. :attr:`path` does not contain the implicit prefixed ``"/"`` since that is somewhat awkward to work with. """ return self._rooted @property def userinfo(self): """The colon-separated string forming the username-password combination. """ return self._userinfo @property def uses_netloc(self): """ """ return self._uses_netloc @property def user(self): """ The user portion of :attr:`~hyperlink.URL.userinfo`. """ return self.userinfo.split(u':')[0] def authority(self, with_password=False, **kw): """Compute and return the appropriate host/port/userinfo combination. >>> url = URL.from_text(u'http://user:pass@localhost:8080/a/b?x=y') >>> url.authority() u'user:@localhost:8080' >>> url.authority(with_password=True) u'user:pass@localhost:8080' Args: with_password (bool): Whether the return value of this method include the password in the URL, if it is set. Defaults to False. Returns: str: The authority (network location and user information) portion of the URL. """ # first, a bit of twisted compat with_password = kw.pop('includeSecrets', with_password) if kw: raise TypeError('got unexpected keyword arguments: %r' % kw.keys()) host = self.host if ':' in host: hostport = ['[' + host + ']'] else: hostport = [self.host] if self.port != SCHEME_PORT_MAP.get(self.scheme): hostport.append(unicode(self.port)) authority = [] if self.userinfo: userinfo = self.userinfo if not with_password and u":" in userinfo: userinfo = userinfo[:userinfo.index(u":") + 1] authority.append(userinfo) authority.append(u":".join(hostport)) return u"@".join(authority) def __eq__(self, other): if not isinstance(other, self.__class__): return NotImplemented for attr in ['scheme', 'userinfo', 'host', 'query', 'fragment', 'port', 'uses_netloc']: if getattr(self, attr) != getattr(other, attr): return False if self.path == other.path or (self.path in _ROOT_PATHS and other.path in _ROOT_PATHS): return True return False def __ne__(self, other): if not isinstance(other, self.__class__): return NotImplemented return not self.__eq__(other) def __hash__(self): return hash((self.__class__, self.scheme, self.userinfo, self.host, self.path, self.query, self.fragment, self.port, self.rooted, self.uses_netloc)) @property def absolute(self): """Whether or not the URL is "absolute". Absolute URLs are complete enough to resolve to a network resource without being relative to a base URI. >>> URL.from_text(u'http://wikipedia.org/').absolute True >>> URL.from_text(u'?a=b&c=d').absolute False Absolute URLs must have both a scheme and a host set. """ return bool(self.scheme and self.host) def replace(self, scheme=_UNSET, host=_UNSET, path=_UNSET, query=_UNSET, fragment=_UNSET, port=_UNSET, rooted=_UNSET, userinfo=_UNSET, uses_netloc=_UNSET): """:class:`URL` objects are immutable, which means that attributes are designed to be set only once, at construction. Instead of modifying an existing URL, one simply creates a copy with the desired changes. If any of the following arguments is omitted, it defaults to the value on the current URL. Args: scheme (unicode): The text name of the scheme. host (unicode): The host portion of the network location port (int): The port part of the network location. path (tuple): A tuple of strings representing the slash-separated parts of the path. query (tuple): The query parameters, as a tuple of key-value pairs. query (tuple): The query parameters, as a dictionary or as an iterable of key-value pairs. fragment (unicode): The fragment part of the URL. rooted (bool): Whether or not the path begins with a slash. userinfo (unicode): The username or colon-separated username:password pair. uses_netloc (bool): Indicates whether two slashes appear between the scheme and the host (``http://eg.com`` vs ``mailto:e@g.com``) Returns: URL: a copy of the current :class:`URL`, with new values for parameters passed. """ return self.__class__( scheme=_optional(scheme, self.scheme), host=_optional(host, self.host), path=_optional(path, self.path), query=_optional(query, self.query), fragment=_optional(fragment, self.fragment), port=_optional(port, self.port), rooted=_optional(rooted, self.rooted), userinfo=_optional(userinfo, self.userinfo), uses_netloc=_optional(uses_netloc, self.uses_netloc) ) @classmethod def from_text(cls, text): """Whereas the :class:`URL` constructor is useful for constructing URLs from parts, :meth:`~URL.from_text` supports parsing whole URLs from their string form:: >>> URL.from_text(u'http://example.com') URL.from_text(u'http://example.com') >>> URL.from_text(u'?a=b&x=y') URL.from_text(u'?a=b&x=y') As you can see above, it's also used as the :func:`repr` of :class:`URL` objects. The natural counterpart to :func:`~URL.to_text()`. This method only accepts *text*, so be sure to decode those bytestrings. Args: text (unicode): A valid URL string. Returns: URL: The structured object version of the parsed string. .. note:: Somewhat unexpectedly, URLs are a far more permissive format than most would assume. Many strings which don't look like URLs are still valid URLs. As a result, this method only raises :class:`URLParseError` on invalid port and IPv6 values in the host portion of the URL. """ um = _URL_RE.match(_textcheck('text', text)) try: gs = um.groupdict() except AttributeError: raise URLParseError('could not parse url: %r' % text) au_text = gs['authority'] or u'' au_m = _AUTHORITY_RE.match(au_text) try: au_gs = au_m.groupdict() except AttributeError: raise URLParseError('invalid authority %r in url: %r' % (au_text, text)) if au_gs['bad_host']: raise URLParseError('invalid host %r in url: %r' % (au_gs['bad_host'], text)) userinfo = au_gs['userinfo'] or u'' host = au_gs['ipv6_host'] or au_gs['plain_host'] port = au_gs['port'] if port is not None: try: port = int(port) except ValueError: if not port: # TODO: excessive? raise URLParseError('port must not be empty: %r' % au_text) raise URLParseError('expected integer for port, not %r' % port) scheme = gs['scheme'] or u'' fragment = gs['fragment'] or u'' uses_netloc = bool(gs['_netloc_sep']) if gs['path']: path = gs['path'].split(u"/") if not path[0]: path.pop(0) rooted = True else: rooted = False else: path = () rooted = bool(au_text) if gs['query']: query = ((qe.split(u"=", 1) if u'=' in qe else (qe, None)) for qe in gs['query'].split(u"&")) else: query = () return cls(scheme, host, path, query, fragment, port, rooted, userinfo, uses_netloc) def normalize(self, scheme=True, host=True, path=True, query=True, fragment=True, userinfo=True, percents=True): """Return a new URL object with several standard normalizations applied: * Decode unreserved characters (`RFC 3986 2.3`_) * Uppercase remaining percent-encoded octets (`RFC 3986 2.1`_) * Convert scheme and host casing to lowercase (`RFC 3986 3.2.2`_) * Resolve any "." and ".." references in the path (`RFC 3986 6.2.2.3`_) * Ensure an ending slash on URLs with an empty path (`RFC 3986 6.2.3`_) * Encode any stray percent signs (`%`) in percent-encoded fields (path, query, fragment, userinfo) (`RFC 3986 2.4`_) All are applied by default, but normalizations can be disabled per-part by passing `False` for that part's corresponding name. Args: scheme (bool): Convert the scheme to lowercase host (bool): Convert the host to lowercase path (bool): Normalize the path (see above for details) query (bool): Normalize the query string fragment (bool): Normalize the fragment userinfo (bool): Normalize the userinfo percents (bool): Encode isolated percent signs for any percent-encoded fields which are being normalized (defaults to True). >>> url = URL.from_text(u'Http://example.COM/a/../b/./c%2f?%61%') >>> print(url.normalize().to_text()) http://example.com/b/c%2F?a%25 .. _RFC 3986 3.2.2: https://tools.ietf.org/html/rfc3986#section-3.2.2 .. _RFC 3986 2.3: https://tools.ietf.org/html/rfc3986#section-2.3 .. _RFC 3986 2.1: https://tools.ietf.org/html/rfc3986#section-2.1 .. _RFC 3986 6.2.2.3: https://tools.ietf.org/html/rfc3986#section-6.2.2.3 .. _RFC 3986 6.2.3: https://tools.ietf.org/html/rfc3986#section-6.2.3 .. _RFC 3986 2.4: https://tools.ietf.org/html/rfc3986#section-2.4 """ kw = {} if scheme: kw['scheme'] = self.scheme.lower() if host: kw['host'] = self.host.lower() def _dec_unres(target): return _decode_unreserved(target, normalize_case=True, encode_stray_percents=percents) if path: if self.path: kw['path'] = [_dec_unres(p) for p in _resolve_dot_segments(self.path)] else: kw['path'] = (u'',) if query: kw['query'] = [(_dec_unres(k), _dec_unres(v) if v else v) for k, v in self.query] if fragment: kw['fragment'] = _dec_unres(self.fragment) if userinfo: kw['userinfo'] = u':'.join([_dec_unres(p) for p in self.userinfo.split(':', 1)]) return self.replace(**kw) def child(self, *segments): """Make a new :class:`URL` where the given path segments are a child of this URL, preserving other parts of the URL, including the query string and fragment. For example:: >>> url = URL.from_text(u'http://localhost/a/b?x=y') >>> child_url = url.child(u"c", u"d") >>> child_url.to_text() u'http://localhost/a/b/c/d?x=y' Args: segments (unicode): Additional parts to be joined and added to the path, like :func:`os.path.join`. Special characters in segments will be percent encoded. Returns: URL: A copy of the current URL with the extra path segments. """ if not segments: return self segments = [_textcheck('path segment', s) for s in segments] new_segs = _encode_path_parts(segments, joined=False, maximal=False) new_path = self.path[:-1 if (self.path and self.path[-1] == u'') else None] + new_segs return self.replace(path=new_path) def sibling(self, segment): """Make a new :class:`URL` with a single path segment that is a sibling of this URL path. Args: segment (unicode): A single path segment. Returns: URL: A copy of the current URL with the last path segment replaced by *segment*. Special characters such as ``/?#`` will be percent encoded. """ _textcheck('path segment', segment) new_path = self.path[:-1] + (_encode_path_part(segment),) return self.replace(path=new_path) def click(self, href=u''): """Resolve the given URL relative to this URL. The resulting URI should match what a web browser would generate if you visited the current URL and clicked on *href*. >>> url = URL.from_text(u'http://blog.hatnote.com/') >>> url.click(u'/post/155074058790').to_text() u'http://blog.hatnote.com/post/155074058790' >>> url = URL.from_text(u'http://localhost/a/b/c/') >>> url.click(u'../d/./e').to_text() u'http://localhost/a/b/d/e' Args: href (unicode): A string representing a clicked URL. Return: URL: A copy of the current URL with navigation logic applied. For more information, see `RFC 3986 section 5`_. .. _RFC 3986 section 5: https://tools.ietf.org/html/rfc3986#section-5 """ if href: if isinstance(href, URL): clicked = href else: # TODO: This error message is not completely accurate, # as URL objects are now also valid, but Twisted's # test suite (wrongly) relies on this exact message. _textcheck('relative URL', href) clicked = URL.from_text(href) if clicked.absolute: return clicked else: clicked = self query = clicked.query if clicked.scheme and not clicked.rooted: # Schemes with relative paths are not well-defined. RFC 3986 calls # them a "loophole in prior specifications" that should be avoided, # or supported only for backwards compatibility. raise NotImplementedError('absolute URI with rootless path: %r' % (href,)) else: if clicked.rooted: path = clicked.path elif clicked.path: path = self.path[:-1] + clicked.path else: path = self.path if not query: query = self.query return self.replace(scheme=clicked.scheme or self.scheme, host=clicked.host or self.host, port=clicked.port or self.port, path=_resolve_dot_segments(path), query=query, fragment=clicked.fragment) def to_uri(self): u"""Make a new :class:`URL` instance with all non-ASCII characters appropriately percent-encoded. This is useful to do in preparation for sending a :class:`URL` over a network protocol. For example:: >>> URL.from_text(u'https://ايران.com/foo⇧bar/').to_uri() URL.from_text(u'https://xn--mgba3a4fra.com/foo%E2%87%A7bar/') Returns: URL: A new instance with its path segments, query parameters, and hostname encoded, so that they are all in the standard US-ASCII range. """ new_userinfo = u':'.join([_encode_userinfo_part(p) for p in self.userinfo.split(':', 1)]) new_path = _encode_path_parts(self.path, has_scheme=bool(self.scheme), rooted=False, joined=False, maximal=True) new_host = self.host if not self.host else idna_encode(self.host, uts46=True).decode("ascii") return self.replace( userinfo=new_userinfo, host=new_host, path=new_path, query=tuple([(_encode_query_key(k, maximal=True), _encode_query_value(v, maximal=True) if v is not None else None) for k, v in self.query]), fragment=_encode_fragment_part(self.fragment, maximal=True) ) def to_iri(self): u"""Make a new :class:`URL` instance with all but a few reserved characters decoded into human-readable format. Percent-encoded Unicode and IDNA-encoded hostnames are decoded, like so:: >>> url = URL.from_text(u'https://xn--mgba3a4fra.example.com/foo%E2%87%A7bar/') >>> print(url.to_iri().to_text()) https://ايران.example.com/foo⇧bar/ .. note:: As a general Python issue, "narrow" (UCS-2) builds of Python may not be able to fully decode certain URLs, and the in those cases, this method will return a best-effort, partially-decoded, URL which is still valid. This issue does not affect any Python builds 3.4+. Returns: URL: A new instance with its path segments, query parameters, and hostname decoded for display purposes. """ new_userinfo = u':'.join([_decode_userinfo_part(p) for p in self.userinfo.split(':', 1)]) host_text = _decode_host(self.host) return self.replace(userinfo=new_userinfo, host=host_text, path=[_decode_path_part(segment) for segment in self.path], query=[(_decode_query_key(k), _decode_query_value(v) if v is not None else None) for k, v in self.query], fragment=_decode_fragment_part(self.fragment)) def to_text(self, with_password=False): """Render this URL to its textual representation. By default, the URL text will *not* include a password, if one is set. RFC 3986 considers using URLs to represent such sensitive information as deprecated. Quoting from RFC 3986, `section 3.2.1`: "Applications should not render as clear text any data after the first colon (":") character found within a userinfo subcomponent unless the data after the colon is the empty string (indicating no password)." Args: with_password (bool): Whether or not to include the password in the URL text. Defaults to False. Returns: str: The serialized textual representation of this URL, such as ``u"http://example.com/some/path?some=query"``. The natural counterpart to :class:`URL.from_text()`. .. _section 3.2.1: https://tools.ietf.org/html/rfc3986#section-3.2.1 """ scheme = self.scheme authority = self.authority(with_password) path = _encode_path_parts(self.path, rooted=self.rooted, has_scheme=bool(scheme), has_authority=bool(authority), maximal=False) query_parts = [] for k, v in self.query: if v is None: query_parts.append(_encode_query_key(k, maximal=False)) else: query_parts.append(u'='.join((_encode_query_key(k, maximal=False), _encode_query_value(v, maximal=False)))) query_string = u'&'.join(query_parts) fragment = self.fragment parts = [] _add = parts.append if scheme: _add(scheme) _add(':') if authority: _add('//') _add(authority) elif (scheme and path[:2] != '//' and self.uses_netloc): _add('//') if path: if scheme and authority and path[:1] != '/': _add('/') # relpaths with abs authorities auto get '/' _add(path) if query_string: _add('?') _add(query_string) if fragment: _add('#') _add(fragment) return u''.join(parts) def __repr__(self): """Convert this URL to an representation that shows all of its constituent parts, as well as being a valid argument to :func:`eval`. """ return '%s.from_text(%r)' % (self.__class__.__name__, self.to_text()) def _to_bytes(self): """ Allows for direct usage of URL objects with libraries like requests, which automatically stringify URL parameters. See issue #49. """ return self.to_uri().to_text().encode('ascii') if PY2: __str__ = _to_bytes __unicode__ = to_text else: __bytes__ = _to_bytes __str__ = to_text # # Begin Twisted Compat Code asURI = to_uri asIRI = to_iri @classmethod def fromText(cls, s): return cls.from_text(s) def asText(self, includeSecrets=False): return self.to_text(with_password=includeSecrets) def __dir__(self): try: ret = object.__dir__(self) except AttributeError: # object.__dir__ == AttributeError # pdw for py2 ret = dir(self.__class__) + list(self.__dict__.keys()) ret = sorted(set(ret) - set(['fromText', 'asURI', 'asIRI', 'asText'])) return ret # # End Twisted Compat Code def add(self, name, value=None): """Make a new :class:`URL` instance with a given query argument, *name*, added to it with the value *value*, like so:: >>> URL.from_text(u'https://example.com/?x=y').add(u'x') URL.from_text(u'https://example.com/?x=y&x') >>> URL.from_text(u'https://example.com/?x=y').add(u'x', u'z') URL.from_text(u'https://example.com/?x=y&x=z') Args: name (unicode): The name of the query parameter to add. The part before the ``=``. value (unicode): The value of the query parameter to add. The part after the ``=``. Defaults to ``None``, meaning no value. Returns: URL: A new :class:`URL` instance with the parameter added. """ return self.replace(query=self.query + ((name, value),)) def set(self, name, value=None): """Make a new :class:`URL` instance with the query parameter *name* set to *value*. All existing occurences, if any are replaced by the single name-value pair. >>> URL.from_text(u'https://example.com/?x=y').set(u'x') URL.from_text(u'https://example.com/?x') >>> URL.from_text(u'https://example.com/?x=y').set(u'x', u'z') URL.from_text(u'https://example.com/?x=z') Args: name (unicode): The name of the query parameter to set. The part before the ``=``. value (unicode): The value of the query parameter to set. The part after the ``=``. Defaults to ``None``, meaning no value. Returns: URL: A new :class:`URL` instance with the parameter set. """ # Preserve the original position of the query key in the list q = [(k, v) for (k, v) in self.query if k != name] idx = next((i for (i, (k, v)) in enumerate(self.query) if k == name), -1) q[idx:idx] = [(name, value)] return self.replace(query=q) def get(self, name): """Get a list of values for the given query parameter, *name*:: >>> url = URL.from_text(u'?x=1&x=2') >>> url.get('x') [u'1', u'2'] >>> url.get('y') [] If the given *name* is not set, an empty list is returned. A list is always returned, and this method raises no exceptions. Args: name (unicode): The name of the query parameter to get. Returns: list: A list of all the values associated with the key, in string form. """ return [value for (key, value) in self.query if name == key] def remove(self, name, value=_UNSET, limit=None): """Make a new :class:`URL` instance with occurrences of the query parameter *name* removed, or, if *value* is set, parameters matching *name* and *value*. No exception is raised if the parameter is not already set. Args: name (unicode): The name of the query parameter to remove. value (unicode): Optional value to additionally filter on. Setting this removes query parameters which match both name and value. limit (int): Optional maximum number of parameters to remove. Returns: URL: A new :class:`URL` instance with the parameter removed. """ if limit is None: if value is _UNSET: nq = [(k, v) for (k, v) in self.query if k != name] else: nq = [(k, v) for (k, v) in self.query if not (k == name and v == value)] else: nq, removed_count = [], 0 for k, v in self.query: if k == name and (value is _UNSET or v == value) and removed_count < limit: removed_count += 1 # drop it else: nq.append((k, v)) # keep it return self.replace(query=nq) EncodedURL = URL # An alias better describing what the URL really is class DecodedURL(object): """DecodedURL is a type meant to act as a higher-level interface to the URL. It is the `unicode` to URL's `bytes`. `DecodedURL` has almost exactly the same API as `URL`, but everything going in and out is in its maximally decoded state. All percent decoding is handled automatically. Where applicable, a UTF-8 encoding is presumed. Be advised that some interactions can raise :exc:`UnicodeEncodeErrors` and :exc:`UnicodeDecodeErrors`, just like when working with bytestrings. Examples of such interactions include handling query strings encoding binary data, and paths containing segments with special characters encoded with codecs other than UTF-8. Args: url (URL): A :class:`URL` object to wrap. lazy (bool): Set to True to avoid pre-decode all parts of the URL to check for validity. Defaults to False. """ def __init__(self, url, lazy=False): self._url = url if not lazy: # cache the following, while triggering any decoding # issues with decodable fields self.host, self.userinfo, self.path, self.query, self.fragment return @classmethod def from_text(cls, text, lazy=False): """\ Make a `DecodedURL` instance from any text string containing a URL. Args: text (unicode): Text containing the URL lazy (bool): Whether to pre-decode all parts of the URL to check for validity. Defaults to True. """ _url = URL.from_text(text) return cls(_url, lazy=lazy) @property def encoded_url(self): """Access the underlying :class:`URL` object, which has any special characters encoded. """ return self._url def to_text(self, *a, **kw): "Passthrough to :meth:`~hyperlink.URL.to_text()`" return self._url.to_text(*a, **kw) def to_uri(self, *a, **kw): "Passthrough to :meth:`~hyperlink.URL.to_uri()`" return self._url.to_uri(*a, **kw) def to_iri(self, *a, **kw): "Passthrough to :meth:`~hyperlink.URL.to_iri()`" return self._url.to_iri(*a, **kw) def click(self, href=u''): "Return a new DecodedURL wrapping the result of :meth:`~hyperlink.URL.click()`" if isinstance(href, DecodedURL): href = href._url return self.__class__(self._url.click(href=href)) def sibling(self, segment): """Automatically encode any reserved characters in *segment* and return a new `DecodedURL` wrapping the result of :meth:`~hyperlink.URL.sibling()` """ return self.__class__(self._url.sibling(_encode_reserved(segment))) def child(self, *segments): """Automatically encode any reserved characters in *segments* and return a new `DecodedURL` wrapping the result of :meth:`~hyperlink.URL.child()`. """ if not segments: return self new_segs = [_encode_reserved(s) for s in segments] return self.__class__(self._url.child(*new_segs)) def normalize(self, *a, **kw): "Return a new `DecodedURL` wrapping the result of :meth:`~hyperlink.URL.normalize()`" return self.__class__(self._url.normalize(*a, **kw)) @property def absolute(self): return self._url.absolute @property def scheme(self): return self._url.scheme @property def host(self): return _decode_host(self._url.host) @property def port(self): return self._url.port @property def rooted(self): return self._url.rooted @property def path(self): try: return self._path except AttributeError: pass self._path = tuple([_percent_decode(p, raise_subencoding_exc=True) for p in self._url.path]) return self._path @property def query(self): try: return self._query except AttributeError: pass _q = [tuple(_percent_decode(x, raise_subencoding_exc=True) if x is not None else None for x in (k, v)) for k, v in self._url.query] self._query = tuple(_q) return self._query @property def fragment(self): try: return self._fragment except AttributeError: pass frag = self._url.fragment self._fragment = _percent_decode(frag, raise_subencoding_exc=True) return self._fragment @property def userinfo(self): try: return self._userinfo except AttributeError: pass self._userinfo = tuple([_percent_decode(p, raise_subencoding_exc=True) for p in self._url.userinfo.split(':', 1)]) return self._userinfo @property def user(self): return self.userinfo[0] @property def uses_netloc(self): return self._url.uses_netloc def replace(self, scheme=_UNSET, host=_UNSET, path=_UNSET, query=_UNSET, fragment=_UNSET, port=_UNSET, rooted=_UNSET, userinfo=_UNSET, uses_netloc=_UNSET): """While the signature is the same, this `replace()` differs a little from URL.replace. For instance, it accepts userinfo as a tuple, not as a string, handling the case of having a username containing a `:`. As with the rest of the methods on DecodedURL, if you pass a reserved character, it will be automatically encoded instead of an error being raised. """ if path is not _UNSET: path = [_encode_reserved(p) for p in path] if query is not _UNSET: query = [[_encode_reserved(x) if x is not None else None for x in (k, v)] for k, v in iter_pairs(query)] if userinfo is not _UNSET: if len(userinfo) > 2: raise ValueError('userinfo expected sequence of ["user"] or' ' ["user", "password"], got %r' % userinfo) userinfo = u':'.join([_encode_reserved(p) for p in userinfo]) new_url = self._url.replace(scheme=scheme, host=host, path=path, query=query, fragment=fragment, port=port, rooted=rooted, userinfo=userinfo, uses_netloc=uses_netloc) return self.__class__(url=new_url) def get(self, name): "Get the value of all query parameters whose name matches *name*" return [v for (k, v) in self.query if name == k] def add(self, name, value=None): "Return a new DecodedURL with the query parameter *name* and *value* added." return self.replace(query=self.query + ((name, value),)) def set(self, name, value=None): "Return a new DecodedURL with query parameter *name* set to *value*" query = self.query q = [(k, v) for (k, v) in query if k != name] idx = next((i for (i, (k, v)) in enumerate(query) if k == name), -1) q[idx:idx] = [(name, value)] return self.replace(query=q) def remove(self, name, value=_UNSET, limit=None): """Return a new DecodedURL with query parameter *name* removed. Optionally also filter for *value*, as well as cap the number of parameters removed with *limit*. """ if limit is None: if value is _UNSET: nq = [(k, v) for (k, v) in self.query if k != name] else: nq = [(k, v) for (k, v) in self.query if not (k == name and v == value)] else: nq, removed_count = [], 0 for k, v in self.query: if k == name and (value is _UNSET or v == value) and removed_count < limit: removed_count += 1 # drop it else: nq.append((k, v)) # keep it return self.replace(query=nq) def __repr__(self): cn = self.__class__.__name__ return '%s(url=%r)' % (cn, self._url) def __str__(self): # TODO: the underlying URL's __str__ needs to change to make # this work as the URL, see #55 return str(self._url) def __eq__(self, other): if not isinstance(other, self.__class__): return NotImplemented return self.normalize().to_uri() == other.normalize().to_uri() def __ne__(self, other): if not isinstance(other, self.__class__): return NotImplemented return not self.__eq__(other) def __hash__(self): return hash((self.__class__, self.scheme, self.userinfo, self.host, self.path, self.query, self.fragment, self.port, self.rooted, self.uses_netloc)) # # Begin Twisted Compat Code asURI = to_uri asIRI = to_iri @classmethod def fromText(cls, s, lazy=False): return cls.from_text(s, lazy=lazy) def asText(self, includeSecrets=False): return self.to_text(with_password=includeSecrets) def __dir__(self): try: ret = object.__dir__(self) except AttributeError: # object.__dir__ == AttributeError # pdw for py2 ret = dir(self.__class__) + list(self.__dict__.keys()) ret = sorted(set(ret) - set(['fromText', 'asURI', 'asIRI', 'asText'])) return ret # # End Twisted Compat Code def parse(url, decoded=True, lazy=False): """Automatically turn text into a structured URL object. Args: decoded (bool): Whether or not to return a :class:`DecodedURL`, which automatically handles all encoding/decoding/quoting/unquoting for all the various accessors of parts of the URL, or an :class:`EncodedURL`, which has the same API, but requires handling of special characters for different parts of the URL. lazy (bool): In the case of `decoded=True`, this controls whether the URL is decoded immediately or as accessed. The default, `lazy=False`, checks all encoded parts of the URL for decodability. """ enc_url = EncodedURL.from_text(url) if not decoded: return enc_url dec_url = DecodedURL(enc_url, lazy=lazy) return dec_url ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/hyperlink/test/__init__.py ================================================ ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/hyperlink/test/common.py ================================================ from unittest import TestCase class HyperlinkTestCase(TestCase): """This type mostly exists to provide a backwards-compatible assertRaises method for Python 2.6 testing. """ def assertRaises(self, excClass, callableObj=None, *args, **kwargs): """Fail unless an exception of class excClass is raised by callableObj when invoked with arguments args and keyword arguments kwargs. If a different type of exception is raised, it will not be caught, and the test case will be deemed to have suffered an error, exactly as for an unexpected exception. If called with callableObj omitted or None, will return a context object used like this:: with self.assertRaises(SomeException): do_something() The context manager keeps a reference to the exception as the 'exception' attribute. This allows you to inspect the exception after the assertion:: with self.assertRaises(SomeException) as cm: do_something() the_exception = cm.exception self.assertEqual(the_exception.error_code, 3) """ context = _AssertRaisesContext(excClass, self) if callableObj is None: return context with context: callableObj(*args, **kwargs) class _AssertRaisesContext(object): "A context manager used to implement HyperlinkTestCase.assertRaises." def __init__(self, expected, test_case): self.expected = expected self.failureException = test_case.failureException def __enter__(self): return self def __exit__(self, exc_type, exc_value, tb): if exc_type is None: exc_name = self.expected.__name__ raise self.failureException("%s not raised" % (exc_name,)) if not issubclass(exc_type, self.expected): # let unexpected exceptions pass through return False self.exception = exc_value # store for later retrieval return True ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/hyperlink/test/test_common.py ================================================ """ Tests for hyperlink.test.common """ from unittest import TestCase from .common import HyperlinkTestCase class _ExpectedException(Exception): """An exception used to test HyperlinkTestCase.assertRaises. """ class _UnexpectedException(Exception): """An exception used to test HyperlinkTestCase.assertRaises. """ class TestHyperlink(TestCase): """Tests for HyperlinkTestCase""" def setUp(self): self.hyperlink_test = HyperlinkTestCase("run") def test_assertRaisesWithCallable(self): """HyperlinkTestCase.assertRaises does not raise an AssertionError when given a callable that, when called with the provided arguments, raises the expected exception. """ called_with = [] def raisesExpected(*args, **kwargs): called_with.append((args, kwargs)) raise _ExpectedException self.hyperlink_test.assertRaises(_ExpectedException, raisesExpected, 1, keyword=True) self.assertEqual(called_with, [((1,), {"keyword": True})]) def test_assertRaisesWithCallableUnexpectedException(self): """When given a callable that raises an unexpected exception, HyperlinkTestCase.assertRaises raises that exception. """ def doesNotRaiseExpected(*args, **kwargs): raise _UnexpectedException try: self.hyperlink_test.assertRaises(_ExpectedException, doesNotRaiseExpected) except _UnexpectedException: pass def test_assertRaisesWithCallableDoesNotRaise(self): """HyperlinkTestCase.assertRaises raises an AssertionError when given a callable that, when called, does not raise any exception. """ def doesNotRaise(*args, **kwargs): return True try: self.hyperlink_test.assertRaises(_ExpectedException, doesNotRaise) except AssertionError: pass def test_assertRaisesContextManager(self): """HyperlinkTestCase.assertRaises does not raise an AssertionError when used as a context manager with a suite that raises the expected exception. The context manager stores the exception instance under its `exception` instance variable. """ with self.hyperlink_test.assertRaises(_ExpectedException) as cm: raise _ExpectedException self.assertTrue(isinstance(cm.exception, _ExpectedException)) def test_assertRaisesContextManagerUnexpectedException(self): """When used as a context manager with a block that raises an unexpected exception, HyperlinkTestCase.assertRaises raises that unexpected exception. """ try: with self.hyperlink_test.assertRaises(_ExpectedException): raise _UnexpectedException except _UnexpectedException: pass def test_assertRaisesContextManagerDoesNotRaise(self): """HyperlinkTestcase.assertRaises raises an AssertionError when used as a context manager with a block that does not raise any exception. """ try: with self.hyperlink_test.assertRaises(_ExpectedException): pass except AssertionError: pass ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/hyperlink/test/test_decoded_url.py ================================================ # -*- coding: utf-8 -*- from __future__ import unicode_literals from .. import DecodedURL from .._url import _percent_decode from .common import HyperlinkTestCase BASIC_URL = 'http://example.com/#' TOTAL_URL = "https://%75%73%65%72:%00%00%00%00@xn--bcher-kva.ch:8080/a/nice%20nice/./path/?zot=23%25&zut#frég" class TestURL(HyperlinkTestCase): def test_durl_basic(self): bdurl = DecodedURL.from_text(BASIC_URL) assert bdurl.scheme == 'http' assert bdurl.host == 'example.com' assert bdurl.port == 80 assert bdurl.path == ('',) assert bdurl.fragment == '' durl = DecodedURL.from_text(TOTAL_URL) assert durl.scheme == 'https' assert durl.host == 'bücher.ch' assert durl.port == 8080 assert durl.path == ('a', 'nice nice', '.', 'path', '') assert durl.fragment == 'frég' assert durl.get('zot') == ['23%'] assert durl.user == 'user' assert durl.userinfo == ('user', '\0\0\0\0') def test_passthroughs(self): # just basic tests for the methods that more or less pass straight # through to the underlying URL durl = DecodedURL.from_text(TOTAL_URL) assert durl.sibling('te%t').path[-1] == 'te%t' assert durl.child('../test2%').path[-1] == '../test2%' assert durl.child() == durl assert durl.child() is durl assert durl.click('/').path[-1] == '' assert durl.user == 'user' assert '.' in durl.path assert '.' not in durl.normalize().path assert durl.to_uri().fragment == 'fr%C3%A9g' assert ' ' in durl.to_iri().path[1] assert durl.to_text(with_password=True) == TOTAL_URL assert durl.absolute assert durl.rooted assert durl == durl.encoded_url.get_decoded_url() durl2 = DecodedURL.from_text(TOTAL_URL, lazy=True) assert durl2 == durl2.encoded_url.get_decoded_url(lazy=True) assert str(DecodedURL.from_text(BASIC_URL).child(' ')) == 'http://example.com/%20' assert not (durl == 1) assert durl != 1 def test_repr(self): durl = DecodedURL.from_text(TOTAL_URL) assert repr(durl) == 'DecodedURL(url=' + repr(durl._url) + ')' def test_query_manipulation(self): durl = DecodedURL.from_text(TOTAL_URL) assert durl.get('zot') == ['23%'] durl = durl.add(' ', 'space') assert durl.get(' ') == ['space'] durl = durl.set(' ', 'spa%ed') assert durl.get(' ') == ['spa%ed'] durl = DecodedURL(url=durl.to_uri()) assert durl.get(' ') == ['spa%ed'] durl = durl.remove(' ') assert durl.get(' ') == [] durl = DecodedURL.from_text('/?%61rg=b&arg=c') assert durl.get('arg') == ['b', 'c'] assert durl.set('arg', 'd').get('arg') == ['d'] durl = DecodedURL.from_text(u"https://example.com/a/b/?fóó=1&bar=2&fóó=3") assert durl.remove("fóó") == DecodedURL.from_text("https://example.com/a/b/?bar=2") assert durl.remove("fóó", value="1") == DecodedURL.from_text("https://example.com/a/b/?bar=2&fóó=3") assert durl.remove("fóó", limit=1) == DecodedURL.from_text("https://example.com/a/b/?bar=2&fóó=3") assert durl.remove("fóó", value="1", limit=0) == DecodedURL.from_text("https://example.com/a/b/?fóó=1&bar=2&fóó=3") def test_equality_and_hashability(self): durl = DecodedURL.from_text(TOTAL_URL) durl2 = DecodedURL.from_text(TOTAL_URL) burl = DecodedURL.from_text(BASIC_URL) durl_uri = durl.to_uri() assert durl == durl assert durl == durl2 assert durl != burl assert durl != None assert durl != durl._url durl_map = {} durl_map[durl] = durl durl_map[durl2] = durl2 assert len(durl_map) == 1 durl_map[burl] = burl assert len(durl_map) == 2 durl_map[durl_uri] = durl_uri assert len(durl_map) == 3 def test_replace_roundtrip(self): durl = DecodedURL.from_text(TOTAL_URL) durl2 = durl.replace(scheme=durl.scheme, host=durl.host, path=durl.path, query=durl.query, fragment=durl.fragment, port=durl.port, rooted=durl.rooted, userinfo=durl.userinfo, uses_netloc=durl.uses_netloc) assert durl == durl2 def test_replace_userinfo(self): durl = DecodedURL.from_text(TOTAL_URL) with self.assertRaises(ValueError): durl.replace(userinfo=['user', 'pw', 'thiswillcauseafailure']) return def test_twisted_compat(self): durl = DecodedURL.from_text(TOTAL_URL) assert durl == DecodedURL.fromText(TOTAL_URL) assert 'to_text' in dir(durl) assert 'asText' not in dir(durl) assert durl.to_text() == durl.asText() def test_percent_decode_bytes(self): assert _percent_decode('%00', subencoding=False) == b'\0' def test_percent_decode_mixed(self): # See https://github.com/python-hyper/hyperlink/pull/59 for a # nice discussion of the possibilities assert _percent_decode('abcdé%C3%A9éfg') == 'abcdéééfg' # still allow percent encoding in the case of an error assert _percent_decode('abcdé%C3éfg') == 'abcdé%C3éfg' # ...unless explicitly told otherwise with self.assertRaises(UnicodeDecodeError): _percent_decode('abcdé%C3éfg', raise_subencoding_exc=True) # check that getting raw bytes works ok assert _percent_decode('a%00b', subencoding=False) == b'a\x00b' # when not encodable as subencoding assert _percent_decode('é%25é', subencoding='ascii') == 'é%25é' def test_click_decoded_url(self): durl = DecodedURL.from_text(TOTAL_URL) durl_dest = DecodedURL.from_text('/tëst') clicked = durl.click(durl_dest) assert clicked.host == durl.host assert clicked.path == durl_dest.path assert clicked.path == ('tëst',) ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/hyperlink/test/test_parse.py ================================================ # -*- coding: utf-8 -*- from __future__ import unicode_literals from .common import HyperlinkTestCase from hyperlink import parse, EncodedURL, DecodedURL BASIC_URL = 'http://example.com/#' TOTAL_URL = "https://%75%73%65%72:%00%00%00%00@xn--bcher-kva.ch:8080/a/nice%20nice/./path/?zot=23%25&zut#frég" UNDECODABLE_FRAG_URL = TOTAL_URL + '%C3' # the %C3 above percent-decodes to an unpaired \xc3 byte which makes this # invalid utf8 class TestURL(HyperlinkTestCase): def test_parse(self): purl = parse(TOTAL_URL) assert isinstance(purl, DecodedURL) assert purl.user == 'user' assert purl.get('zot') == ['23%'] assert purl.fragment == 'frég' purl2 = parse(TOTAL_URL, decoded=False) assert isinstance(purl2, EncodedURL) assert purl2.get('zot') == ['23%25'] with self.assertRaises(UnicodeDecodeError): purl3 = parse(UNDECODABLE_FRAG_URL) purl3 = parse(UNDECODABLE_FRAG_URL, lazy=True) with self.assertRaises(UnicodeDecodeError): purl3.fragment return ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/hyperlink/test/test_scheme_registration.py ================================================ # -*- coding: utf-8 -*- from __future__ import unicode_literals from .. import _url from .common import HyperlinkTestCase from .._url import register_scheme, URL class TestSchemeRegistration(HyperlinkTestCase): def setUp(self): self._orig_scheme_port_map = dict(_url.SCHEME_PORT_MAP) self._orig_no_netloc_schemes = set(_url.NO_NETLOC_SCHEMES) def tearDown(self): _url.SCHEME_PORT_MAP = self._orig_scheme_port_map _url.NO_NETLOC_SCHEMES = self._orig_no_netloc_schemes def test_register_scheme_basic(self): register_scheme('deltron', uses_netloc=True, default_port=3030) u1 = URL.from_text('deltron://example.com') assert u1.scheme == 'deltron' assert u1.port == 3030 assert u1.uses_netloc is True # test netloc works even when the original gives no indication u2 = URL.from_text('deltron:') u2 = u2.replace(host='example.com') assert u2.to_text() == 'deltron://example.com' # test default port means no emission u3 = URL.from_text('deltron://example.com:3030') assert u3.to_text() == 'deltron://example.com' register_scheme('nonetron', default_port=3031) u4 = URL(scheme='nonetron') u4 = u4.replace(host='example.com') assert u4.to_text() == 'nonetron://example.com' def test_register_no_netloc_scheme(self): register_scheme('noloctron', uses_netloc=False) u4 = URL(scheme='noloctron') u4 = u4.replace(path=("example", "path")) assert u4.to_text() == 'noloctron:example/path' def test_register_no_netloc_with_port(self): with self.assertRaises(ValueError): register_scheme('badnetlocless', uses_netloc=False, default_port=7) def test_invalid_uses_netloc(self): with self.assertRaises(ValueError): register_scheme('badnetloc', uses_netloc=None) with self.assertRaises(ValueError): register_scheme('badnetloc', uses_netloc=object()) def test_register_invalid_uses_netloc(self): with self.assertRaises(ValueError): register_scheme('lol', uses_netloc=lambda: 'nope') def test_register_invalid_port(self): with self.assertRaises(ValueError): register_scheme('nope', default_port=lambda: 'lol') ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/hyperlink/test/test_url.py ================================================ # -*- coding: utf-8 -*- # Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. from __future__ import unicode_literals import sys import socket from .common import HyperlinkTestCase from .. import URL, URLParseError # automatically import the py27 windows implementation when appropriate from .. import _url from .._url import inet_pton, SCHEME_PORT_MAP, parse_host PY2 = (sys.version_info[0] == 2) unicode = type(u'') BASIC_URL = "http://www.foo.com/a/nice/path/?zot=23&zut" # Examples from RFC 3986 section 5.4, Reference Resolution Examples relativeLinkBaseForRFC3986 = 'http://a/b/c/d;p?q' relativeLinkTestsForRFC3986 = [ # "Normal" # ('g:h', 'g:h'), # can't click on a scheme-having url without an abs path ('g', 'http://a/b/c/g'), ('./g', 'http://a/b/c/g'), ('g/', 'http://a/b/c/g/'), ('/g', 'http://a/g'), ('//g', 'http://g'), ('?y', 'http://a/b/c/d;p?y'), ('g?y', 'http://a/b/c/g?y'), ('#s', 'http://a/b/c/d;p?q#s'), ('g#s', 'http://a/b/c/g#s'), ('g?y#s', 'http://a/b/c/g?y#s'), (';x', 'http://a/b/c/;x'), ('g;x', 'http://a/b/c/g;x'), ('g;x?y#s', 'http://a/b/c/g;x?y#s'), ('', 'http://a/b/c/d;p?q'), ('.', 'http://a/b/c/'), ('./', 'http://a/b/c/'), ('..', 'http://a/b/'), ('../', 'http://a/b/'), ('../g', 'http://a/b/g'), ('../..', 'http://a/'), ('../../', 'http://a/'), ('../../g', 'http://a/g'), # Abnormal examples # ".." cannot be used to change the authority component of a URI. ('../../../g', 'http://a/g'), ('../../../../g', 'http://a/g'), # Only include "." and ".." when they are only part of a larger segment, # not by themselves. ('/./g', 'http://a/g'), ('/../g', 'http://a/g'), ('g.', 'http://a/b/c/g.'), ('.g', 'http://a/b/c/.g'), ('g..', 'http://a/b/c/g..'), ('..g', 'http://a/b/c/..g'), # Unnecessary or nonsensical forms of "." and "..". ('./../g', 'http://a/b/g'), ('./g/.', 'http://a/b/c/g/'), ('g/./h', 'http://a/b/c/g/h'), ('g/../h', 'http://a/b/c/h'), ('g;x=1/./y', 'http://a/b/c/g;x=1/y'), ('g;x=1/../y', 'http://a/b/c/y'), # Separating the reference's query and fragment components from the path. ('g?y/./x', 'http://a/b/c/g?y/./x'), ('g?y/../x', 'http://a/b/c/g?y/../x'), ('g#s/./x', 'http://a/b/c/g#s/./x'), ('g#s/../x', 'http://a/b/c/g#s/../x') ] ROUNDTRIP_TESTS = ( "http://localhost", "http://localhost/", "http://127.0.0.1/", "http://[::127.0.0.1]/", "http://[::1]/", "http://localhost/foo", "http://localhost/foo/", "http://localhost/foo!!bar/", "http://localhost/foo%20bar/", "http://localhost/foo%2Fbar/", "http://localhost/foo?n", "http://localhost/foo?n=v", "http://localhost/foo?n=/a/b", "http://example.com/foo!@$bar?b!@z=123", "http://localhost/asd?a=asd%20sdf/345", "http://(%2525)/(%2525)?(%2525)&(%2525)=(%2525)#(%2525)", "http://(%C3%A9)/(%C3%A9)?(%C3%A9)&(%C3%A9)=(%C3%A9)#(%C3%A9)", "?sslrootcert=/Users/glyph/Downloads/rds-ca-2015-root.pem&sslmode=verify", # from boltons.urlutils' tests 'http://googlewebsite.com/e-shops.aspx', 'http://example.com:8080/search?q=123&business=Nothing%20Special', 'http://hatnote.com:9000/?arg=1&arg=2&arg=3', 'https://xn--bcher-kva.ch', 'http://xn--ggbla1c4e.xn--ngbc5azd/', 'http://tools.ietf.org/html/rfc3986#section-3.4', # 'http://wiki:pedia@hatnote.com', 'ftp://ftp.rfc-editor.org/in-notes/tar/RFCs0001-0500.tar.gz', 'http://[1080:0:0:0:8:800:200C:417A]/index.html', 'ssh://192.0.2.16:2222/', 'https://[::101.45.75.219]:80/?hi=bye', 'ldap://[::192.9.5.5]/dc=example,dc=com??sub?(sn=Jensen)', 'mailto:me@example.com?to=me@example.com&body=hi%20http://wikipedia.org', 'news:alt.rec.motorcycle', 'tel:+1-800-867-5309', 'urn:oasis:member:A00024:x', ('magnet:?xt=urn:btih:1a42b9e04e122b97a5254e3df77ab3c4b7da725f&dn=Puppy%' '20Linux%20precise-5.7.1.iso&tr=udp://tracker.openbittorrent.com:80&' 'tr=udp://tracker.publicbt.com:80&tr=udp://tracker.istole.it:6969&' 'tr=udp://tracker.ccc.de:80&tr=udp://open.demonii.com:1337'), # percent-encoded delimiters in percent-encodable fields 'https://%3A@example.com/', # colon in username 'https://%40@example.com/', # at sign in username 'https://%2f@example.com/', # slash in username 'https://a:%3a@example.com/', # colon in password 'https://a:%40@example.com/', # at sign in password 'https://a:%2f@example.com/', # slash in password 'https://a:%3f@example.com/', # question mark in password 'https://example.com/%2F/', # slash in path 'https://example.com/%3F/', # question mark in path 'https://example.com/%23/', # hash in path 'https://example.com/?%23=b', # hash in query param name 'https://example.com/?%3D=b', # equals in query param name 'https://example.com/?%26=b', # ampersand in query param name 'https://example.com/?a=%23', # hash in query param value 'https://example.com/?a=%26', # ampersand in query param value 'https://example.com/?a=%3D', # equals in query param value # double-encoded percent sign in all percent-encodable positions: "http://(%2525):(%2525)@example.com/(%2525)/?(%2525)=(%2525)#(%2525)", # colon in first part of schemeless relative url 'first_seg_rel_path__colon%3Anotok/second_seg__colon%3Aok', ) class TestURL(HyperlinkTestCase): """ Tests for L{URL}. """ def assertUnicoded(self, u): """ The given L{URL}'s components should be L{unicode}. @param u: The L{URL} to test. """ self.assertTrue(isinstance(u.scheme, unicode) or u.scheme is None, repr(u)) self.assertTrue(isinstance(u.host, unicode) or u.host is None, repr(u)) for seg in u.path: self.assertEqual(type(seg), unicode, repr(u)) for (k, v) in u.query: self.assertEqual(type(seg), unicode, repr(u)) self.assertTrue(v is None or isinstance(v, unicode), repr(u)) self.assertEqual(type(u.fragment), unicode, repr(u)) def assertURL(self, u, scheme, host, path, query, fragment, port, userinfo=''): """ The given L{URL} should have the given components. @param u: The actual L{URL} to examine. @param scheme: The expected scheme. @param host: The expected host. @param path: The expected path. @param query: The expected query. @param fragment: The expected fragment. @param port: The expected port. @param userinfo: The expected userinfo. """ actual = (u.scheme, u.host, u.path, u.query, u.fragment, u.port, u.userinfo) expected = (scheme, host, tuple(path), tuple(query), fragment, port, u.userinfo) self.assertEqual(actual, expected) def test_initDefaults(self): """ L{URL} should have appropriate default values. """ def check(u): self.assertUnicoded(u) self.assertURL(u, 'http', '', [], [], '', 80, '') check(URL('http', '')) check(URL('http', '', [], [])) check(URL('http', '', [], [], '')) def test_init(self): """ L{URL} should accept L{unicode} parameters. """ u = URL('s', 'h', ['p'], [('k', 'v'), ('k', None)], 'f') self.assertUnicoded(u) self.assertURL(u, 's', 'h', ['p'], [('k', 'v'), ('k', None)], 'f', None) self.assertURL(URL('http', '\xe0', ['\xe9'], [('\u03bb', '\u03c0')], '\u22a5'), 'http', '\xe0', ['\xe9'], [('\u03bb', '\u03c0')], '\u22a5', 80) def test_initPercent(self): """ L{URL} should accept (and not interpret) percent characters. """ u = URL('s', '%68', ['%70'], [('%6B', '%76'), ('%6B', None)], '%66') self.assertUnicoded(u) self.assertURL(u, 's', '%68', ['%70'], [('%6B', '%76'), ('%6B', None)], '%66', None) def test_repr(self): """ L{URL.__repr__} will display the canonical form of the URL, wrapped in a L{URL.from_text} invocation, so that it is C{eval}-able but still easy to read. """ self.assertEqual( repr(URL(scheme='http', host='foo', path=['bar'], query=[('baz', None), ('k', 'v')], fragment='frob')), "URL.from_text(%s)" % (repr(u"http://foo/bar?baz&k=v#frob"),) ) def test_from_text(self): """ Round-tripping L{URL.from_text} with C{str} results in an equivalent URL. """ urlpath = URL.from_text(BASIC_URL) self.assertEqual(BASIC_URL, urlpath.to_text()) def test_roundtrip(self): """ L{URL.to_text} should invert L{URL.from_text}. """ for test in ROUNDTRIP_TESTS: result = URL.from_text(test).to_text(with_password=True) self.assertEqual(test, result) def test_roundtrip_double_iri(self): for test in ROUNDTRIP_TESTS: url = URL.from_text(test) iri = url.to_iri() double_iri = iri.to_iri() assert iri == double_iri iri_text = iri.to_text(with_password=True) double_iri_text = double_iri.to_text(with_password=True) assert iri_text == double_iri_text return def test_equality(self): """ Two URLs decoded using L{URL.from_text} will be equal (C{==}) if they decoded same URL string, and unequal (C{!=}) if they decoded different strings. """ urlpath = URL.from_text(BASIC_URL) self.assertEqual(urlpath, URL.from_text(BASIC_URL)) self.assertNotEqual( urlpath, URL.from_text('ftp://www.anotherinvaliddomain.com/' 'foo/bar/baz/?zot=21&zut') ) def test_fragmentEquality(self): """ An URL created with the empty string for a fragment compares equal to an URL created with an unspecified fragment. """ self.assertEqual(URL(fragment=''), URL()) self.assertEqual(URL.from_text(u"http://localhost/#"), URL.from_text(u"http://localhost/")) def test_child(self): """ L{URL.child} appends a new path segment, but does not affect the query or fragment. """ urlpath = URL.from_text(BASIC_URL) self.assertEqual("http://www.foo.com/a/nice/path/gong?zot=23&zut", urlpath.child('gong').to_text()) self.assertEqual("http://www.foo.com/a/nice/path/gong%2F?zot=23&zut", urlpath.child('gong/').to_text()) self.assertEqual( "http://www.foo.com/a/nice/path/gong%2Fdouble?zot=23&zut", urlpath.child('gong/double').to_text() ) self.assertEqual( "http://www.foo.com/a/nice/path/gong%2Fdouble%2F?zot=23&zut", urlpath.child('gong/double/').to_text() ) def test_multiChild(self): """ L{URL.child} receives multiple segments as C{*args} and appends each in turn. """ url = URL.from_text('http://example.com/a/b') self.assertEqual(url.child('c', 'd', 'e').to_text(), 'http://example.com/a/b/c/d/e') def test_childInitRoot(self): """ L{URL.child} of a L{URL} without a path produces a L{URL} with a single path segment. """ childURL = URL(host=u"www.foo.com").child(u"c") self.assertTrue(childURL.rooted) self.assertEqual("http://www.foo.com/c", childURL.to_text()) def test_emptyChild(self): """ L{URL.child} without any new segments returns the original L{URL}. """ url = URL(host=u"www.foo.com") self.assertEqual(url.child(), url) def test_sibling(self): """ L{URL.sibling} of a L{URL} replaces the last path segment, but does not affect the query or fragment. """ urlpath = URL.from_text(BASIC_URL) self.assertEqual( "http://www.foo.com/a/nice/path/sister?zot=23&zut", urlpath.sibling('sister').to_text() ) # Use an url without trailing '/' to check child removal. url_text = "http://www.foo.com/a/nice/path?zot=23&zut" urlpath = URL.from_text(url_text) self.assertEqual( "http://www.foo.com/a/nice/sister?zot=23&zut", urlpath.sibling('sister').to_text() ) def test_click(self): """ L{URL.click} interprets the given string as a relative URI-reference and returns a new L{URL} interpreting C{self} as the base absolute URI. """ urlpath = URL.from_text(BASIC_URL) # A null uri should be valid (return here). self.assertEqual("http://www.foo.com/a/nice/path/?zot=23&zut", urlpath.click("").to_text()) # A simple relative path remove the query. self.assertEqual("http://www.foo.com/a/nice/path/click", urlpath.click("click").to_text()) # An absolute path replace path and query. self.assertEqual("http://www.foo.com/click", urlpath.click("/click").to_text()) # Replace just the query. self.assertEqual("http://www.foo.com/a/nice/path/?burp", urlpath.click("?burp").to_text()) # One full url to another should not generate '//' between authority. # and path self.assertTrue("//foobar" not in urlpath.click('http://www.foo.com/foobar').to_text()) # From a url with no query clicking a url with a query, the query # should be handled properly. u = URL.from_text('http://www.foo.com/me/noquery') self.assertEqual('http://www.foo.com/me/17?spam=158', u.click('/me/17?spam=158').to_text()) # Check that everything from the path onward is removed when the click # link has no path. u = URL.from_text('http://localhost/foo?abc=def') self.assertEqual(u.click('http://www.python.org').to_text(), 'http://www.python.org') # https://twistedmatrix.com/trac/ticket/8184 u = URL.from_text('http://hatnote.com/a/b/../c/./d/e/..') res = 'http://hatnote.com/a/c/d/' self.assertEqual(u.click('').to_text(), res) # test click default arg is same as empty string above self.assertEqual(u.click().to_text(), res) # test click on a URL instance u = URL.fromText('http://localhost/foo/?abc=def') u2 = URL.from_text('bar') u3 = u.click(u2) self.assertEqual(u3.to_text(), 'http://localhost/foo/bar') def test_clickRFC3986(self): """ L{URL.click} should correctly resolve the examples in RFC 3986. """ base = URL.from_text(relativeLinkBaseForRFC3986) for (ref, expected) in relativeLinkTestsForRFC3986: self.assertEqual(base.click(ref).to_text(), expected) def test_clickSchemeRelPath(self): """ L{URL.click} should not accept schemes with relative paths. """ base = URL.from_text(relativeLinkBaseForRFC3986) self.assertRaises(NotImplementedError, base.click, 'g:h') self.assertRaises(NotImplementedError, base.click, 'http:h') def test_cloneUnchanged(self): """ Verify that L{URL.replace} doesn't change any of the arguments it is passed. """ urlpath = URL.from_text('https://x:1/y?z=1#A') self.assertEqual(urlpath.replace(urlpath.scheme, urlpath.host, urlpath.path, urlpath.query, urlpath.fragment, urlpath.port), urlpath) self.assertEqual(urlpath.replace(), urlpath) def test_clickCollapse(self): """ L{URL.click} collapses C{.} and C{..} according to RFC 3986 section 5.2.4. """ tests = [ ['http://localhost/', '.', 'http://localhost/'], ['http://localhost/', '..', 'http://localhost/'], ['http://localhost/a/b/c', '.', 'http://localhost/a/b/'], ['http://localhost/a/b/c', '..', 'http://localhost/a/'], ['http://localhost/a/b/c', './d/e', 'http://localhost/a/b/d/e'], ['http://localhost/a/b/c', '../d/e', 'http://localhost/a/d/e'], ['http://localhost/a/b/c', '/./d/e', 'http://localhost/d/e'], ['http://localhost/a/b/c', '/../d/e', 'http://localhost/d/e'], ['http://localhost/a/b/c/', '../../d/e/', 'http://localhost/a/d/e/'], ['http://localhost/a/./c', '../d/e', 'http://localhost/d/e'], ['http://localhost/a/./c/', '../d/e', 'http://localhost/a/d/e'], ['http://localhost/a/b/c/d', './e/../f/../g', 'http://localhost/a/b/c/g'], ['http://localhost/a/b/c', 'd//e', 'http://localhost/a/b/d//e'], ] for start, click, expected in tests: actual = URL.from_text(start).click(click).to_text() self.assertEqual( actual, expected, "{start}.click({click}) => {actual} not {expected}".format( start=start, click=repr(click), actual=actual, expected=expected, ) ) def test_queryAdd(self): """ L{URL.add} adds query parameters. """ self.assertEqual( "http://www.foo.com/a/nice/path/?foo=bar", URL.from_text("http://www.foo.com/a/nice/path/") .add(u"foo", u"bar").to_text()) self.assertEqual( "http://www.foo.com/?foo=bar", URL(host=u"www.foo.com").add(u"foo", u"bar") .to_text()) urlpath = URL.from_text(BASIC_URL) self.assertEqual( "http://www.foo.com/a/nice/path/?zot=23&zut&burp", urlpath.add(u"burp").to_text()) self.assertEqual( "http://www.foo.com/a/nice/path/?zot=23&zut&burp=xxx", urlpath.add(u"burp", u"xxx").to_text()) self.assertEqual( "http://www.foo.com/a/nice/path/?zot=23&zut&burp=xxx&zing", urlpath.add(u"burp", u"xxx").add(u"zing").to_text()) # Note the inversion! self.assertEqual( "http://www.foo.com/a/nice/path/?zot=23&zut&zing&burp=xxx", urlpath.add(u"zing").add(u"burp", u"xxx").to_text()) # Note the two values for the same name. self.assertEqual( "http://www.foo.com/a/nice/path/?zot=23&zut&burp=xxx&zot=32", urlpath.add(u"burp", u"xxx").add(u"zot", '32') .to_text()) def test_querySet(self): """ L{URL.set} replaces query parameters by name. """ urlpath = URL.from_text(BASIC_URL) self.assertEqual( "http://www.foo.com/a/nice/path/?zot=32&zut", urlpath.set(u"zot", '32').to_text()) # Replace name without value with name/value and vice-versa. self.assertEqual( "http://www.foo.com/a/nice/path/?zot&zut=itworked", urlpath.set(u"zot").set(u"zut", u"itworked").to_text() ) # Q: what happens when the query has two values and we replace? # A: we replace both values with a single one self.assertEqual( "http://www.foo.com/a/nice/path/?zot=32&zut", urlpath.add(u"zot", u"xxx").set(u"zot", '32').to_text() ) def test_queryRemove(self): """ L{URL.remove} removes instances of a query parameter. """ url = URL.from_text(u"https://example.com/a/b/?foo=1&bar=2&foo=3") self.assertEqual( url.remove(u"foo"), URL.from_text(u"https://example.com/a/b/?bar=2") ) self.assertEqual( url.remove(name=u"foo", value=u"1"), URL.from_text(u"https://example.com/a/b/?bar=2&foo=3") ) self.assertEqual( url.remove(name=u"foo", limit=1), URL.from_text(u"https://example.com/a/b/?bar=2&foo=3") ) self.assertEqual( url.remove(name=u"foo", value=u"1", limit=0), URL.from_text(u"https://example.com/a/b/?foo=1&bar=2&foo=3") ) def test_parseEqualSignInParamValue(self): """ Every C{=}-sign after the first in a query parameter is simply included in the value of the parameter. """ u = URL.from_text('http://localhost/?=x=x=x') self.assertEqual(u.get(''), ['x=x=x']) self.assertEqual(u.to_text(), 'http://localhost/?=x=x=x') u = URL.from_text('http://localhost/?foo=x=x=x&bar=y') self.assertEqual(u.query, (('foo', 'x=x=x'), ('bar', 'y'))) self.assertEqual(u.to_text(), 'http://localhost/?foo=x=x=x&bar=y') u = URL.from_text('https://example.com/?argument=3&argument=4&operator=%3D') iri = u.to_iri() self.assertEqual(iri.get('operator'), ['=']) # assert that the equals is not unnecessarily escaped self.assertEqual(iri.to_uri().get('operator'), ['=']) def test_empty(self): """ An empty L{URL} should serialize as the empty string. """ self.assertEqual(URL().to_text(), '') def test_justQueryText(self): """ An L{URL} with query text should serialize as just query text. """ u = URL(query=[(u"hello", u"world")]) self.assertEqual(u.to_text(), '?hello=world') def test_identicalEqual(self): """ L{URL} compares equal to itself. """ u = URL.from_text('http://localhost/') self.assertEqual(u, u) def test_similarEqual(self): """ URLs with equivalent components should compare equal. """ u1 = URL.from_text('http://u@localhost:8080/p/a/t/h?q=p#f') u2 = URL.from_text('http://u@localhost:8080/p/a/t/h?q=p#f') self.assertEqual(u1, u2) def test_differentNotEqual(self): """ L{URL}s that refer to different resources are both unequal (C{!=}) and also not equal (not C{==}). """ u1 = URL.from_text('http://localhost/a') u2 = URL.from_text('http://localhost/b') self.assertFalse(u1 == u2, "%r != %r" % (u1, u2)) self.assertNotEqual(u1, u2) def test_otherTypesNotEqual(self): """ L{URL} is not equal (C{==}) to other types. """ u = URL.from_text('http://localhost/') self.assertFalse(u == 42, "URL must not equal a number.") self.assertFalse(u == object(), "URL must not equal an object.") self.assertNotEqual(u, 42) self.assertNotEqual(u, object()) def test_identicalNotUnequal(self): """ Identical L{URL}s are not unequal (C{!=}) to each other. """ u = URL.from_text('http://u@localhost:8080/p/a/t/h?q=p#f') self.assertFalse(u != u, "%r == itself" % u) def test_similarNotUnequal(self): """ Structurally similar L{URL}s are not unequal (C{!=}) to each other. """ u1 = URL.from_text('http://u@localhost:8080/p/a/t/h?q=p#f') u2 = URL.from_text('http://u@localhost:8080/p/a/t/h?q=p#f') self.assertFalse(u1 != u2, "%r == %r" % (u1, u2)) def test_differentUnequal(self): """ Structurally different L{URL}s are unequal (C{!=}) to each other. """ u1 = URL.from_text('http://localhost/a') u2 = URL.from_text('http://localhost/b') self.assertTrue(u1 != u2, "%r == %r" % (u1, u2)) def test_otherTypesUnequal(self): """ L{URL} is unequal (C{!=}) to other types. """ u = URL.from_text('http://localhost/') self.assertTrue(u != 42, "URL must differ from a number.") self.assertTrue(u != object(), "URL must be differ from an object.") def test_asURI(self): """ L{URL.asURI} produces an URI which converts any URI unicode encoding into pure US-ASCII and returns a new L{URL}. """ unicodey = ('http://\N{LATIN SMALL LETTER E WITH ACUTE}.com/' '\N{LATIN SMALL LETTER E}\N{COMBINING ACUTE ACCENT}' '?\N{LATIN SMALL LETTER A}\N{COMBINING ACUTE ACCENT}=' '\N{LATIN SMALL LETTER I}\N{COMBINING ACUTE ACCENT}' '#\N{LATIN SMALL LETTER U}\N{COMBINING ACUTE ACCENT}') iri = URL.from_text(unicodey) uri = iri.asURI() self.assertEqual(iri.host, '\N{LATIN SMALL LETTER E WITH ACUTE}.com') self.assertEqual(iri.path[0], '\N{LATIN SMALL LETTER E}\N{COMBINING ACUTE ACCENT}') self.assertEqual(iri.to_text(), unicodey) expectedURI = 'http://xn--9ca.com/%C3%A9?%C3%A1=%C3%AD#%C3%BA' actualURI = uri.to_text() self.assertEqual(actualURI, expectedURI, '%r != %r' % (actualURI, expectedURI)) def test_asIRI(self): """ L{URL.asIRI} decodes any percent-encoded text in the URI, making it more suitable for reading by humans, and returns a new L{URL}. """ asciiish = 'http://xn--9ca.com/%C3%A9?%C3%A1=%C3%AD#%C3%BA' uri = URL.from_text(asciiish) iri = uri.asIRI() self.assertEqual(uri.host, 'xn--9ca.com') self.assertEqual(uri.path[0], '%C3%A9') self.assertEqual(uri.to_text(), asciiish) expectedIRI = ('http://\N{LATIN SMALL LETTER E WITH ACUTE}.com/' '\N{LATIN SMALL LETTER E WITH ACUTE}' '?\N{LATIN SMALL LETTER A WITH ACUTE}=' '\N{LATIN SMALL LETTER I WITH ACUTE}' '#\N{LATIN SMALL LETTER U WITH ACUTE}') actualIRI = iri.to_text() self.assertEqual(actualIRI, expectedIRI, '%r != %r' % (actualIRI, expectedIRI)) def test_badUTF8AsIRI(self): """ Bad UTF-8 in a path segment, query parameter, or fragment results in that portion of the URI remaining percent-encoded in the IRI. """ urlWithBinary = 'http://xn--9ca.com/%00%FF/%C3%A9' uri = URL.from_text(urlWithBinary) iri = uri.asIRI() expectedIRI = ('http://\N{LATIN SMALL LETTER E WITH ACUTE}.com/' '%00%FF/' '\N{LATIN SMALL LETTER E WITH ACUTE}') actualIRI = iri.to_text() self.assertEqual(actualIRI, expectedIRI, '%r != %r' % (actualIRI, expectedIRI)) def test_alreadyIRIAsIRI(self): """ A L{URL} composed of non-ASCII text will result in non-ASCII text. """ unicodey = ('http://\N{LATIN SMALL LETTER E WITH ACUTE}.com/' '\N{LATIN SMALL LETTER E}\N{COMBINING ACUTE ACCENT}' '?\N{LATIN SMALL LETTER A}\N{COMBINING ACUTE ACCENT}=' '\N{LATIN SMALL LETTER I}\N{COMBINING ACUTE ACCENT}' '#\N{LATIN SMALL LETTER U}\N{COMBINING ACUTE ACCENT}') iri = URL.from_text(unicodey) alsoIRI = iri.asIRI() self.assertEqual(alsoIRI.to_text(), unicodey) def test_alreadyURIAsURI(self): """ A L{URL} composed of encoded text will remain encoded. """ expectedURI = 'http://xn--9ca.com/%C3%A9?%C3%A1=%C3%AD#%C3%BA' uri = URL.from_text(expectedURI) actualURI = uri.asURI().to_text() self.assertEqual(actualURI, expectedURI) def test_userinfo(self): """ L{URL.from_text} will parse the C{userinfo} portion of the URI separately from the host and port. """ url = URL.from_text( 'http://someuser:somepassword@example.com/some-segment@ignore' ) self.assertEqual(url.authority(True), 'someuser:somepassword@example.com') self.assertEqual(url.authority(False), 'someuser:@example.com') self.assertEqual(url.userinfo, 'someuser:somepassword') self.assertEqual(url.user, 'someuser') self.assertEqual(url.to_text(), 'http://someuser:@example.com/some-segment@ignore') self.assertEqual( url.replace(userinfo=u"someuser").to_text(), 'http://someuser@example.com/some-segment@ignore' ) def test_portText(self): """ L{URL.from_text} parses custom port numbers as integers. """ portURL = URL.from_text(u"http://www.example.com:8080/") self.assertEqual(portURL.port, 8080) self.assertEqual(portURL.to_text(), u"http://www.example.com:8080/") def test_mailto(self): """ Although L{URL} instances are mainly for dealing with HTTP, other schemes (such as C{mailto:}) should work as well. For example, L{URL.from_text}/L{URL.to_text} round-trips cleanly for a C{mailto:} URL representing an email address. """ self.assertEqual(URL.from_text(u"mailto:user@example.com").to_text(), u"mailto:user@example.com") def test_queryIterable(self): """ When a L{URL} is created with a C{query} argument, the C{query} argument is converted into an N-tuple of 2-tuples, sensibly handling dictionaries. """ expected = (('alpha', 'beta'),) url = URL(query=[['alpha', 'beta']]) self.assertEqual(url.query, expected) url = URL(query={'alpha': 'beta'}) self.assertEqual(url.query, expected) def test_pathIterable(self): """ When a L{URL} is created with a C{path} argument, the C{path} is converted into a tuple. """ url = URL(path=['hello', 'world']) self.assertEqual(url.path, ('hello', 'world')) def test_invalidArguments(self): """ Passing an argument of the wrong type to any of the constructor arguments of L{URL} will raise a descriptive L{TypeError}. L{URL} typechecks very aggressively to ensure that its constitutent parts are all properly immutable and to prevent confusing errors when bad data crops up in a method call long after the code that called the constructor is off the stack. """ class Unexpected(object): def __str__(self): return "wrong" def __repr__(self): return "" defaultExpectation = "unicode" if bytes is str else "str" def assertRaised(raised, expectation, name): self.assertEqual(str(raised.exception), "expected {0} for {1}, got {2}".format( expectation, name, "")) def check(param, expectation=defaultExpectation): with self.assertRaises(TypeError) as raised: URL(**{param: Unexpected()}) assertRaised(raised, expectation, param) check("scheme") check("host") check("fragment") check("rooted", "bool") check("userinfo") check("port", "int or NoneType") with self.assertRaises(TypeError) as raised: URL(path=[Unexpected()]) assertRaised(raised, defaultExpectation, "path segment") with self.assertRaises(TypeError) as raised: URL(query=[(u"name", Unexpected())]) assertRaised(raised, defaultExpectation + " or NoneType", "query parameter value") with self.assertRaises(TypeError) as raised: URL(query=[(Unexpected(), u"value")]) assertRaised(raised, defaultExpectation, "query parameter name") # No custom error message for this one, just want to make sure # non-2-tuples don't get through. with self.assertRaises(TypeError): URL(query=[Unexpected()]) with self.assertRaises(ValueError): URL(query=[('k', 'v', 'vv')]) with self.assertRaises(ValueError): URL(query=[('k',)]) url = URL.from_text("https://valid.example.com/") with self.assertRaises(TypeError) as raised: url.child(Unexpected()) assertRaised(raised, defaultExpectation, "path segment") with self.assertRaises(TypeError) as raised: url.sibling(Unexpected()) assertRaised(raised, defaultExpectation, "path segment") with self.assertRaises(TypeError) as raised: url.click(Unexpected()) assertRaised(raised, defaultExpectation, "relative URL") def test_technicallyTextIsIterableBut(self): """ Technically, L{str} (or L{unicode}, as appropriate) is iterable, but C{URL(path="foo")} resulting in C{URL.from_text("f/o/o")} is never what you want. """ with self.assertRaises(TypeError) as raised: URL(path='foo') self.assertEqual( str(raised.exception), "expected iterable of text for path, not: {0}" .format(repr('foo')) ) def test_netloc(self): url = URL(scheme='https') self.assertEqual(url.uses_netloc, True) url = URL(scheme='git+https') self.assertEqual(url.uses_netloc, True) url = URL(scheme='mailto') self.assertEqual(url.uses_netloc, False) url = URL(scheme='ztp') self.assertEqual(url.uses_netloc, None) url = URL.from_text('ztp://test.com') self.assertEqual(url.uses_netloc, True) url = URL.from_text('ztp:test:com') self.assertEqual(url.uses_netloc, False) def test_ipv6_with_port(self): t = 'https://[2001:0db8:85a3:0000:0000:8a2e:0370:7334]:80/' url = URL.from_text(t) assert url.host == '2001:0db8:85a3:0000:0000:8a2e:0370:7334' assert url.port == 80 assert SCHEME_PORT_MAP[url.scheme] != url.port def test_basic(self): text = 'https://user:pass@example.com/path/to/here?k=v#nice' url = URL.from_text(text) assert url.scheme == 'https' assert url.userinfo == 'user:pass' assert url.host == 'example.com' assert url.path == ('path', 'to', 'here') assert url.fragment == 'nice' text = 'https://user:pass@127.0.0.1/path/to/here?k=v#nice' url = URL.from_text(text) assert url.scheme == 'https' assert url.userinfo == 'user:pass' assert url.host == '127.0.0.1' assert url.path == ('path', 'to', 'here') text = 'https://user:pass@[::1]/path/to/here?k=v#nice' url = URL.from_text(text) assert url.scheme == 'https' assert url.userinfo == 'user:pass' assert url.host == '::1' assert url.path == ('path', 'to', 'here') def test_invalid_url(self): self.assertRaises(URLParseError, URL.from_text, '#\n\n') def test_invalid_authority_url(self): self.assertRaises(URLParseError, URL.from_text, 'http://abc:\n\n/#') def test_invalid_ipv6(self): invalid_ipv6_ips = ['2001::0234:C1ab::A0:aabc:003F', '2001::1::3F', ':', '::::', '::256.0.0.1'] for ip in invalid_ipv6_ips: url_text = 'http://[' + ip + ']' self.assertRaises(socket.error, inet_pton, socket.AF_INET6, ip) self.assertRaises(URLParseError, URL.from_text, url_text) def test_invalid_port(self): self.assertRaises(URLParseError, URL.from_text, 'ftp://portmouth:smash') self.assertRaises(ValueError, URL.from_text, 'http://reader.googlewebsite.com:neverforget') def test_idna(self): u1 = URL.from_text('http://bücher.ch') self.assertEquals(u1.host, 'bücher.ch') self.assertEquals(u1.to_text(), 'http://bücher.ch') self.assertEquals(u1.to_uri().to_text(), 'http://xn--bcher-kva.ch') u2 = URL.from_text('https://xn--bcher-kva.ch') self.assertEquals(u2.host, 'xn--bcher-kva.ch') self.assertEquals(u2.to_text(), 'https://xn--bcher-kva.ch') self.assertEquals(u2.to_iri().to_text(), u'https://bücher.ch') def test_netloc_slashes(self): # basic sanity checks url = URL.from_text('mailto:mahmoud@hatnote.com') self.assertEquals(url.scheme, 'mailto') self.assertEquals(url.to_text(), 'mailto:mahmoud@hatnote.com') url = URL.from_text('http://hatnote.com') self.assertEquals(url.scheme, 'http') self.assertEquals(url.to_text(), 'http://hatnote.com') # test that unrecognized schemes stay consistent with '//' url = URL.from_text('newscheme:a:b:c') self.assertEquals(url.scheme, 'newscheme') self.assertEquals(url.to_text(), 'newscheme:a:b:c') url = URL.from_text('newerscheme://a/b/c') self.assertEquals(url.scheme, 'newerscheme') self.assertEquals(url.to_text(), 'newerscheme://a/b/c') # test that reasonable guesses are made url = URL.from_text('git+ftp://gitstub.biz/glyph/lefkowitz') self.assertEquals(url.scheme, 'git+ftp') self.assertEquals(url.to_text(), 'git+ftp://gitstub.biz/glyph/lefkowitz') url = URL.from_text('what+mailto:freerealestate@enotuniq.org') self.assertEquals(url.scheme, 'what+mailto') self.assertEquals(url.to_text(), 'what+mailto:freerealestate@enotuniq.org') url = URL(scheme='ztp', path=('x', 'y', 'z'), rooted=True) self.assertEquals(url.to_text(), 'ztp:/x/y/z') # also works when the input doesn't include '//' url = URL(scheme='git+ftp', path=('x', 'y', 'z' ,''), rooted=True, uses_netloc=True) # broken bc urlunsplit self.assertEquals(url.to_text(), 'git+ftp:///x/y/z/') # really why would this ever come up but ok url = URL.from_text('file:///path/to/heck') url2 = url.replace(scheme='mailto') self.assertEquals(url2.to_text(), 'mailto:/path/to/heck') url_text = 'unregisteredscheme:///a/b/c' url = URL.from_text(url_text) no_netloc_url = url.replace(uses_netloc=False) self.assertEquals(no_netloc_url.to_text(), 'unregisteredscheme:/a/b/c') netloc_url = url.replace(uses_netloc=True) self.assertEquals(netloc_url.to_text(), url_text) return def test_wrong_constructor(self): with self.assertRaises(ValueError): # whole URL not allowed URL(BASIC_URL) with self.assertRaises(ValueError): # explicitly bad scheme not allowed URL('HTTP_____more_like_imHoTTeP') def test_encoded_userinfo(self): url = URL.from_text('http://user:pass@example.com') assert url.userinfo == 'user:pass' url = url.replace(userinfo='us%20her:pass') iri = url.to_iri() assert iri.to_text(with_password=True) == 'http://us her:pass@example.com' assert iri.to_text(with_password=False) == 'http://us her:@example.com' assert iri.to_uri().to_text(with_password=True) == 'http://us%20her:pass@example.com' def test_hash(self): url_map = {} url1 = URL.from_text('http://blog.hatnote.com/ask?utm_source=geocity') assert hash(url1) == hash(url1) # sanity url_map[url1] = 1 url2 = URL.from_text('http://blog.hatnote.com/ask') url2 = url2.set('utm_source', 'geocity') url_map[url2] = 2 assert len(url_map) == 1 assert list(url_map.values()) == [2] assert hash(URL()) == hash(URL()) # slightly more sanity def test_dir(self): url = URL() res = dir(url) assert len(res) > 15 # twisted compat assert 'fromText' not in res assert 'asText' not in res assert 'asURI' not in res assert 'asIRI' not in res def test_twisted_compat(self): url = URL.fromText(u'http://example.com/a%20té%C3%A9st') assert url.asText() == 'http://example.com/a%20té%C3%A9st' assert url.asURI().asText() == 'http://example.com/a%20t%C3%A9%C3%A9st' # TODO: assert url.asIRI().asText() == u'http://example.com/a%20téést' def test_set_ordering(self): # TODO url = URL.from_text('http://example.com/?a=b&c') url = url.set(u'x', u'x') url = url.add(u'x', u'y') assert url.to_text() == u'http://example.com/?a=b&x=x&c&x=y' # Would expect: # assert url.to_text() == u'http://example.com/?a=b&c&x=x&x=y' def test_schemeless_path(self): "See issue #4" u1 = URL.from_text("urn%3Aietf%3Awg%3Aoauth%3A2.0%3Aoob") u2 = URL.from_text(u1.to_text()) assert u1 == u2 # sanity testing roundtripping u3 = URL.from_text(u1.to_iri().to_text()) assert u1 == u3 assert u2 == u3 # test that colons are ok past the first segment u4 = URL.from_text("first-segment/urn%3Aietf%3Awg%3Aoauth%3A2.0%3Aoob") u5 = u4.to_iri() assert u5.to_text() == u'first-segment/urn:ietf:wg:oauth:2.0:oob' u6 = URL.from_text(u5.to_text()).to_uri() assert u5 == u6 # colons stay decoded bc they're not in the first seg def test_emoji_domain(self): "See issue #7, affecting only narrow builds (2.6-3.3)" url = URL.from_text('https://xn--vi8hiv.ws') iri = url.to_iri() iri.to_text() # as long as we don't get ValueErrors, we're good def test_delim_in_param(self): "Per issue #6 and #8" self.assertRaises(ValueError, URL, scheme=u'http', host=u'a/c') self.assertRaises(ValueError, URL, path=(u"?",)) self.assertRaises(ValueError, URL, path=(u"#",)) self.assertRaises(ValueError, URL, query=((u"&", "test"))) def test_empty_paths_eq(self): u1 = URL.from_text('http://example.com/') u2 = URL.from_text('http://example.com') assert u1 == u2 u1 = URL.from_text('http://example.com') u2 = URL.from_text('http://example.com') assert u1 == u2 u1 = URL.from_text('http://example.com') u2 = URL.from_text('http://example.com/') assert u1 == u2 u1 = URL.from_text('http://example.com/') u2 = URL.from_text('http://example.com/') assert u1 == u2 def test_from_text_type(self): assert URL.from_text(u'#ok').fragment == u'ok' # sanity self.assertRaises(TypeError, URL.from_text, b'bytes://x.y.z') self.assertRaises(TypeError, URL.from_text, object()) def test_from_text_bad_authority(self): # bad ipv6 brackets self.assertRaises(URLParseError, URL.from_text, 'http://[::1/') self.assertRaises(URLParseError, URL.from_text, 'http://::1]/') self.assertRaises(URLParseError, URL.from_text, 'http://[[::1]/') self.assertRaises(URLParseError, URL.from_text, 'http://[::1]]/') # empty port self.assertRaises(URLParseError, URL.from_text, 'http://127.0.0.1:') # non-integer port self.assertRaises(URLParseError, URL.from_text, 'http://127.0.0.1:hi') # extra port colon (makes for an invalid host) self.assertRaises(URLParseError, URL.from_text, 'http://127.0.0.1::80') def test_normalize(self): url = URL.from_text('HTTP://Example.com/A%61/./../A%61?B%62=C%63#D%64') assert url.get('Bb') == [] assert url.get('B%62') == ['C%63'] assert len(url.path) == 4 # test that most expected normalizations happen norm_url = url.normalize() assert norm_url.scheme == 'http' assert norm_url.host == 'example.com' assert norm_url.path == ('Aa',) assert norm_url.get('Bb') == ['Cc'] assert norm_url.fragment == 'Dd' assert norm_url.to_text() == 'http://example.com/Aa?Bb=Cc#Dd' # test that flags work noop_norm_url = url.normalize(scheme=False, host=False, path=False, query=False, fragment=False) assert noop_norm_url == url # test that empty paths get at least one slash slashless_url = URL.from_text('http://example.io') slashful_url = slashless_url.normalize() assert slashful_url.to_text() == 'http://example.io/' # test case normalization for percent encoding delimited_url = URL.from_text('/a%2fb/cd%3f?k%3d=v%23#test') norm_delimited_url = delimited_url.normalize() assert norm_delimited_url.to_text() == '/a%2Fb/cd%3F?k%3D=v%23#test' # test invalid percent encoding during normalize assert URL(path=('', '%te%sts')).normalize(percents=False).to_text() == '/%te%sts' assert URL(path=('', '%te%sts')).normalize().to_text() == '/%25te%25sts' percenty_url = URL(scheme='ftp', path=['%%%', '%a%b'], query=[('%', '%%')], fragment='%', userinfo='%:%') assert percenty_url.to_text(with_password=True) == 'ftp://%:%@/%%%/%a%b?%=%%#%' assert percenty_url.normalize().to_text(with_password=True) == 'ftp://%25:%25@/%25%25%25/%25a%25b?%25=%25%25#%25' def test_str(self): # see also issue #49 text = u'http://example.com/á/y%20a%20y/?b=%25' url = URL.from_text(text) assert unicode(url) == text assert bytes(url) == b'http://example.com/%C3%A1/y%20a%20y/?b=%25' if PY2: assert isinstance(str(url), bytes) assert isinstance(unicode(url), unicode) else: assert isinstance(str(url), unicode) assert isinstance(bytes(url), bytes) def test_idna_corners(self): text = u'http://abé.com/' url = URL.from_text(text) assert url.to_iri().host == u'abé.com' assert url.to_uri().host == u'xn--ab-cja.com' url = URL.from_text("http://ドメイン.テスト.co.jp#test") assert url.to_iri().host == u'ドメイン.テスト.co.jp' assert url.to_uri().host == u'xn--eckwd4c7c.xn--zckzah.co.jp' assert url.to_uri().get_decoded_url().host == u'ドメイン.テスト.co.jp' assert URL.from_text('http://Example.com').to_uri().get_decoded_url().host == 'example.com' ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/hyperlink-19.0.0.dist-info/DESCRIPTION.rst ================================================ The humble, but powerful, URL runs everything around us. Chances are you've used several just to read this text. Hyperlink is a featureful, pure-Python implementation of the URL, with an emphasis on correctness. BSD licensed. See the docs at http://hyperlink.readthedocs.io. ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/hyperlink-19.0.0.dist-info/INSTALLER ================================================ pip ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/hyperlink-19.0.0.dist-info/METADATA ================================================ Metadata-Version: 2.0 Name: hyperlink Version: 19.0.0 Summary: A featureful, immutable, and correct URL for Python. Home-page: https://github.com/python-hyper/hyperlink Author: Mahmoud Hashemi and Glyph Lefkowitz Author-email: mahmoud@hatnote.com License: MIT Platform: any Classifier: Topic :: Utilities Classifier: Intended Audience :: Developers Classifier: Topic :: Software Development :: Libraries Classifier: Development Status :: 5 - Production/Stable Classifier: Programming Language :: Python :: 2.6 Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3.4 Classifier: Programming Language :: Python :: 3.5 Classifier: Programming Language :: Python :: 3.6 Classifier: Programming Language :: Python :: Implementation :: PyPy Requires-Dist: idna (>=2.5) The humble, but powerful, URL runs everything around us. Chances are you've used several just to read this text. Hyperlink is a featureful, pure-Python implementation of the URL, with an emphasis on correctness. BSD licensed. See the docs at http://hyperlink.readthedocs.io. ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/hyperlink-19.0.0.dist-info/RECORD ================================================ hyperlink-19.0.0.dist-info/DESCRIPTION.rst,sha256=a-0GCP8glYZ0Ysq4Y0mPEe6VJHqJNsGdheikkI7rwCo,279 hyperlink-19.0.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 hyperlink-19.0.0.dist-info/METADATA,sha256=y172hVTAqkayU3cFJRIJNy5At7oX9iecXN70uD1tY68,1087 hyperlink-19.0.0.dist-info/RECORD,, hyperlink-19.0.0.dist-info/WHEEL,sha256=5wvfB7GvgZAbKBSE9uX9Zbi6LCL-_KgezgHblXhCRnM,113 hyperlink-19.0.0.dist-info/metadata.json,sha256=JAh7SySskyDcNAPuBXetb6bTuS_-euZRkk75-LVtNBI,983 hyperlink-19.0.0.dist-info/top_level.txt,sha256=qKx9FGU_zxD9mGqiFgleNejfO4AwPY7duhQPaZ30U_M,10 hyperlink/__init__.py,sha256=OFqG_8hDTyyc8MmhVR-LyXL-aShz_Y9Qg98__-vcfTE,302 hyperlink/__pycache__/__init__.cpython-36.pyc,, hyperlink/__pycache__/_url.cpython-36.pyc,, hyperlink/_url.py,sha256=JW1raJr9hSmMyqDi_1GTgo0oes2RGL_zsEXhkaQLHKE,72479 hyperlink/test/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 hyperlink/test/__pycache__/__init__.cpython-36.pyc,, hyperlink/test/__pycache__/common.cpython-36.pyc,, hyperlink/test/__pycache__/test_common.cpython-36.pyc,, hyperlink/test/__pycache__/test_decoded_url.cpython-36.pyc,, hyperlink/test/__pycache__/test_parse.cpython-36.pyc,, hyperlink/test/__pycache__/test_scheme_registration.cpython-36.pyc,, hyperlink/test/__pycache__/test_url.cpython-36.pyc,, hyperlink/test/common.py,sha256=fZ0gLTlEC1YFnlyn8Hc7_aJJCEGadL1Glw3BVtIvOkQ,2108 hyperlink/test/test_common.py,sha256=6wiI5TjCYO0cyJwPXSL3TFTlkaSyGYGem5_uGIN-6p8,3399 hyperlink/test/test_decoded_url.py,sha256=2aF0fxCJXVjSdownHyD7y-HMnlsnRnsHl4RPOPdKYpM,6259 hyperlink/test/test_parse.py,sha256=HOF7Ns2tGnXUDrX5i8apyVEfnqsiuCtHu2_9uueY5xg,1081 hyperlink/test/test_scheme_registration.py,sha256=cRlrJVt3aFCAYOpz6rqSf9YHFBgjsimbfNdW8PYqbfM,2328 hyperlink/test/test_url.py,sha256=a8mHV7_VfsW4_Uim13q3PSvmBCMLHut_lu9b4zFv8W4,47162 ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/hyperlink-19.0.0.dist-info/WHEEL ================================================ Wheel-Version: 1.0 Generator: bdist_wheel (0.30.0.a0) Root-Is-Purelib: true Tag: py2-none-any Tag: py3-none-any ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/hyperlink-19.0.0.dist-info/metadata.json ================================================ {"classifiers": ["Topic :: Utilities", "Intended Audience :: Developers", "Topic :: Software Development :: Libraries", "Development Status :: 5 - Production/Stable", "Programming Language :: Python :: 2.6", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3.4", "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: Implementation :: PyPy"], "extensions": {"python.details": {"contacts": [{"email": "mahmoud@hatnote.com", "name": "Mahmoud Hashemi and Glyph Lefkowitz", "role": "author"}], "document_names": {"description": "DESCRIPTION.rst"}, "project_urls": {"Home": "https://github.com/python-hyper/hyperlink"}}}, "extras": [], "generator": "bdist_wheel (0.30.0.a0)", "license": "MIT", "metadata_version": "2.0", "name": "hyperlink", "platform": "any", "run_requires": [{"requires": ["idna (>=2.5)"]}], "summary": "A featureful, immutable, and correct URL for Python.", "version": "19.0.0"} ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/hyperlink-19.0.0.dist-info/top_level.txt ================================================ hyperlink ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/idna/__init__.py ================================================ from .package_data import __version__ from .core import * ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/idna/codec.py ================================================ from .core import encode, decode, alabel, ulabel, IDNAError import codecs import re _unicode_dots_re = re.compile(u'[\u002e\u3002\uff0e\uff61]') class Codec(codecs.Codec): def encode(self, data, errors='strict'): if errors != 'strict': raise IDNAError("Unsupported error handling \"{0}\"".format(errors)) if not data: return "", 0 return encode(data), len(data) def decode(self, data, errors='strict'): if errors != 'strict': raise IDNAError("Unsupported error handling \"{0}\"".format(errors)) if not data: return u"", 0 return decode(data), len(data) class IncrementalEncoder(codecs.BufferedIncrementalEncoder): def _buffer_encode(self, data, errors, final): if errors != 'strict': raise IDNAError("Unsupported error handling \"{0}\"".format(errors)) if not data: return ("", 0) labels = _unicode_dots_re.split(data) trailing_dot = u'' if labels: if not labels[-1]: trailing_dot = '.' del labels[-1] elif not final: # Keep potentially unfinished label until the next call del labels[-1] if labels: trailing_dot = '.' result = [] size = 0 for label in labels: result.append(alabel(label)) if size: size += 1 size += len(label) # Join with U+002E result = ".".join(result) + trailing_dot size += len(trailing_dot) return (result, size) class IncrementalDecoder(codecs.BufferedIncrementalDecoder): def _buffer_decode(self, data, errors, final): if errors != 'strict': raise IDNAError("Unsupported error handling \"{0}\"".format(errors)) if not data: return (u"", 0) # IDNA allows decoding to operate on Unicode strings, too. if isinstance(data, unicode): labels = _unicode_dots_re.split(data) else: # Must be ASCII string data = str(data) unicode(data, "ascii") labels = data.split(".") trailing_dot = u'' if labels: if not labels[-1]: trailing_dot = u'.' del labels[-1] elif not final: # Keep potentially unfinished label until the next call del labels[-1] if labels: trailing_dot = u'.' result = [] size = 0 for label in labels: result.append(ulabel(label)) if size: size += 1 size += len(label) result = u".".join(result) + trailing_dot size += len(trailing_dot) return (result, size) class StreamWriter(Codec, codecs.StreamWriter): pass class StreamReader(Codec, codecs.StreamReader): pass def getregentry(): return codecs.CodecInfo( name='idna', encode=Codec().encode, decode=Codec().decode, incrementalencoder=IncrementalEncoder, incrementaldecoder=IncrementalDecoder, streamwriter=StreamWriter, streamreader=StreamReader, ) ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/idna/compat.py ================================================ from .core import * from .codec import * def ToASCII(label): return encode(label) def ToUnicode(label): return decode(label) def nameprep(s): raise NotImplementedError("IDNA 2008 does not utilise nameprep protocol") ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/idna/core.py ================================================ from . import idnadata import bisect import unicodedata import re import sys from .intranges import intranges_contain _virama_combining_class = 9 _alabel_prefix = b'xn--' _unicode_dots_re = re.compile(u'[\u002e\u3002\uff0e\uff61]') if sys.version_info[0] == 3: unicode = str unichr = chr class IDNAError(UnicodeError): """ Base exception for all IDNA-encoding related problems """ pass class IDNABidiError(IDNAError): """ Exception when bidirectional requirements are not satisfied """ pass class InvalidCodepoint(IDNAError): """ Exception when a disallowed or unallocated codepoint is used """ pass class InvalidCodepointContext(IDNAError): """ Exception when the codepoint is not valid in the context it is used """ pass def _combining_class(cp): v = unicodedata.combining(unichr(cp)) if v == 0: if not unicodedata.name(unichr(cp)): raise ValueError("Unknown character in unicodedata") return v def _is_script(cp, script): return intranges_contain(ord(cp), idnadata.scripts[script]) def _punycode(s): return s.encode('punycode') def _unot(s): return 'U+{0:04X}'.format(s) def valid_label_length(label): if len(label) > 63: return False return True def valid_string_length(label, trailing_dot): if len(label) > (254 if trailing_dot else 253): return False return True def check_bidi(label, check_ltr=False): # Bidi rules should only be applied if string contains RTL characters bidi_label = False for (idx, cp) in enumerate(label, 1): direction = unicodedata.bidirectional(cp) if direction == '': # String likely comes from a newer version of Unicode raise IDNABidiError('Unknown directionality in label {0} at position {1}'.format(repr(label), idx)) if direction in ['R', 'AL', 'AN']: bidi_label = True if not bidi_label and not check_ltr: return True # Bidi rule 1 direction = unicodedata.bidirectional(label[0]) if direction in ['R', 'AL']: rtl = True elif direction == 'L': rtl = False else: raise IDNABidiError('First codepoint in label {0} must be directionality L, R or AL'.format(repr(label))) valid_ending = False number_type = False for (idx, cp) in enumerate(label, 1): direction = unicodedata.bidirectional(cp) if rtl: # Bidi rule 2 if not direction in ['R', 'AL', 'AN', 'EN', 'ES', 'CS', 'ET', 'ON', 'BN', 'NSM']: raise IDNABidiError('Invalid direction for codepoint at position {0} in a right-to-left label'.format(idx)) # Bidi rule 3 if direction in ['R', 'AL', 'EN', 'AN']: valid_ending = True elif direction != 'NSM': valid_ending = False # Bidi rule 4 if direction in ['AN', 'EN']: if not number_type: number_type = direction else: if number_type != direction: raise IDNABidiError('Can not mix numeral types in a right-to-left label') else: # Bidi rule 5 if not direction in ['L', 'EN', 'ES', 'CS', 'ET', 'ON', 'BN', 'NSM']: raise IDNABidiError('Invalid direction for codepoint at position {0} in a left-to-right label'.format(idx)) # Bidi rule 6 if direction in ['L', 'EN']: valid_ending = True elif direction != 'NSM': valid_ending = False if not valid_ending: raise IDNABidiError('Label ends with illegal codepoint directionality') return True def check_initial_combiner(label): if unicodedata.category(label[0])[0] == 'M': raise IDNAError('Label begins with an illegal combining character') return True def check_hyphen_ok(label): if label[2:4] == '--': raise IDNAError('Label has disallowed hyphens in 3rd and 4th position') if label[0] == '-' or label[-1] == '-': raise IDNAError('Label must not start or end with a hyphen') return True def check_nfc(label): if unicodedata.normalize('NFC', label) != label: raise IDNAError('Label must be in Normalization Form C') def valid_contextj(label, pos): cp_value = ord(label[pos]) if cp_value == 0x200c: if pos > 0: if _combining_class(ord(label[pos - 1])) == _virama_combining_class: return True ok = False for i in range(pos-1, -1, -1): joining_type = idnadata.joining_types.get(ord(label[i])) if joining_type == ord('T'): continue if joining_type in [ord('L'), ord('D')]: ok = True break if not ok: return False ok = False for i in range(pos+1, len(label)): joining_type = idnadata.joining_types.get(ord(label[i])) if joining_type == ord('T'): continue if joining_type in [ord('R'), ord('D')]: ok = True break return ok if cp_value == 0x200d: if pos > 0: if _combining_class(ord(label[pos - 1])) == _virama_combining_class: return True return False else: return False def valid_contexto(label, pos, exception=False): cp_value = ord(label[pos]) if cp_value == 0x00b7: if 0 < pos < len(label)-1: if ord(label[pos - 1]) == 0x006c and ord(label[pos + 1]) == 0x006c: return True return False elif cp_value == 0x0375: if pos < len(label)-1 and len(label) > 1: return _is_script(label[pos + 1], 'Greek') return False elif cp_value == 0x05f3 or cp_value == 0x05f4: if pos > 0: return _is_script(label[pos - 1], 'Hebrew') return False elif cp_value == 0x30fb: for cp in label: if cp == u'\u30fb': continue if _is_script(cp, 'Hiragana') or _is_script(cp, 'Katakana') or _is_script(cp, 'Han'): return True return False elif 0x660 <= cp_value <= 0x669: for cp in label: if 0x6f0 <= ord(cp) <= 0x06f9: return False return True elif 0x6f0 <= cp_value <= 0x6f9: for cp in label: if 0x660 <= ord(cp) <= 0x0669: return False return True def check_label(label): if isinstance(label, (bytes, bytearray)): label = label.decode('utf-8') if len(label) == 0: raise IDNAError('Empty Label') check_nfc(label) check_hyphen_ok(label) check_initial_combiner(label) for (pos, cp) in enumerate(label): cp_value = ord(cp) if intranges_contain(cp_value, idnadata.codepoint_classes['PVALID']): continue elif intranges_contain(cp_value, idnadata.codepoint_classes['CONTEXTJ']): try: if not valid_contextj(label, pos): raise InvalidCodepointContext('Joiner {0} not allowed at position {1} in {2}'.format( _unot(cp_value), pos+1, repr(label))) except ValueError: raise IDNAError('Unknown codepoint adjacent to joiner {0} at position {1} in {2}'.format( _unot(cp_value), pos+1, repr(label))) elif intranges_contain(cp_value, idnadata.codepoint_classes['CONTEXTO']): if not valid_contexto(label, pos): raise InvalidCodepointContext('Codepoint {0} not allowed at position {1} in {2}'.format(_unot(cp_value), pos+1, repr(label))) else: raise InvalidCodepoint('Codepoint {0} at position {1} of {2} not allowed'.format(_unot(cp_value), pos+1, repr(label))) check_bidi(label) def alabel(label): try: label = label.encode('ascii') ulabel(label) if not valid_label_length(label): raise IDNAError('Label too long') return label except UnicodeEncodeError: pass if not label: raise IDNAError('No Input') label = unicode(label) check_label(label) label = _punycode(label) label = _alabel_prefix + label if not valid_label_length(label): raise IDNAError('Label too long') return label def ulabel(label): if not isinstance(label, (bytes, bytearray)): try: label = label.encode('ascii') except UnicodeEncodeError: check_label(label) return label label = label.lower() if label.startswith(_alabel_prefix): label = label[len(_alabel_prefix):] else: check_label(label) return label.decode('ascii') label = label.decode('punycode') check_label(label) return label def uts46_remap(domain, std3_rules=True, transitional=False): """Re-map the characters in the string according to UTS46 processing.""" from .uts46data import uts46data output = u"" try: for pos, char in enumerate(domain): code_point = ord(char) uts46row = uts46data[code_point if code_point < 256 else bisect.bisect_left(uts46data, (code_point, "Z")) - 1] status = uts46row[1] replacement = uts46row[2] if len(uts46row) == 3 else None if (status == "V" or (status == "D" and not transitional) or (status == "3" and not std3_rules and replacement is None)): output += char elif replacement is not None and (status == "M" or (status == "3" and not std3_rules) or (status == "D" and transitional)): output += replacement elif status != "I": raise IndexError() return unicodedata.normalize("NFC", output) except IndexError: raise InvalidCodepoint( "Codepoint {0} not allowed at position {1} in {2}".format( _unot(code_point), pos + 1, repr(domain))) def encode(s, strict=False, uts46=False, std3_rules=False, transitional=False): if isinstance(s, (bytes, bytearray)): s = s.decode("ascii") if uts46: s = uts46_remap(s, std3_rules, transitional) trailing_dot = False result = [] if strict: labels = s.split('.') else: labels = _unicode_dots_re.split(s) if not labels or labels == ['']: raise IDNAError('Empty domain') if labels[-1] == '': del labels[-1] trailing_dot = True for label in labels: s = alabel(label) if s: result.append(s) else: raise IDNAError('Empty label') if trailing_dot: result.append(b'') s = b'.'.join(result) if not valid_string_length(s, trailing_dot): raise IDNAError('Domain too long') return s def decode(s, strict=False, uts46=False, std3_rules=False): if isinstance(s, (bytes, bytearray)): s = s.decode("ascii") if uts46: s = uts46_remap(s, std3_rules, False) trailing_dot = False result = [] if not strict: labels = _unicode_dots_re.split(s) else: labels = s.split(u'.') if not labels or labels == ['']: raise IDNAError('Empty domain') if not labels[-1]: del labels[-1] trailing_dot = True for label in labels: s = ulabel(label) if s: result.append(s) else: raise IDNAError('Empty label') if trailing_dot: result.append(u'') return u'.'.join(result) ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/idna/idnadata.py ================================================ # This file is automatically generated by tools/idna-data __version__ = "11.0.0" scripts = { 'Greek': ( 0x37000000374, 0x37500000378, 0x37a0000037e, 0x37f00000380, 0x38400000385, 0x38600000387, 0x3880000038b, 0x38c0000038d, 0x38e000003a2, 0x3a3000003e2, 0x3f000000400, 0x1d2600001d2b, 0x1d5d00001d62, 0x1d6600001d6b, 0x1dbf00001dc0, 0x1f0000001f16, 0x1f1800001f1e, 0x1f2000001f46, 0x1f4800001f4e, 0x1f5000001f58, 0x1f5900001f5a, 0x1f5b00001f5c, 0x1f5d00001f5e, 0x1f5f00001f7e, 0x1f8000001fb5, 0x1fb600001fc5, 0x1fc600001fd4, 0x1fd600001fdc, 0x1fdd00001ff0, 0x1ff200001ff5, 0x1ff600001fff, 0x212600002127, 0xab650000ab66, 0x101400001018f, 0x101a0000101a1, 0x1d2000001d246, ), 'Han': ( 0x2e8000002e9a, 0x2e9b00002ef4, 0x2f0000002fd6, 0x300500003006, 0x300700003008, 0x30210000302a, 0x30380000303c, 0x340000004db6, 0x4e0000009ff0, 0xf9000000fa6e, 0xfa700000fada, 0x200000002a6d7, 0x2a7000002b735, 0x2b7400002b81e, 0x2b8200002cea2, 0x2ceb00002ebe1, 0x2f8000002fa1e, ), 'Hebrew': ( 0x591000005c8, 0x5d0000005eb, 0x5ef000005f5, 0xfb1d0000fb37, 0xfb380000fb3d, 0xfb3e0000fb3f, 0xfb400000fb42, 0xfb430000fb45, 0xfb460000fb50, ), 'Hiragana': ( 0x304100003097, 0x309d000030a0, 0x1b0010001b11f, 0x1f2000001f201, ), 'Katakana': ( 0x30a1000030fb, 0x30fd00003100, 0x31f000003200, 0x32d0000032ff, 0x330000003358, 0xff660000ff70, 0xff710000ff9e, 0x1b0000001b001, ), } joining_types = { 0x600: 85, 0x601: 85, 0x602: 85, 0x603: 85, 0x604: 85, 0x605: 85, 0x608: 85, 0x60b: 85, 0x620: 68, 0x621: 85, 0x622: 82, 0x623: 82, 0x624: 82, 0x625: 82, 0x626: 68, 0x627: 82, 0x628: 68, 0x629: 82, 0x62a: 68, 0x62b: 68, 0x62c: 68, 0x62d: 68, 0x62e: 68, 0x62f: 82, 0x630: 82, 0x631: 82, 0x632: 82, 0x633: 68, 0x634: 68, 0x635: 68, 0x636: 68, 0x637: 68, 0x638: 68, 0x639: 68, 0x63a: 68, 0x63b: 68, 0x63c: 68, 0x63d: 68, 0x63e: 68, 0x63f: 68, 0x640: 67, 0x641: 68, 0x642: 68, 0x643: 68, 0x644: 68, 0x645: 68, 0x646: 68, 0x647: 68, 0x648: 82, 0x649: 68, 0x64a: 68, 0x66e: 68, 0x66f: 68, 0x671: 82, 0x672: 82, 0x673: 82, 0x674: 85, 0x675: 82, 0x676: 82, 0x677: 82, 0x678: 68, 0x679: 68, 0x67a: 68, 0x67b: 68, 0x67c: 68, 0x67d: 68, 0x67e: 68, 0x67f: 68, 0x680: 68, 0x681: 68, 0x682: 68, 0x683: 68, 0x684: 68, 0x685: 68, 0x686: 68, 0x687: 68, 0x688: 82, 0x689: 82, 0x68a: 82, 0x68b: 82, 0x68c: 82, 0x68d: 82, 0x68e: 82, 0x68f: 82, 0x690: 82, 0x691: 82, 0x692: 82, 0x693: 82, 0x694: 82, 0x695: 82, 0x696: 82, 0x697: 82, 0x698: 82, 0x699: 82, 0x69a: 68, 0x69b: 68, 0x69c: 68, 0x69d: 68, 0x69e: 68, 0x69f: 68, 0x6a0: 68, 0x6a1: 68, 0x6a2: 68, 0x6a3: 68, 0x6a4: 68, 0x6a5: 68, 0x6a6: 68, 0x6a7: 68, 0x6a8: 68, 0x6a9: 68, 0x6aa: 68, 0x6ab: 68, 0x6ac: 68, 0x6ad: 68, 0x6ae: 68, 0x6af: 68, 0x6b0: 68, 0x6b1: 68, 0x6b2: 68, 0x6b3: 68, 0x6b4: 68, 0x6b5: 68, 0x6b6: 68, 0x6b7: 68, 0x6b8: 68, 0x6b9: 68, 0x6ba: 68, 0x6bb: 68, 0x6bc: 68, 0x6bd: 68, 0x6be: 68, 0x6bf: 68, 0x6c0: 82, 0x6c1: 68, 0x6c2: 68, 0x6c3: 82, 0x6c4: 82, 0x6c5: 82, 0x6c6: 82, 0x6c7: 82, 0x6c8: 82, 0x6c9: 82, 0x6ca: 82, 0x6cb: 82, 0x6cc: 68, 0x6cd: 82, 0x6ce: 68, 0x6cf: 82, 0x6d0: 68, 0x6d1: 68, 0x6d2: 82, 0x6d3: 82, 0x6d5: 82, 0x6dd: 85, 0x6ee: 82, 0x6ef: 82, 0x6fa: 68, 0x6fb: 68, 0x6fc: 68, 0x6ff: 68, 0x70f: 84, 0x710: 82, 0x712: 68, 0x713: 68, 0x714: 68, 0x715: 82, 0x716: 82, 0x717: 82, 0x718: 82, 0x719: 82, 0x71a: 68, 0x71b: 68, 0x71c: 68, 0x71d: 68, 0x71e: 82, 0x71f: 68, 0x720: 68, 0x721: 68, 0x722: 68, 0x723: 68, 0x724: 68, 0x725: 68, 0x726: 68, 0x727: 68, 0x728: 82, 0x729: 68, 0x72a: 82, 0x72b: 68, 0x72c: 82, 0x72d: 68, 0x72e: 68, 0x72f: 82, 0x74d: 82, 0x74e: 68, 0x74f: 68, 0x750: 68, 0x751: 68, 0x752: 68, 0x753: 68, 0x754: 68, 0x755: 68, 0x756: 68, 0x757: 68, 0x758: 68, 0x759: 82, 0x75a: 82, 0x75b: 82, 0x75c: 68, 0x75d: 68, 0x75e: 68, 0x75f: 68, 0x760: 68, 0x761: 68, 0x762: 68, 0x763: 68, 0x764: 68, 0x765: 68, 0x766: 68, 0x767: 68, 0x768: 68, 0x769: 68, 0x76a: 68, 0x76b: 82, 0x76c: 82, 0x76d: 68, 0x76e: 68, 0x76f: 68, 0x770: 68, 0x771: 82, 0x772: 68, 0x773: 82, 0x774: 82, 0x775: 68, 0x776: 68, 0x777: 68, 0x778: 82, 0x779: 82, 0x77a: 68, 0x77b: 68, 0x77c: 68, 0x77d: 68, 0x77e: 68, 0x77f: 68, 0x7ca: 68, 0x7cb: 68, 0x7cc: 68, 0x7cd: 68, 0x7ce: 68, 0x7cf: 68, 0x7d0: 68, 0x7d1: 68, 0x7d2: 68, 0x7d3: 68, 0x7d4: 68, 0x7d5: 68, 0x7d6: 68, 0x7d7: 68, 0x7d8: 68, 0x7d9: 68, 0x7da: 68, 0x7db: 68, 0x7dc: 68, 0x7dd: 68, 0x7de: 68, 0x7df: 68, 0x7e0: 68, 0x7e1: 68, 0x7e2: 68, 0x7e3: 68, 0x7e4: 68, 0x7e5: 68, 0x7e6: 68, 0x7e7: 68, 0x7e8: 68, 0x7e9: 68, 0x7ea: 68, 0x7fa: 67, 0x840: 82, 0x841: 68, 0x842: 68, 0x843: 68, 0x844: 68, 0x845: 68, 0x846: 82, 0x847: 82, 0x848: 68, 0x849: 82, 0x84a: 68, 0x84b: 68, 0x84c: 68, 0x84d: 68, 0x84e: 68, 0x84f: 68, 0x850: 68, 0x851: 68, 0x852: 68, 0x853: 68, 0x854: 82, 0x855: 68, 0x856: 85, 0x857: 85, 0x858: 85, 0x860: 68, 0x861: 85, 0x862: 68, 0x863: 68, 0x864: 68, 0x865: 68, 0x866: 85, 0x867: 82, 0x868: 68, 0x869: 82, 0x86a: 82, 0x8a0: 68, 0x8a1: 68, 0x8a2: 68, 0x8a3: 68, 0x8a4: 68, 0x8a5: 68, 0x8a6: 68, 0x8a7: 68, 0x8a8: 68, 0x8a9: 68, 0x8aa: 82, 0x8ab: 82, 0x8ac: 82, 0x8ad: 85, 0x8ae: 82, 0x8af: 68, 0x8b0: 68, 0x8b1: 82, 0x8b2: 82, 0x8b3: 68, 0x8b4: 68, 0x8b6: 68, 0x8b7: 68, 0x8b8: 68, 0x8b9: 82, 0x8ba: 68, 0x8bb: 68, 0x8bc: 68, 0x8bd: 68, 0x8e2: 85, 0x1806: 85, 0x1807: 68, 0x180a: 67, 0x180e: 85, 0x1820: 68, 0x1821: 68, 0x1822: 68, 0x1823: 68, 0x1824: 68, 0x1825: 68, 0x1826: 68, 0x1827: 68, 0x1828: 68, 0x1829: 68, 0x182a: 68, 0x182b: 68, 0x182c: 68, 0x182d: 68, 0x182e: 68, 0x182f: 68, 0x1830: 68, 0x1831: 68, 0x1832: 68, 0x1833: 68, 0x1834: 68, 0x1835: 68, 0x1836: 68, 0x1837: 68, 0x1838: 68, 0x1839: 68, 0x183a: 68, 0x183b: 68, 0x183c: 68, 0x183d: 68, 0x183e: 68, 0x183f: 68, 0x1840: 68, 0x1841: 68, 0x1842: 68, 0x1843: 68, 0x1844: 68, 0x1845: 68, 0x1846: 68, 0x1847: 68, 0x1848: 68, 0x1849: 68, 0x184a: 68, 0x184b: 68, 0x184c: 68, 0x184d: 68, 0x184e: 68, 0x184f: 68, 0x1850: 68, 0x1851: 68, 0x1852: 68, 0x1853: 68, 0x1854: 68, 0x1855: 68, 0x1856: 68, 0x1857: 68, 0x1858: 68, 0x1859: 68, 0x185a: 68, 0x185b: 68, 0x185c: 68, 0x185d: 68, 0x185e: 68, 0x185f: 68, 0x1860: 68, 0x1861: 68, 0x1862: 68, 0x1863: 68, 0x1864: 68, 0x1865: 68, 0x1866: 68, 0x1867: 68, 0x1868: 68, 0x1869: 68, 0x186a: 68, 0x186b: 68, 0x186c: 68, 0x186d: 68, 0x186e: 68, 0x186f: 68, 0x1870: 68, 0x1871: 68, 0x1872: 68, 0x1873: 68, 0x1874: 68, 0x1875: 68, 0x1876: 68, 0x1877: 68, 0x1878: 68, 0x1880: 85, 0x1881: 85, 0x1882: 85, 0x1883: 85, 0x1884: 85, 0x1885: 84, 0x1886: 84, 0x1887: 68, 0x1888: 68, 0x1889: 68, 0x188a: 68, 0x188b: 68, 0x188c: 68, 0x188d: 68, 0x188e: 68, 0x188f: 68, 0x1890: 68, 0x1891: 68, 0x1892: 68, 0x1893: 68, 0x1894: 68, 0x1895: 68, 0x1896: 68, 0x1897: 68, 0x1898: 68, 0x1899: 68, 0x189a: 68, 0x189b: 68, 0x189c: 68, 0x189d: 68, 0x189e: 68, 0x189f: 68, 0x18a0: 68, 0x18a1: 68, 0x18a2: 68, 0x18a3: 68, 0x18a4: 68, 0x18a5: 68, 0x18a6: 68, 0x18a7: 68, 0x18a8: 68, 0x18aa: 68, 0x200c: 85, 0x200d: 67, 0x202f: 85, 0x2066: 85, 0x2067: 85, 0x2068: 85, 0x2069: 85, 0xa840: 68, 0xa841: 68, 0xa842: 68, 0xa843: 68, 0xa844: 68, 0xa845: 68, 0xa846: 68, 0xa847: 68, 0xa848: 68, 0xa849: 68, 0xa84a: 68, 0xa84b: 68, 0xa84c: 68, 0xa84d: 68, 0xa84e: 68, 0xa84f: 68, 0xa850: 68, 0xa851: 68, 0xa852: 68, 0xa853: 68, 0xa854: 68, 0xa855: 68, 0xa856: 68, 0xa857: 68, 0xa858: 68, 0xa859: 68, 0xa85a: 68, 0xa85b: 68, 0xa85c: 68, 0xa85d: 68, 0xa85e: 68, 0xa85f: 68, 0xa860: 68, 0xa861: 68, 0xa862: 68, 0xa863: 68, 0xa864: 68, 0xa865: 68, 0xa866: 68, 0xa867: 68, 0xa868: 68, 0xa869: 68, 0xa86a: 68, 0xa86b: 68, 0xa86c: 68, 0xa86d: 68, 0xa86e: 68, 0xa86f: 68, 0xa870: 68, 0xa871: 68, 0xa872: 76, 0xa873: 85, 0x10ac0: 68, 0x10ac1: 68, 0x10ac2: 68, 0x10ac3: 68, 0x10ac4: 68, 0x10ac5: 82, 0x10ac6: 85, 0x10ac7: 82, 0x10ac8: 85, 0x10ac9: 82, 0x10aca: 82, 0x10acb: 85, 0x10acc: 85, 0x10acd: 76, 0x10ace: 82, 0x10acf: 82, 0x10ad0: 82, 0x10ad1: 82, 0x10ad2: 82, 0x10ad3: 68, 0x10ad4: 68, 0x10ad5: 68, 0x10ad6: 68, 0x10ad7: 76, 0x10ad8: 68, 0x10ad9: 68, 0x10ada: 68, 0x10adb: 68, 0x10adc: 68, 0x10add: 82, 0x10ade: 68, 0x10adf: 68, 0x10ae0: 68, 0x10ae1: 82, 0x10ae2: 85, 0x10ae3: 85, 0x10ae4: 82, 0x10aeb: 68, 0x10aec: 68, 0x10aed: 68, 0x10aee: 68, 0x10aef: 82, 0x10b80: 68, 0x10b81: 82, 0x10b82: 68, 0x10b83: 82, 0x10b84: 82, 0x10b85: 82, 0x10b86: 68, 0x10b87: 68, 0x10b88: 68, 0x10b89: 82, 0x10b8a: 68, 0x10b8b: 68, 0x10b8c: 82, 0x10b8d: 68, 0x10b8e: 82, 0x10b8f: 82, 0x10b90: 68, 0x10b91: 82, 0x10ba9: 82, 0x10baa: 82, 0x10bab: 82, 0x10bac: 82, 0x10bad: 68, 0x10bae: 68, 0x10baf: 85, 0x10d00: 76, 0x10d01: 68, 0x10d02: 68, 0x10d03: 68, 0x10d04: 68, 0x10d05: 68, 0x10d06: 68, 0x10d07: 68, 0x10d08: 68, 0x10d09: 68, 0x10d0a: 68, 0x10d0b: 68, 0x10d0c: 68, 0x10d0d: 68, 0x10d0e: 68, 0x10d0f: 68, 0x10d10: 68, 0x10d11: 68, 0x10d12: 68, 0x10d13: 68, 0x10d14: 68, 0x10d15: 68, 0x10d16: 68, 0x10d17: 68, 0x10d18: 68, 0x10d19: 68, 0x10d1a: 68, 0x10d1b: 68, 0x10d1c: 68, 0x10d1d: 68, 0x10d1e: 68, 0x10d1f: 68, 0x10d20: 68, 0x10d21: 68, 0x10d22: 82, 0x10d23: 68, 0x10f30: 68, 0x10f31: 68, 0x10f32: 68, 0x10f33: 82, 0x10f34: 68, 0x10f35: 68, 0x10f36: 68, 0x10f37: 68, 0x10f38: 68, 0x10f39: 68, 0x10f3a: 68, 0x10f3b: 68, 0x10f3c: 68, 0x10f3d: 68, 0x10f3e: 68, 0x10f3f: 68, 0x10f40: 68, 0x10f41: 68, 0x10f42: 68, 0x10f43: 68, 0x10f44: 68, 0x10f45: 85, 0x10f51: 68, 0x10f52: 68, 0x10f53: 68, 0x10f54: 82, 0x110bd: 85, 0x110cd: 85, 0x1e900: 68, 0x1e901: 68, 0x1e902: 68, 0x1e903: 68, 0x1e904: 68, 0x1e905: 68, 0x1e906: 68, 0x1e907: 68, 0x1e908: 68, 0x1e909: 68, 0x1e90a: 68, 0x1e90b: 68, 0x1e90c: 68, 0x1e90d: 68, 0x1e90e: 68, 0x1e90f: 68, 0x1e910: 68, 0x1e911: 68, 0x1e912: 68, 0x1e913: 68, 0x1e914: 68, 0x1e915: 68, 0x1e916: 68, 0x1e917: 68, 0x1e918: 68, 0x1e919: 68, 0x1e91a: 68, 0x1e91b: 68, 0x1e91c: 68, 0x1e91d: 68, 0x1e91e: 68, 0x1e91f: 68, 0x1e920: 68, 0x1e921: 68, 0x1e922: 68, 0x1e923: 68, 0x1e924: 68, 0x1e925: 68, 0x1e926: 68, 0x1e927: 68, 0x1e928: 68, 0x1e929: 68, 0x1e92a: 68, 0x1e92b: 68, 0x1e92c: 68, 0x1e92d: 68, 0x1e92e: 68, 0x1e92f: 68, 0x1e930: 68, 0x1e931: 68, 0x1e932: 68, 0x1e933: 68, 0x1e934: 68, 0x1e935: 68, 0x1e936: 68, 0x1e937: 68, 0x1e938: 68, 0x1e939: 68, 0x1e93a: 68, 0x1e93b: 68, 0x1e93c: 68, 0x1e93d: 68, 0x1e93e: 68, 0x1e93f: 68, 0x1e940: 68, 0x1e941: 68, 0x1e942: 68, 0x1e943: 68, } codepoint_classes = { 'PVALID': ( 0x2d0000002e, 0x300000003a, 0x610000007b, 0xdf000000f7, 0xf800000100, 0x10100000102, 0x10300000104, 0x10500000106, 0x10700000108, 0x1090000010a, 0x10b0000010c, 0x10d0000010e, 0x10f00000110, 0x11100000112, 0x11300000114, 0x11500000116, 0x11700000118, 0x1190000011a, 0x11b0000011c, 0x11d0000011e, 0x11f00000120, 0x12100000122, 0x12300000124, 0x12500000126, 0x12700000128, 0x1290000012a, 0x12b0000012c, 0x12d0000012e, 0x12f00000130, 0x13100000132, 0x13500000136, 0x13700000139, 0x13a0000013b, 0x13c0000013d, 0x13e0000013f, 0x14200000143, 0x14400000145, 0x14600000147, 0x14800000149, 0x14b0000014c, 0x14d0000014e, 0x14f00000150, 0x15100000152, 0x15300000154, 0x15500000156, 0x15700000158, 0x1590000015a, 0x15b0000015c, 0x15d0000015e, 0x15f00000160, 0x16100000162, 0x16300000164, 0x16500000166, 0x16700000168, 0x1690000016a, 0x16b0000016c, 0x16d0000016e, 0x16f00000170, 0x17100000172, 0x17300000174, 0x17500000176, 0x17700000178, 0x17a0000017b, 0x17c0000017d, 0x17e0000017f, 0x18000000181, 0x18300000184, 0x18500000186, 0x18800000189, 0x18c0000018e, 0x19200000193, 0x19500000196, 0x1990000019c, 0x19e0000019f, 0x1a1000001a2, 0x1a3000001a4, 0x1a5000001a6, 0x1a8000001a9, 0x1aa000001ac, 0x1ad000001ae, 0x1b0000001b1, 0x1b4000001b5, 0x1b6000001b7, 0x1b9000001bc, 0x1bd000001c4, 0x1ce000001cf, 0x1d0000001d1, 0x1d2000001d3, 0x1d4000001d5, 0x1d6000001d7, 0x1d8000001d9, 0x1da000001db, 0x1dc000001de, 0x1df000001e0, 0x1e1000001e2, 0x1e3000001e4, 0x1e5000001e6, 0x1e7000001e8, 0x1e9000001ea, 0x1eb000001ec, 0x1ed000001ee, 0x1ef000001f1, 0x1f5000001f6, 0x1f9000001fa, 0x1fb000001fc, 0x1fd000001fe, 0x1ff00000200, 0x20100000202, 0x20300000204, 0x20500000206, 0x20700000208, 0x2090000020a, 0x20b0000020c, 0x20d0000020e, 0x20f00000210, 0x21100000212, 0x21300000214, 0x21500000216, 0x21700000218, 0x2190000021a, 0x21b0000021c, 0x21d0000021e, 0x21f00000220, 0x22100000222, 0x22300000224, 0x22500000226, 0x22700000228, 0x2290000022a, 0x22b0000022c, 0x22d0000022e, 0x22f00000230, 0x23100000232, 0x2330000023a, 0x23c0000023d, 0x23f00000241, 0x24200000243, 0x24700000248, 0x2490000024a, 0x24b0000024c, 0x24d0000024e, 0x24f000002b0, 0x2b9000002c2, 0x2c6000002d2, 0x2ec000002ed, 0x2ee000002ef, 0x30000000340, 0x34200000343, 0x3460000034f, 0x35000000370, 0x37100000372, 0x37300000374, 0x37700000378, 0x37b0000037e, 0x39000000391, 0x3ac000003cf, 0x3d7000003d8, 0x3d9000003da, 0x3db000003dc, 0x3dd000003de, 0x3df000003e0, 0x3e1000003e2, 0x3e3000003e4, 0x3e5000003e6, 0x3e7000003e8, 0x3e9000003ea, 0x3eb000003ec, 0x3ed000003ee, 0x3ef000003f0, 0x3f3000003f4, 0x3f8000003f9, 0x3fb000003fd, 0x43000000460, 0x46100000462, 0x46300000464, 0x46500000466, 0x46700000468, 0x4690000046a, 0x46b0000046c, 0x46d0000046e, 0x46f00000470, 0x47100000472, 0x47300000474, 0x47500000476, 0x47700000478, 0x4790000047a, 0x47b0000047c, 0x47d0000047e, 0x47f00000480, 0x48100000482, 0x48300000488, 0x48b0000048c, 0x48d0000048e, 0x48f00000490, 0x49100000492, 0x49300000494, 0x49500000496, 0x49700000498, 0x4990000049a, 0x49b0000049c, 0x49d0000049e, 0x49f000004a0, 0x4a1000004a2, 0x4a3000004a4, 0x4a5000004a6, 0x4a7000004a8, 0x4a9000004aa, 0x4ab000004ac, 0x4ad000004ae, 0x4af000004b0, 0x4b1000004b2, 0x4b3000004b4, 0x4b5000004b6, 0x4b7000004b8, 0x4b9000004ba, 0x4bb000004bc, 0x4bd000004be, 0x4bf000004c0, 0x4c2000004c3, 0x4c4000004c5, 0x4c6000004c7, 0x4c8000004c9, 0x4ca000004cb, 0x4cc000004cd, 0x4ce000004d0, 0x4d1000004d2, 0x4d3000004d4, 0x4d5000004d6, 0x4d7000004d8, 0x4d9000004da, 0x4db000004dc, 0x4dd000004de, 0x4df000004e0, 0x4e1000004e2, 0x4e3000004e4, 0x4e5000004e6, 0x4e7000004e8, 0x4e9000004ea, 0x4eb000004ec, 0x4ed000004ee, 0x4ef000004f0, 0x4f1000004f2, 0x4f3000004f4, 0x4f5000004f6, 0x4f7000004f8, 0x4f9000004fa, 0x4fb000004fc, 0x4fd000004fe, 0x4ff00000500, 0x50100000502, 0x50300000504, 0x50500000506, 0x50700000508, 0x5090000050a, 0x50b0000050c, 0x50d0000050e, 0x50f00000510, 0x51100000512, 0x51300000514, 0x51500000516, 0x51700000518, 0x5190000051a, 0x51b0000051c, 0x51d0000051e, 0x51f00000520, 0x52100000522, 0x52300000524, 0x52500000526, 0x52700000528, 0x5290000052a, 0x52b0000052c, 0x52d0000052e, 0x52f00000530, 0x5590000055a, 0x56000000587, 0x58800000589, 0x591000005be, 0x5bf000005c0, 0x5c1000005c3, 0x5c4000005c6, 0x5c7000005c8, 0x5d0000005eb, 0x5ef000005f3, 0x6100000061b, 0x62000000640, 0x64100000660, 0x66e00000675, 0x679000006d4, 0x6d5000006dd, 0x6df000006e9, 0x6ea000006f0, 0x6fa00000700, 0x7100000074b, 0x74d000007b2, 0x7c0000007f6, 0x7fd000007fe, 0x8000000082e, 0x8400000085c, 0x8600000086b, 0x8a0000008b5, 0x8b6000008be, 0x8d3000008e2, 0x8e300000958, 0x96000000964, 0x96600000970, 0x97100000984, 0x9850000098d, 0x98f00000991, 0x993000009a9, 0x9aa000009b1, 0x9b2000009b3, 0x9b6000009ba, 0x9bc000009c5, 0x9c7000009c9, 0x9cb000009cf, 0x9d7000009d8, 0x9e0000009e4, 0x9e6000009f2, 0x9fc000009fd, 0x9fe000009ff, 0xa0100000a04, 0xa0500000a0b, 0xa0f00000a11, 0xa1300000a29, 0xa2a00000a31, 0xa3200000a33, 0xa3500000a36, 0xa3800000a3a, 0xa3c00000a3d, 0xa3e00000a43, 0xa4700000a49, 0xa4b00000a4e, 0xa5100000a52, 0xa5c00000a5d, 0xa6600000a76, 0xa8100000a84, 0xa8500000a8e, 0xa8f00000a92, 0xa9300000aa9, 0xaaa00000ab1, 0xab200000ab4, 0xab500000aba, 0xabc00000ac6, 0xac700000aca, 0xacb00000ace, 0xad000000ad1, 0xae000000ae4, 0xae600000af0, 0xaf900000b00, 0xb0100000b04, 0xb0500000b0d, 0xb0f00000b11, 0xb1300000b29, 0xb2a00000b31, 0xb3200000b34, 0xb3500000b3a, 0xb3c00000b45, 0xb4700000b49, 0xb4b00000b4e, 0xb5600000b58, 0xb5f00000b64, 0xb6600000b70, 0xb7100000b72, 0xb8200000b84, 0xb8500000b8b, 0xb8e00000b91, 0xb9200000b96, 0xb9900000b9b, 0xb9c00000b9d, 0xb9e00000ba0, 0xba300000ba5, 0xba800000bab, 0xbae00000bba, 0xbbe00000bc3, 0xbc600000bc9, 0xbca00000bce, 0xbd000000bd1, 0xbd700000bd8, 0xbe600000bf0, 0xc0000000c0d, 0xc0e00000c11, 0xc1200000c29, 0xc2a00000c3a, 0xc3d00000c45, 0xc4600000c49, 0xc4a00000c4e, 0xc5500000c57, 0xc5800000c5b, 0xc6000000c64, 0xc6600000c70, 0xc8000000c84, 0xc8500000c8d, 0xc8e00000c91, 0xc9200000ca9, 0xcaa00000cb4, 0xcb500000cba, 0xcbc00000cc5, 0xcc600000cc9, 0xcca00000cce, 0xcd500000cd7, 0xcde00000cdf, 0xce000000ce4, 0xce600000cf0, 0xcf100000cf3, 0xd0000000d04, 0xd0500000d0d, 0xd0e00000d11, 0xd1200000d45, 0xd4600000d49, 0xd4a00000d4f, 0xd5400000d58, 0xd5f00000d64, 0xd6600000d70, 0xd7a00000d80, 0xd8200000d84, 0xd8500000d97, 0xd9a00000db2, 0xdb300000dbc, 0xdbd00000dbe, 0xdc000000dc7, 0xdca00000dcb, 0xdcf00000dd5, 0xdd600000dd7, 0xdd800000de0, 0xde600000df0, 0xdf200000df4, 0xe0100000e33, 0xe3400000e3b, 0xe4000000e4f, 0xe5000000e5a, 0xe8100000e83, 0xe8400000e85, 0xe8700000e89, 0xe8a00000e8b, 0xe8d00000e8e, 0xe9400000e98, 0xe9900000ea0, 0xea100000ea4, 0xea500000ea6, 0xea700000ea8, 0xeaa00000eac, 0xead00000eb3, 0xeb400000eba, 0xebb00000ebe, 0xec000000ec5, 0xec600000ec7, 0xec800000ece, 0xed000000eda, 0xede00000ee0, 0xf0000000f01, 0xf0b00000f0c, 0xf1800000f1a, 0xf2000000f2a, 0xf3500000f36, 0xf3700000f38, 0xf3900000f3a, 0xf3e00000f43, 0xf4400000f48, 0xf4900000f4d, 0xf4e00000f52, 0xf5300000f57, 0xf5800000f5c, 0xf5d00000f69, 0xf6a00000f6d, 0xf7100000f73, 0xf7400000f75, 0xf7a00000f81, 0xf8200000f85, 0xf8600000f93, 0xf9400000f98, 0xf9900000f9d, 0xf9e00000fa2, 0xfa300000fa7, 0xfa800000fac, 0xfad00000fb9, 0xfba00000fbd, 0xfc600000fc7, 0x10000000104a, 0x10500000109e, 0x10d0000010fb, 0x10fd00001100, 0x120000001249, 0x124a0000124e, 0x125000001257, 0x125800001259, 0x125a0000125e, 0x126000001289, 0x128a0000128e, 0x1290000012b1, 0x12b2000012b6, 0x12b8000012bf, 0x12c0000012c1, 0x12c2000012c6, 0x12c8000012d7, 0x12d800001311, 0x131200001316, 0x13180000135b, 0x135d00001360, 0x138000001390, 0x13a0000013f6, 0x14010000166d, 0x166f00001680, 0x16810000169b, 0x16a0000016eb, 0x16f1000016f9, 0x17000000170d, 0x170e00001715, 0x172000001735, 0x174000001754, 0x17600000176d, 0x176e00001771, 0x177200001774, 0x1780000017b4, 0x17b6000017d4, 0x17d7000017d8, 0x17dc000017de, 0x17e0000017ea, 0x18100000181a, 0x182000001879, 0x1880000018ab, 0x18b0000018f6, 0x19000000191f, 0x19200000192c, 0x19300000193c, 0x19460000196e, 0x197000001975, 0x1980000019ac, 0x19b0000019ca, 0x19d0000019da, 0x1a0000001a1c, 0x1a2000001a5f, 0x1a6000001a7d, 0x1a7f00001a8a, 0x1a9000001a9a, 0x1aa700001aa8, 0x1ab000001abe, 0x1b0000001b4c, 0x1b5000001b5a, 0x1b6b00001b74, 0x1b8000001bf4, 0x1c0000001c38, 0x1c4000001c4a, 0x1c4d00001c7e, 0x1cd000001cd3, 0x1cd400001cfa, 0x1d0000001d2c, 0x1d2f00001d30, 0x1d3b00001d3c, 0x1d4e00001d4f, 0x1d6b00001d78, 0x1d7900001d9b, 0x1dc000001dfa, 0x1dfb00001e00, 0x1e0100001e02, 0x1e0300001e04, 0x1e0500001e06, 0x1e0700001e08, 0x1e0900001e0a, 0x1e0b00001e0c, 0x1e0d00001e0e, 0x1e0f00001e10, 0x1e1100001e12, 0x1e1300001e14, 0x1e1500001e16, 0x1e1700001e18, 0x1e1900001e1a, 0x1e1b00001e1c, 0x1e1d00001e1e, 0x1e1f00001e20, 0x1e2100001e22, 0x1e2300001e24, 0x1e2500001e26, 0x1e2700001e28, 0x1e2900001e2a, 0x1e2b00001e2c, 0x1e2d00001e2e, 0x1e2f00001e30, 0x1e3100001e32, 0x1e3300001e34, 0x1e3500001e36, 0x1e3700001e38, 0x1e3900001e3a, 0x1e3b00001e3c, 0x1e3d00001e3e, 0x1e3f00001e40, 0x1e4100001e42, 0x1e4300001e44, 0x1e4500001e46, 0x1e4700001e48, 0x1e4900001e4a, 0x1e4b00001e4c, 0x1e4d00001e4e, 0x1e4f00001e50, 0x1e5100001e52, 0x1e5300001e54, 0x1e5500001e56, 0x1e5700001e58, 0x1e5900001e5a, 0x1e5b00001e5c, 0x1e5d00001e5e, 0x1e5f00001e60, 0x1e6100001e62, 0x1e6300001e64, 0x1e6500001e66, 0x1e6700001e68, 0x1e6900001e6a, 0x1e6b00001e6c, 0x1e6d00001e6e, 0x1e6f00001e70, 0x1e7100001e72, 0x1e7300001e74, 0x1e7500001e76, 0x1e7700001e78, 0x1e7900001e7a, 0x1e7b00001e7c, 0x1e7d00001e7e, 0x1e7f00001e80, 0x1e8100001e82, 0x1e8300001e84, 0x1e8500001e86, 0x1e8700001e88, 0x1e8900001e8a, 0x1e8b00001e8c, 0x1e8d00001e8e, 0x1e8f00001e90, 0x1e9100001e92, 0x1e9300001e94, 0x1e9500001e9a, 0x1e9c00001e9e, 0x1e9f00001ea0, 0x1ea100001ea2, 0x1ea300001ea4, 0x1ea500001ea6, 0x1ea700001ea8, 0x1ea900001eaa, 0x1eab00001eac, 0x1ead00001eae, 0x1eaf00001eb0, 0x1eb100001eb2, 0x1eb300001eb4, 0x1eb500001eb6, 0x1eb700001eb8, 0x1eb900001eba, 0x1ebb00001ebc, 0x1ebd00001ebe, 0x1ebf00001ec0, 0x1ec100001ec2, 0x1ec300001ec4, 0x1ec500001ec6, 0x1ec700001ec8, 0x1ec900001eca, 0x1ecb00001ecc, 0x1ecd00001ece, 0x1ecf00001ed0, 0x1ed100001ed2, 0x1ed300001ed4, 0x1ed500001ed6, 0x1ed700001ed8, 0x1ed900001eda, 0x1edb00001edc, 0x1edd00001ede, 0x1edf00001ee0, 0x1ee100001ee2, 0x1ee300001ee4, 0x1ee500001ee6, 0x1ee700001ee8, 0x1ee900001eea, 0x1eeb00001eec, 0x1eed00001eee, 0x1eef00001ef0, 0x1ef100001ef2, 0x1ef300001ef4, 0x1ef500001ef6, 0x1ef700001ef8, 0x1ef900001efa, 0x1efb00001efc, 0x1efd00001efe, 0x1eff00001f08, 0x1f1000001f16, 0x1f2000001f28, 0x1f3000001f38, 0x1f4000001f46, 0x1f5000001f58, 0x1f6000001f68, 0x1f7000001f71, 0x1f7200001f73, 0x1f7400001f75, 0x1f7600001f77, 0x1f7800001f79, 0x1f7a00001f7b, 0x1f7c00001f7d, 0x1fb000001fb2, 0x1fb600001fb7, 0x1fc600001fc7, 0x1fd000001fd3, 0x1fd600001fd8, 0x1fe000001fe3, 0x1fe400001fe8, 0x1ff600001ff7, 0x214e0000214f, 0x218400002185, 0x2c3000002c5f, 0x2c6100002c62, 0x2c6500002c67, 0x2c6800002c69, 0x2c6a00002c6b, 0x2c6c00002c6d, 0x2c7100002c72, 0x2c7300002c75, 0x2c7600002c7c, 0x2c8100002c82, 0x2c8300002c84, 0x2c8500002c86, 0x2c8700002c88, 0x2c8900002c8a, 0x2c8b00002c8c, 0x2c8d00002c8e, 0x2c8f00002c90, 0x2c9100002c92, 0x2c9300002c94, 0x2c9500002c96, 0x2c9700002c98, 0x2c9900002c9a, 0x2c9b00002c9c, 0x2c9d00002c9e, 0x2c9f00002ca0, 0x2ca100002ca2, 0x2ca300002ca4, 0x2ca500002ca6, 0x2ca700002ca8, 0x2ca900002caa, 0x2cab00002cac, 0x2cad00002cae, 0x2caf00002cb0, 0x2cb100002cb2, 0x2cb300002cb4, 0x2cb500002cb6, 0x2cb700002cb8, 0x2cb900002cba, 0x2cbb00002cbc, 0x2cbd00002cbe, 0x2cbf00002cc0, 0x2cc100002cc2, 0x2cc300002cc4, 0x2cc500002cc6, 0x2cc700002cc8, 0x2cc900002cca, 0x2ccb00002ccc, 0x2ccd00002cce, 0x2ccf00002cd0, 0x2cd100002cd2, 0x2cd300002cd4, 0x2cd500002cd6, 0x2cd700002cd8, 0x2cd900002cda, 0x2cdb00002cdc, 0x2cdd00002cde, 0x2cdf00002ce0, 0x2ce100002ce2, 0x2ce300002ce5, 0x2cec00002ced, 0x2cee00002cf2, 0x2cf300002cf4, 0x2d0000002d26, 0x2d2700002d28, 0x2d2d00002d2e, 0x2d3000002d68, 0x2d7f00002d97, 0x2da000002da7, 0x2da800002daf, 0x2db000002db7, 0x2db800002dbf, 0x2dc000002dc7, 0x2dc800002dcf, 0x2dd000002dd7, 0x2dd800002ddf, 0x2de000002e00, 0x2e2f00002e30, 0x300500003008, 0x302a0000302e, 0x303c0000303d, 0x304100003097, 0x30990000309b, 0x309d0000309f, 0x30a1000030fb, 0x30fc000030ff, 0x310500003130, 0x31a0000031bb, 0x31f000003200, 0x340000004db6, 0x4e0000009ff0, 0xa0000000a48d, 0xa4d00000a4fe, 0xa5000000a60d, 0xa6100000a62c, 0xa6410000a642, 0xa6430000a644, 0xa6450000a646, 0xa6470000a648, 0xa6490000a64a, 0xa64b0000a64c, 0xa64d0000a64e, 0xa64f0000a650, 0xa6510000a652, 0xa6530000a654, 0xa6550000a656, 0xa6570000a658, 0xa6590000a65a, 0xa65b0000a65c, 0xa65d0000a65e, 0xa65f0000a660, 0xa6610000a662, 0xa6630000a664, 0xa6650000a666, 0xa6670000a668, 0xa6690000a66a, 0xa66b0000a66c, 0xa66d0000a670, 0xa6740000a67e, 0xa67f0000a680, 0xa6810000a682, 0xa6830000a684, 0xa6850000a686, 0xa6870000a688, 0xa6890000a68a, 0xa68b0000a68c, 0xa68d0000a68e, 0xa68f0000a690, 0xa6910000a692, 0xa6930000a694, 0xa6950000a696, 0xa6970000a698, 0xa6990000a69a, 0xa69b0000a69c, 0xa69e0000a6e6, 0xa6f00000a6f2, 0xa7170000a720, 0xa7230000a724, 0xa7250000a726, 0xa7270000a728, 0xa7290000a72a, 0xa72b0000a72c, 0xa72d0000a72e, 0xa72f0000a732, 0xa7330000a734, 0xa7350000a736, 0xa7370000a738, 0xa7390000a73a, 0xa73b0000a73c, 0xa73d0000a73e, 0xa73f0000a740, 0xa7410000a742, 0xa7430000a744, 0xa7450000a746, 0xa7470000a748, 0xa7490000a74a, 0xa74b0000a74c, 0xa74d0000a74e, 0xa74f0000a750, 0xa7510000a752, 0xa7530000a754, 0xa7550000a756, 0xa7570000a758, 0xa7590000a75a, 0xa75b0000a75c, 0xa75d0000a75e, 0xa75f0000a760, 0xa7610000a762, 0xa7630000a764, 0xa7650000a766, 0xa7670000a768, 0xa7690000a76a, 0xa76b0000a76c, 0xa76d0000a76e, 0xa76f0000a770, 0xa7710000a779, 0xa77a0000a77b, 0xa77c0000a77d, 0xa77f0000a780, 0xa7810000a782, 0xa7830000a784, 0xa7850000a786, 0xa7870000a789, 0xa78c0000a78d, 0xa78e0000a790, 0xa7910000a792, 0xa7930000a796, 0xa7970000a798, 0xa7990000a79a, 0xa79b0000a79c, 0xa79d0000a79e, 0xa79f0000a7a0, 0xa7a10000a7a2, 0xa7a30000a7a4, 0xa7a50000a7a6, 0xa7a70000a7a8, 0xa7a90000a7aa, 0xa7af0000a7b0, 0xa7b50000a7b6, 0xa7b70000a7b8, 0xa7b90000a7ba, 0xa7f70000a7f8, 0xa7fa0000a828, 0xa8400000a874, 0xa8800000a8c6, 0xa8d00000a8da, 0xa8e00000a8f8, 0xa8fb0000a8fc, 0xa8fd0000a92e, 0xa9300000a954, 0xa9800000a9c1, 0xa9cf0000a9da, 0xa9e00000a9ff, 0xaa000000aa37, 0xaa400000aa4e, 0xaa500000aa5a, 0xaa600000aa77, 0xaa7a0000aac3, 0xaadb0000aade, 0xaae00000aaf0, 0xaaf20000aaf7, 0xab010000ab07, 0xab090000ab0f, 0xab110000ab17, 0xab200000ab27, 0xab280000ab2f, 0xab300000ab5b, 0xab600000ab66, 0xabc00000abeb, 0xabec0000abee, 0xabf00000abfa, 0xac000000d7a4, 0xfa0e0000fa10, 0xfa110000fa12, 0xfa130000fa15, 0xfa1f0000fa20, 0xfa210000fa22, 0xfa230000fa25, 0xfa270000fa2a, 0xfb1e0000fb1f, 0xfe200000fe30, 0xfe730000fe74, 0x100000001000c, 0x1000d00010027, 0x100280001003b, 0x1003c0001003e, 0x1003f0001004e, 0x100500001005e, 0x10080000100fb, 0x101fd000101fe, 0x102800001029d, 0x102a0000102d1, 0x102e0000102e1, 0x1030000010320, 0x1032d00010341, 0x103420001034a, 0x103500001037b, 0x103800001039e, 0x103a0000103c4, 0x103c8000103d0, 0x104280001049e, 0x104a0000104aa, 0x104d8000104fc, 0x1050000010528, 0x1053000010564, 0x1060000010737, 0x1074000010756, 0x1076000010768, 0x1080000010806, 0x1080800010809, 0x1080a00010836, 0x1083700010839, 0x1083c0001083d, 0x1083f00010856, 0x1086000010877, 0x108800001089f, 0x108e0000108f3, 0x108f4000108f6, 0x1090000010916, 0x109200001093a, 0x10980000109b8, 0x109be000109c0, 0x10a0000010a04, 0x10a0500010a07, 0x10a0c00010a14, 0x10a1500010a18, 0x10a1900010a36, 0x10a3800010a3b, 0x10a3f00010a40, 0x10a6000010a7d, 0x10a8000010a9d, 0x10ac000010ac8, 0x10ac900010ae7, 0x10b0000010b36, 0x10b4000010b56, 0x10b6000010b73, 0x10b8000010b92, 0x10c0000010c49, 0x10cc000010cf3, 0x10d0000010d28, 0x10d3000010d3a, 0x10f0000010f1d, 0x10f2700010f28, 0x10f3000010f51, 0x1100000011047, 0x1106600011070, 0x1107f000110bb, 0x110d0000110e9, 0x110f0000110fa, 0x1110000011135, 0x1113600011140, 0x1114400011147, 0x1115000011174, 0x1117600011177, 0x11180000111c5, 0x111c9000111cd, 0x111d0000111db, 0x111dc000111dd, 0x1120000011212, 0x1121300011238, 0x1123e0001123f, 0x1128000011287, 0x1128800011289, 0x1128a0001128e, 0x1128f0001129e, 0x1129f000112a9, 0x112b0000112eb, 0x112f0000112fa, 0x1130000011304, 0x113050001130d, 0x1130f00011311, 0x1131300011329, 0x1132a00011331, 0x1133200011334, 0x113350001133a, 0x1133b00011345, 0x1134700011349, 0x1134b0001134e, 0x1135000011351, 0x1135700011358, 0x1135d00011364, 0x113660001136d, 0x1137000011375, 0x114000001144b, 0x114500001145a, 0x1145e0001145f, 0x11480000114c6, 0x114c7000114c8, 0x114d0000114da, 0x11580000115b6, 0x115b8000115c1, 0x115d8000115de, 0x1160000011641, 0x1164400011645, 0x116500001165a, 0x11680000116b8, 0x116c0000116ca, 0x117000001171b, 0x1171d0001172c, 0x117300001173a, 0x118000001183b, 0x118c0000118ea, 0x118ff00011900, 0x11a0000011a3f, 0x11a4700011a48, 0x11a5000011a84, 0x11a8600011a9a, 0x11a9d00011a9e, 0x11ac000011af9, 0x11c0000011c09, 0x11c0a00011c37, 0x11c3800011c41, 0x11c5000011c5a, 0x11c7200011c90, 0x11c9200011ca8, 0x11ca900011cb7, 0x11d0000011d07, 0x11d0800011d0a, 0x11d0b00011d37, 0x11d3a00011d3b, 0x11d3c00011d3e, 0x11d3f00011d48, 0x11d5000011d5a, 0x11d6000011d66, 0x11d6700011d69, 0x11d6a00011d8f, 0x11d9000011d92, 0x11d9300011d99, 0x11da000011daa, 0x11ee000011ef7, 0x120000001239a, 0x1248000012544, 0x130000001342f, 0x1440000014647, 0x1680000016a39, 0x16a4000016a5f, 0x16a6000016a6a, 0x16ad000016aee, 0x16af000016af5, 0x16b0000016b37, 0x16b4000016b44, 0x16b5000016b5a, 0x16b6300016b78, 0x16b7d00016b90, 0x16e6000016e80, 0x16f0000016f45, 0x16f5000016f7f, 0x16f8f00016fa0, 0x16fe000016fe2, 0x17000000187f2, 0x1880000018af3, 0x1b0000001b11f, 0x1b1700001b2fc, 0x1bc000001bc6b, 0x1bc700001bc7d, 0x1bc800001bc89, 0x1bc900001bc9a, 0x1bc9d0001bc9f, 0x1da000001da37, 0x1da3b0001da6d, 0x1da750001da76, 0x1da840001da85, 0x1da9b0001daa0, 0x1daa10001dab0, 0x1e0000001e007, 0x1e0080001e019, 0x1e01b0001e022, 0x1e0230001e025, 0x1e0260001e02b, 0x1e8000001e8c5, 0x1e8d00001e8d7, 0x1e9220001e94b, 0x1e9500001e95a, 0x200000002a6d7, 0x2a7000002b735, 0x2b7400002b81e, 0x2b8200002cea2, 0x2ceb00002ebe1, ), 'CONTEXTJ': ( 0x200c0000200e, ), 'CONTEXTO': ( 0xb7000000b8, 0x37500000376, 0x5f3000005f5, 0x6600000066a, 0x6f0000006fa, 0x30fb000030fc, ), } ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/idna/intranges.py ================================================ """ Given a list of integers, made up of (hopefully) a small number of long runs of consecutive integers, compute a representation of the form ((start1, end1), (start2, end2) ...). Then answer the question "was x present in the original list?" in time O(log(# runs)). """ import bisect def intranges_from_list(list_): """Represent a list of integers as a sequence of ranges: ((start_0, end_0), (start_1, end_1), ...), such that the original integers are exactly those x such that start_i <= x < end_i for some i. Ranges are encoded as single integers (start << 32 | end), not as tuples. """ sorted_list = sorted(list_) ranges = [] last_write = -1 for i in range(len(sorted_list)): if i+1 < len(sorted_list): if sorted_list[i] == sorted_list[i+1]-1: continue current_range = sorted_list[last_write+1:i+1] ranges.append(_encode_range(current_range[0], current_range[-1] + 1)) last_write = i return tuple(ranges) def _encode_range(start, end): return (start << 32) | end def _decode_range(r): return (r >> 32), (r & ((1 << 32) - 1)) def intranges_contain(int_, ranges): """Determine if `int_` falls into one of the ranges in `ranges`.""" tuple_ = _encode_range(int_, 0) pos = bisect.bisect_left(ranges, tuple_) # we could be immediately ahead of a tuple (start, end) # with start < int_ <= end if pos > 0: left, right = _decode_range(ranges[pos-1]) if left <= int_ < right: return True # or we could be immediately behind a tuple (int_, end) if pos < len(ranges): left, _ = _decode_range(ranges[pos]) if left == int_: return True return False ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/idna/package_data.py ================================================ __version__ = '2.8' ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/idna/uts46data.py ================================================ # This file is automatically generated by tools/idna-data # vim: set fileencoding=utf-8 : """IDNA Mapping Table from UTS46.""" __version__ = "11.0.0" def _seg_0(): return [ (0x0, '3'), (0x1, '3'), (0x2, '3'), (0x3, '3'), (0x4, '3'), (0x5, '3'), (0x6, '3'), (0x7, '3'), (0x8, '3'), (0x9, '3'), (0xA, '3'), (0xB, '3'), (0xC, '3'), (0xD, '3'), (0xE, '3'), (0xF, '3'), (0x10, '3'), (0x11, '3'), (0x12, '3'), (0x13, '3'), (0x14, '3'), (0x15, '3'), (0x16, '3'), (0x17, '3'), (0x18, '3'), (0x19, '3'), (0x1A, '3'), (0x1B, '3'), (0x1C, '3'), (0x1D, '3'), (0x1E, '3'), (0x1F, '3'), (0x20, '3'), (0x21, '3'), (0x22, '3'), (0x23, '3'), (0x24, '3'), (0x25, '3'), (0x26, '3'), (0x27, '3'), (0x28, '3'), (0x29, '3'), (0x2A, '3'), (0x2B, '3'), (0x2C, '3'), (0x2D, 'V'), (0x2E, 'V'), (0x2F, '3'), (0x30, 'V'), (0x31, 'V'), (0x32, 'V'), (0x33, 'V'), (0x34, 'V'), (0x35, 'V'), (0x36, 'V'), (0x37, 'V'), (0x38, 'V'), (0x39, 'V'), (0x3A, '3'), (0x3B, '3'), (0x3C, '3'), (0x3D, '3'), (0x3E, '3'), (0x3F, '3'), (0x40, '3'), (0x41, 'M', u'a'), (0x42, 'M', u'b'), (0x43, 'M', u'c'), (0x44, 'M', u'd'), (0x45, 'M', u'e'), (0x46, 'M', u'f'), (0x47, 'M', u'g'), (0x48, 'M', u'h'), (0x49, 'M', u'i'), (0x4A, 'M', u'j'), (0x4B, 'M', u'k'), (0x4C, 'M', u'l'), (0x4D, 'M', u'm'), (0x4E, 'M', u'n'), (0x4F, 'M', u'o'), (0x50, 'M', u'p'), (0x51, 'M', u'q'), (0x52, 'M', u'r'), (0x53, 'M', u's'), (0x54, 'M', u't'), (0x55, 'M', u'u'), (0x56, 'M', u'v'), (0x57, 'M', u'w'), (0x58, 'M', u'x'), (0x59, 'M', u'y'), (0x5A, 'M', u'z'), (0x5B, '3'), (0x5C, '3'), (0x5D, '3'), (0x5E, '3'), (0x5F, '3'), (0x60, '3'), (0x61, 'V'), (0x62, 'V'), (0x63, 'V'), ] def _seg_1(): return [ (0x64, 'V'), (0x65, 'V'), (0x66, 'V'), (0x67, 'V'), (0x68, 'V'), (0x69, 'V'), (0x6A, 'V'), (0x6B, 'V'), (0x6C, 'V'), (0x6D, 'V'), (0x6E, 'V'), (0x6F, 'V'), (0x70, 'V'), (0x71, 'V'), (0x72, 'V'), (0x73, 'V'), (0x74, 'V'), (0x75, 'V'), (0x76, 'V'), (0x77, 'V'), (0x78, 'V'), (0x79, 'V'), (0x7A, 'V'), (0x7B, '3'), (0x7C, '3'), (0x7D, '3'), (0x7E, '3'), (0x7F, '3'), (0x80, 'X'), (0x81, 'X'), (0x82, 'X'), (0x83, 'X'), (0x84, 'X'), (0x85, 'X'), (0x86, 'X'), (0x87, 'X'), (0x88, 'X'), (0x89, 'X'), (0x8A, 'X'), (0x8B, 'X'), (0x8C, 'X'), (0x8D, 'X'), (0x8E, 'X'), (0x8F, 'X'), (0x90, 'X'), (0x91, 'X'), (0x92, 'X'), (0x93, 'X'), (0x94, 'X'), (0x95, 'X'), (0x96, 'X'), (0x97, 'X'), (0x98, 'X'), (0x99, 'X'), (0x9A, 'X'), (0x9B, 'X'), (0x9C, 'X'), (0x9D, 'X'), (0x9E, 'X'), (0x9F, 'X'), (0xA0, '3', u' '), (0xA1, 'V'), (0xA2, 'V'), (0xA3, 'V'), (0xA4, 'V'), (0xA5, 'V'), (0xA6, 'V'), (0xA7, 'V'), (0xA8, '3', u' ̈'), (0xA9, 'V'), (0xAA, 'M', u'a'), (0xAB, 'V'), (0xAC, 'V'), (0xAD, 'I'), (0xAE, 'V'), (0xAF, '3', u' ̄'), (0xB0, 'V'), (0xB1, 'V'), (0xB2, 'M', u'2'), (0xB3, 'M', u'3'), (0xB4, '3', u' ́'), (0xB5, 'M', u'μ'), (0xB6, 'V'), (0xB7, 'V'), (0xB8, '3', u' ̧'), (0xB9, 'M', u'1'), (0xBA, 'M', u'o'), (0xBB, 'V'), (0xBC, 'M', u'1⁄4'), (0xBD, 'M', u'1⁄2'), (0xBE, 'M', u'3⁄4'), (0xBF, 'V'), (0xC0, 'M', u'à'), (0xC1, 'M', u'á'), (0xC2, 'M', u'â'), (0xC3, 'M', u'ã'), (0xC4, 'M', u'ä'), (0xC5, 'M', u'å'), (0xC6, 'M', u'æ'), (0xC7, 'M', u'ç'), ] def _seg_2(): return [ (0xC8, 'M', u'è'), (0xC9, 'M', u'é'), (0xCA, 'M', u'ê'), (0xCB, 'M', u'ë'), (0xCC, 'M', u'ì'), (0xCD, 'M', u'í'), (0xCE, 'M', u'î'), (0xCF, 'M', u'ï'), (0xD0, 'M', u'ð'), (0xD1, 'M', u'ñ'), (0xD2, 'M', u'ò'), (0xD3, 'M', u'ó'), (0xD4, 'M', u'ô'), (0xD5, 'M', u'õ'), (0xD6, 'M', u'ö'), (0xD7, 'V'), (0xD8, 'M', u'ø'), (0xD9, 'M', u'ù'), (0xDA, 'M', u'ú'), (0xDB, 'M', u'û'), (0xDC, 'M', u'ü'), (0xDD, 'M', u'ý'), (0xDE, 'M', u'þ'), (0xDF, 'D', u'ss'), (0xE0, 'V'), (0xE1, 'V'), (0xE2, 'V'), (0xE3, 'V'), (0xE4, 'V'), (0xE5, 'V'), (0xE6, 'V'), (0xE7, 'V'), (0xE8, 'V'), (0xE9, 'V'), (0xEA, 'V'), (0xEB, 'V'), (0xEC, 'V'), (0xED, 'V'), (0xEE, 'V'), (0xEF, 'V'), (0xF0, 'V'), (0xF1, 'V'), (0xF2, 'V'), (0xF3, 'V'), (0xF4, 'V'), (0xF5, 'V'), (0xF6, 'V'), (0xF7, 'V'), (0xF8, 'V'), (0xF9, 'V'), (0xFA, 'V'), (0xFB, 'V'), (0xFC, 'V'), (0xFD, 'V'), (0xFE, 'V'), (0xFF, 'V'), (0x100, 'M', u'ā'), (0x101, 'V'), (0x102, 'M', u'ă'), (0x103, 'V'), (0x104, 'M', u'ą'), (0x105, 'V'), (0x106, 'M', u'ć'), (0x107, 'V'), (0x108, 'M', u'ĉ'), (0x109, 'V'), (0x10A, 'M', u'ċ'), (0x10B, 'V'), (0x10C, 'M', u'č'), (0x10D, 'V'), (0x10E, 'M', u'ď'), (0x10F, 'V'), (0x110, 'M', u'đ'), (0x111, 'V'), (0x112, 'M', u'ē'), (0x113, 'V'), (0x114, 'M', u'ĕ'), (0x115, 'V'), (0x116, 'M', u'ė'), (0x117, 'V'), (0x118, 'M', u'ę'), (0x119, 'V'), (0x11A, 'M', u'ě'), (0x11B, 'V'), (0x11C, 'M', u'ĝ'), (0x11D, 'V'), (0x11E, 'M', u'ğ'), (0x11F, 'V'), (0x120, 'M', u'ġ'), (0x121, 'V'), (0x122, 'M', u'ģ'), (0x123, 'V'), (0x124, 'M', u'ĥ'), (0x125, 'V'), (0x126, 'M', u'ħ'), (0x127, 'V'), (0x128, 'M', u'ĩ'), (0x129, 'V'), (0x12A, 'M', u'ī'), (0x12B, 'V'), ] def _seg_3(): return [ (0x12C, 'M', u'ĭ'), (0x12D, 'V'), (0x12E, 'M', u'į'), (0x12F, 'V'), (0x130, 'M', u'i̇'), (0x131, 'V'), (0x132, 'M', u'ij'), (0x134, 'M', u'ĵ'), (0x135, 'V'), (0x136, 'M', u'ķ'), (0x137, 'V'), (0x139, 'M', u'ĺ'), (0x13A, 'V'), (0x13B, 'M', u'ļ'), (0x13C, 'V'), (0x13D, 'M', u'ľ'), (0x13E, 'V'), (0x13F, 'M', u'l·'), (0x141, 'M', u'ł'), (0x142, 'V'), (0x143, 'M', u'ń'), (0x144, 'V'), (0x145, 'M', u'ņ'), (0x146, 'V'), (0x147, 'M', u'ň'), (0x148, 'V'), (0x149, 'M', u'ʼn'), (0x14A, 'M', u'ŋ'), (0x14B, 'V'), (0x14C, 'M', u'ō'), (0x14D, 'V'), (0x14E, 'M', u'ŏ'), (0x14F, 'V'), (0x150, 'M', u'ő'), (0x151, 'V'), (0x152, 'M', u'œ'), (0x153, 'V'), (0x154, 'M', u'ŕ'), (0x155, 'V'), (0x156, 'M', u'ŗ'), (0x157, 'V'), (0x158, 'M', u'ř'), (0x159, 'V'), (0x15A, 'M', u'ś'), (0x15B, 'V'), (0x15C, 'M', u'ŝ'), (0x15D, 'V'), (0x15E, 'M', u'ş'), (0x15F, 'V'), (0x160, 'M', u'š'), (0x161, 'V'), (0x162, 'M', u'ţ'), (0x163, 'V'), (0x164, 'M', u'ť'), (0x165, 'V'), (0x166, 'M', u'ŧ'), (0x167, 'V'), (0x168, 'M', u'ũ'), (0x169, 'V'), (0x16A, 'M', u'ū'), (0x16B, 'V'), (0x16C, 'M', u'ŭ'), (0x16D, 'V'), (0x16E, 'M', u'ů'), (0x16F, 'V'), (0x170, 'M', u'ű'), (0x171, 'V'), (0x172, 'M', u'ų'), (0x173, 'V'), (0x174, 'M', u'ŵ'), (0x175, 'V'), (0x176, 'M', u'ŷ'), (0x177, 'V'), (0x178, 'M', u'ÿ'), (0x179, 'M', u'ź'), (0x17A, 'V'), (0x17B, 'M', u'ż'), (0x17C, 'V'), (0x17D, 'M', u'ž'), (0x17E, 'V'), (0x17F, 'M', u's'), (0x180, 'V'), (0x181, 'M', u'ɓ'), (0x182, 'M', u'ƃ'), (0x183, 'V'), (0x184, 'M', u'ƅ'), (0x185, 'V'), (0x186, 'M', u'ɔ'), (0x187, 'M', u'ƈ'), (0x188, 'V'), (0x189, 'M', u'ɖ'), (0x18A, 'M', u'ɗ'), (0x18B, 'M', u'ƌ'), (0x18C, 'V'), (0x18E, 'M', u'ǝ'), (0x18F, 'M', u'ə'), (0x190, 'M', u'ɛ'), (0x191, 'M', u'ƒ'), (0x192, 'V'), (0x193, 'M', u'ɠ'), ] def _seg_4(): return [ (0x194, 'M', u'ɣ'), (0x195, 'V'), (0x196, 'M', u'ɩ'), (0x197, 'M', u'ɨ'), (0x198, 'M', u'ƙ'), (0x199, 'V'), (0x19C, 'M', u'ɯ'), (0x19D, 'M', u'ɲ'), (0x19E, 'V'), (0x19F, 'M', u'ɵ'), (0x1A0, 'M', u'ơ'), (0x1A1, 'V'), (0x1A2, 'M', u'ƣ'), (0x1A3, 'V'), (0x1A4, 'M', u'ƥ'), (0x1A5, 'V'), (0x1A6, 'M', u'ʀ'), (0x1A7, 'M', u'ƨ'), (0x1A8, 'V'), (0x1A9, 'M', u'ʃ'), (0x1AA, 'V'), (0x1AC, 'M', u'ƭ'), (0x1AD, 'V'), (0x1AE, 'M', u'ʈ'), (0x1AF, 'M', u'ư'), (0x1B0, 'V'), (0x1B1, 'M', u'ʊ'), (0x1B2, 'M', u'ʋ'), (0x1B3, 'M', u'ƴ'), (0x1B4, 'V'), (0x1B5, 'M', u'ƶ'), (0x1B6, 'V'), (0x1B7, 'M', u'ʒ'), (0x1B8, 'M', u'ƹ'), (0x1B9, 'V'), (0x1BC, 'M', u'ƽ'), (0x1BD, 'V'), (0x1C4, 'M', u'dž'), (0x1C7, 'M', u'lj'), (0x1CA, 'M', u'nj'), (0x1CD, 'M', u'ǎ'), (0x1CE, 'V'), (0x1CF, 'M', u'ǐ'), (0x1D0, 'V'), (0x1D1, 'M', u'ǒ'), (0x1D2, 'V'), (0x1D3, 'M', u'ǔ'), (0x1D4, 'V'), (0x1D5, 'M', u'ǖ'), (0x1D6, 'V'), (0x1D7, 'M', u'ǘ'), (0x1D8, 'V'), (0x1D9, 'M', u'ǚ'), (0x1DA, 'V'), (0x1DB, 'M', u'ǜ'), (0x1DC, 'V'), (0x1DE, 'M', u'ǟ'), (0x1DF, 'V'), (0x1E0, 'M', u'ǡ'), (0x1E1, 'V'), (0x1E2, 'M', u'ǣ'), (0x1E3, 'V'), (0x1E4, 'M', u'ǥ'), (0x1E5, 'V'), (0x1E6, 'M', u'ǧ'), (0x1E7, 'V'), (0x1E8, 'M', u'ǩ'), (0x1E9, 'V'), (0x1EA, 'M', u'ǫ'), (0x1EB, 'V'), (0x1EC, 'M', u'ǭ'), (0x1ED, 'V'), (0x1EE, 'M', u'ǯ'), (0x1EF, 'V'), (0x1F1, 'M', u'dz'), (0x1F4, 'M', u'ǵ'), (0x1F5, 'V'), (0x1F6, 'M', u'ƕ'), (0x1F7, 'M', u'ƿ'), (0x1F8, 'M', u'ǹ'), (0x1F9, 'V'), (0x1FA, 'M', u'ǻ'), (0x1FB, 'V'), (0x1FC, 'M', u'ǽ'), (0x1FD, 'V'), (0x1FE, 'M', u'ǿ'), (0x1FF, 'V'), (0x200, 'M', u'ȁ'), (0x201, 'V'), (0x202, 'M', u'ȃ'), (0x203, 'V'), (0x204, 'M', u'ȅ'), (0x205, 'V'), (0x206, 'M', u'ȇ'), (0x207, 'V'), (0x208, 'M', u'ȉ'), (0x209, 'V'), (0x20A, 'M', u'ȋ'), (0x20B, 'V'), (0x20C, 'M', u'ȍ'), ] def _seg_5(): return [ (0x20D, 'V'), (0x20E, 'M', u'ȏ'), (0x20F, 'V'), (0x210, 'M', u'ȑ'), (0x211, 'V'), (0x212, 'M', u'ȓ'), (0x213, 'V'), (0x214, 'M', u'ȕ'), (0x215, 'V'), (0x216, 'M', u'ȗ'), (0x217, 'V'), (0x218, 'M', u'ș'), (0x219, 'V'), (0x21A, 'M', u'ț'), (0x21B, 'V'), (0x21C, 'M', u'ȝ'), (0x21D, 'V'), (0x21E, 'M', u'ȟ'), (0x21F, 'V'), (0x220, 'M', u'ƞ'), (0x221, 'V'), (0x222, 'M', u'ȣ'), (0x223, 'V'), (0x224, 'M', u'ȥ'), (0x225, 'V'), (0x226, 'M', u'ȧ'), (0x227, 'V'), (0x228, 'M', u'ȩ'), (0x229, 'V'), (0x22A, 'M', u'ȫ'), (0x22B, 'V'), (0x22C, 'M', u'ȭ'), (0x22D, 'V'), (0x22E, 'M', u'ȯ'), (0x22F, 'V'), (0x230, 'M', u'ȱ'), (0x231, 'V'), (0x232, 'M', u'ȳ'), (0x233, 'V'), (0x23A, 'M', u'ⱥ'), (0x23B, 'M', u'ȼ'), (0x23C, 'V'), (0x23D, 'M', u'ƚ'), (0x23E, 'M', u'ⱦ'), (0x23F, 'V'), (0x241, 'M', u'ɂ'), (0x242, 'V'), (0x243, 'M', u'ƀ'), (0x244, 'M', u'ʉ'), (0x245, 'M', u'ʌ'), (0x246, 'M', u'ɇ'), (0x247, 'V'), (0x248, 'M', u'ɉ'), (0x249, 'V'), (0x24A, 'M', u'ɋ'), (0x24B, 'V'), (0x24C, 'M', u'ɍ'), (0x24D, 'V'), (0x24E, 'M', u'ɏ'), (0x24F, 'V'), (0x2B0, 'M', u'h'), (0x2B1, 'M', u'ɦ'), (0x2B2, 'M', u'j'), (0x2B3, 'M', u'r'), (0x2B4, 'M', u'ɹ'), (0x2B5, 'M', u'ɻ'), (0x2B6, 'M', u'ʁ'), (0x2B7, 'M', u'w'), (0x2B8, 'M', u'y'), (0x2B9, 'V'), (0x2D8, '3', u' ̆'), (0x2D9, '3', u' ̇'), (0x2DA, '3', u' ̊'), (0x2DB, '3', u' ̨'), (0x2DC, '3', u' ̃'), (0x2DD, '3', u' ̋'), (0x2DE, 'V'), (0x2E0, 'M', u'ɣ'), (0x2E1, 'M', u'l'), (0x2E2, 'M', u's'), (0x2E3, 'M', u'x'), (0x2E4, 'M', u'ʕ'), (0x2E5, 'V'), (0x340, 'M', u'̀'), (0x341, 'M', u'́'), (0x342, 'V'), (0x343, 'M', u'̓'), (0x344, 'M', u'̈́'), (0x345, 'M', u'ι'), (0x346, 'V'), (0x34F, 'I'), (0x350, 'V'), (0x370, 'M', u'ͱ'), (0x371, 'V'), (0x372, 'M', u'ͳ'), (0x373, 'V'), (0x374, 'M', u'ʹ'), (0x375, 'V'), (0x376, 'M', u'ͷ'), (0x377, 'V'), ] def _seg_6(): return [ (0x378, 'X'), (0x37A, '3', u' ι'), (0x37B, 'V'), (0x37E, '3', u';'), (0x37F, 'M', u'ϳ'), (0x380, 'X'), (0x384, '3', u' ́'), (0x385, '3', u' ̈́'), (0x386, 'M', u'ά'), (0x387, 'M', u'·'), (0x388, 'M', u'έ'), (0x389, 'M', u'ή'), (0x38A, 'M', u'ί'), (0x38B, 'X'), (0x38C, 'M', u'ό'), (0x38D, 'X'), (0x38E, 'M', u'ύ'), (0x38F, 'M', u'ώ'), (0x390, 'V'), (0x391, 'M', u'α'), (0x392, 'M', u'β'), (0x393, 'M', u'γ'), (0x394, 'M', u'δ'), (0x395, 'M', u'ε'), (0x396, 'M', u'ζ'), (0x397, 'M', u'η'), (0x398, 'M', u'θ'), (0x399, 'M', u'ι'), (0x39A, 'M', u'κ'), (0x39B, 'M', u'λ'), (0x39C, 'M', u'μ'), (0x39D, 'M', u'ν'), (0x39E, 'M', u'ξ'), (0x39F, 'M', u'ο'), (0x3A0, 'M', u'π'), (0x3A1, 'M', u'ρ'), (0x3A2, 'X'), (0x3A3, 'M', u'σ'), (0x3A4, 'M', u'τ'), (0x3A5, 'M', u'υ'), (0x3A6, 'M', u'φ'), (0x3A7, 'M', u'χ'), (0x3A8, 'M', u'ψ'), (0x3A9, 'M', u'ω'), (0x3AA, 'M', u'ϊ'), (0x3AB, 'M', u'ϋ'), (0x3AC, 'V'), (0x3C2, 'D', u'σ'), (0x3C3, 'V'), (0x3CF, 'M', u'ϗ'), (0x3D0, 'M', u'β'), (0x3D1, 'M', u'θ'), (0x3D2, 'M', u'υ'), (0x3D3, 'M', u'ύ'), (0x3D4, 'M', u'ϋ'), (0x3D5, 'M', u'φ'), (0x3D6, 'M', u'π'), (0x3D7, 'V'), (0x3D8, 'M', u'ϙ'), (0x3D9, 'V'), (0x3DA, 'M', u'ϛ'), (0x3DB, 'V'), (0x3DC, 'M', u'ϝ'), (0x3DD, 'V'), (0x3DE, 'M', u'ϟ'), (0x3DF, 'V'), (0x3E0, 'M', u'ϡ'), (0x3E1, 'V'), (0x3E2, 'M', u'ϣ'), (0x3E3, 'V'), (0x3E4, 'M', u'ϥ'), (0x3E5, 'V'), (0x3E6, 'M', u'ϧ'), (0x3E7, 'V'), (0x3E8, 'M', u'ϩ'), (0x3E9, 'V'), (0x3EA, 'M', u'ϫ'), (0x3EB, 'V'), (0x3EC, 'M', u'ϭ'), (0x3ED, 'V'), (0x3EE, 'M', u'ϯ'), (0x3EF, 'V'), (0x3F0, 'M', u'κ'), (0x3F1, 'M', u'ρ'), (0x3F2, 'M', u'σ'), (0x3F3, 'V'), (0x3F4, 'M', u'θ'), (0x3F5, 'M', u'ε'), (0x3F6, 'V'), (0x3F7, 'M', u'ϸ'), (0x3F8, 'V'), (0x3F9, 'M', u'σ'), (0x3FA, 'M', u'ϻ'), (0x3FB, 'V'), (0x3FD, 'M', u'ͻ'), (0x3FE, 'M', u'ͼ'), (0x3FF, 'M', u'ͽ'), (0x400, 'M', u'ѐ'), (0x401, 'M', u'ё'), (0x402, 'M', u'ђ'), ] def _seg_7(): return [ (0x403, 'M', u'ѓ'), (0x404, 'M', u'є'), (0x405, 'M', u'ѕ'), (0x406, 'M', u'і'), (0x407, 'M', u'ї'), (0x408, 'M', u'ј'), (0x409, 'M', u'љ'), (0x40A, 'M', u'њ'), (0x40B, 'M', u'ћ'), (0x40C, 'M', u'ќ'), (0x40D, 'M', u'ѝ'), (0x40E, 'M', u'ў'), (0x40F, 'M', u'џ'), (0x410, 'M', u'а'), (0x411, 'M', u'б'), (0x412, 'M', u'в'), (0x413, 'M', u'г'), (0x414, 'M', u'д'), (0x415, 'M', u'е'), (0x416, 'M', u'ж'), (0x417, 'M', u'з'), (0x418, 'M', u'и'), (0x419, 'M', u'й'), (0x41A, 'M', u'к'), (0x41B, 'M', u'л'), (0x41C, 'M', u'м'), (0x41D, 'M', u'н'), (0x41E, 'M', u'о'), (0x41F, 'M', u'п'), (0x420, 'M', u'р'), (0x421, 'M', u'с'), (0x422, 'M', u'т'), (0x423, 'M', u'у'), (0x424, 'M', u'ф'), (0x425, 'M', u'х'), (0x426, 'M', u'ц'), (0x427, 'M', u'ч'), (0x428, 'M', u'ш'), (0x429, 'M', u'щ'), (0x42A, 'M', u'ъ'), (0x42B, 'M', u'ы'), (0x42C, 'M', u'ь'), (0x42D, 'M', u'э'), (0x42E, 'M', u'ю'), (0x42F, 'M', u'я'), (0x430, 'V'), (0x460, 'M', u'ѡ'), (0x461, 'V'), (0x462, 'M', u'ѣ'), (0x463, 'V'), (0x464, 'M', u'ѥ'), (0x465, 'V'), (0x466, 'M', u'ѧ'), (0x467, 'V'), (0x468, 'M', u'ѩ'), (0x469, 'V'), (0x46A, 'M', u'ѫ'), (0x46B, 'V'), (0x46C, 'M', u'ѭ'), (0x46D, 'V'), (0x46E, 'M', u'ѯ'), (0x46F, 'V'), (0x470, 'M', u'ѱ'), (0x471, 'V'), (0x472, 'M', u'ѳ'), (0x473, 'V'), (0x474, 'M', u'ѵ'), (0x475, 'V'), (0x476, 'M', u'ѷ'), (0x477, 'V'), (0x478, 'M', u'ѹ'), (0x479, 'V'), (0x47A, 'M', u'ѻ'), (0x47B, 'V'), (0x47C, 'M', u'ѽ'), (0x47D, 'V'), (0x47E, 'M', u'ѿ'), (0x47F, 'V'), (0x480, 'M', u'ҁ'), (0x481, 'V'), (0x48A, 'M', u'ҋ'), (0x48B, 'V'), (0x48C, 'M', u'ҍ'), (0x48D, 'V'), (0x48E, 'M', u'ҏ'), (0x48F, 'V'), (0x490, 'M', u'ґ'), (0x491, 'V'), (0x492, 'M', u'ғ'), (0x493, 'V'), (0x494, 'M', u'ҕ'), (0x495, 'V'), (0x496, 'M', u'җ'), (0x497, 'V'), (0x498, 'M', u'ҙ'), (0x499, 'V'), (0x49A, 'M', u'қ'), (0x49B, 'V'), (0x49C, 'M', u'ҝ'), (0x49D, 'V'), ] def _seg_8(): return [ (0x49E, 'M', u'ҟ'), (0x49F, 'V'), (0x4A0, 'M', u'ҡ'), (0x4A1, 'V'), (0x4A2, 'M', u'ң'), (0x4A3, 'V'), (0x4A4, 'M', u'ҥ'), (0x4A5, 'V'), (0x4A6, 'M', u'ҧ'), (0x4A7, 'V'), (0x4A8, 'M', u'ҩ'), (0x4A9, 'V'), (0x4AA, 'M', u'ҫ'), (0x4AB, 'V'), (0x4AC, 'M', u'ҭ'), (0x4AD, 'V'), (0x4AE, 'M', u'ү'), (0x4AF, 'V'), (0x4B0, 'M', u'ұ'), (0x4B1, 'V'), (0x4B2, 'M', u'ҳ'), (0x4B3, 'V'), (0x4B4, 'M', u'ҵ'), (0x4B5, 'V'), (0x4B6, 'M', u'ҷ'), (0x4B7, 'V'), (0x4B8, 'M', u'ҹ'), (0x4B9, 'V'), (0x4BA, 'M', u'һ'), (0x4BB, 'V'), (0x4BC, 'M', u'ҽ'), (0x4BD, 'V'), (0x4BE, 'M', u'ҿ'), (0x4BF, 'V'), (0x4C0, 'X'), (0x4C1, 'M', u'ӂ'), (0x4C2, 'V'), (0x4C3, 'M', u'ӄ'), (0x4C4, 'V'), (0x4C5, 'M', u'ӆ'), (0x4C6, 'V'), (0x4C7, 'M', u'ӈ'), (0x4C8, 'V'), (0x4C9, 'M', u'ӊ'), (0x4CA, 'V'), (0x4CB, 'M', u'ӌ'), (0x4CC, 'V'), (0x4CD, 'M', u'ӎ'), (0x4CE, 'V'), (0x4D0, 'M', u'ӑ'), (0x4D1, 'V'), (0x4D2, 'M', u'ӓ'), (0x4D3, 'V'), (0x4D4, 'M', u'ӕ'), (0x4D5, 'V'), (0x4D6, 'M', u'ӗ'), (0x4D7, 'V'), (0x4D8, 'M', u'ә'), (0x4D9, 'V'), (0x4DA, 'M', u'ӛ'), (0x4DB, 'V'), (0x4DC, 'M', u'ӝ'), (0x4DD, 'V'), (0x4DE, 'M', u'ӟ'), (0x4DF, 'V'), (0x4E0, 'M', u'ӡ'), (0x4E1, 'V'), (0x4E2, 'M', u'ӣ'), (0x4E3, 'V'), (0x4E4, 'M', u'ӥ'), (0x4E5, 'V'), (0x4E6, 'M', u'ӧ'), (0x4E7, 'V'), (0x4E8, 'M', u'ө'), (0x4E9, 'V'), (0x4EA, 'M', u'ӫ'), (0x4EB, 'V'), (0x4EC, 'M', u'ӭ'), (0x4ED, 'V'), (0x4EE, 'M', u'ӯ'), (0x4EF, 'V'), (0x4F0, 'M', u'ӱ'), (0x4F1, 'V'), (0x4F2, 'M', u'ӳ'), (0x4F3, 'V'), (0x4F4, 'M', u'ӵ'), (0x4F5, 'V'), (0x4F6, 'M', u'ӷ'), (0x4F7, 'V'), (0x4F8, 'M', u'ӹ'), (0x4F9, 'V'), (0x4FA, 'M', u'ӻ'), (0x4FB, 'V'), (0x4FC, 'M', u'ӽ'), (0x4FD, 'V'), (0x4FE, 'M', u'ӿ'), (0x4FF, 'V'), (0x500, 'M', u'ԁ'), (0x501, 'V'), (0x502, 'M', u'ԃ'), ] def _seg_9(): return [ (0x503, 'V'), (0x504, 'M', u'ԅ'), (0x505, 'V'), (0x506, 'M', u'ԇ'), (0x507, 'V'), (0x508, 'M', u'ԉ'), (0x509, 'V'), (0x50A, 'M', u'ԋ'), (0x50B, 'V'), (0x50C, 'M', u'ԍ'), (0x50D, 'V'), (0x50E, 'M', u'ԏ'), (0x50F, 'V'), (0x510, 'M', u'ԑ'), (0x511, 'V'), (0x512, 'M', u'ԓ'), (0x513, 'V'), (0x514, 'M', u'ԕ'), (0x515, 'V'), (0x516, 'M', u'ԗ'), (0x517, 'V'), (0x518, 'M', u'ԙ'), (0x519, 'V'), (0x51A, 'M', u'ԛ'), (0x51B, 'V'), (0x51C, 'M', u'ԝ'), (0x51D, 'V'), (0x51E, 'M', u'ԟ'), (0x51F, 'V'), (0x520, 'M', u'ԡ'), (0x521, 'V'), (0x522, 'M', u'ԣ'), (0x523, 'V'), (0x524, 'M', u'ԥ'), (0x525, 'V'), (0x526, 'M', u'ԧ'), (0x527, 'V'), (0x528, 'M', u'ԩ'), (0x529, 'V'), (0x52A, 'M', u'ԫ'), (0x52B, 'V'), (0x52C, 'M', u'ԭ'), (0x52D, 'V'), (0x52E, 'M', u'ԯ'), (0x52F, 'V'), (0x530, 'X'), (0x531, 'M', u'ա'), (0x532, 'M', u'բ'), (0x533, 'M', u'գ'), (0x534, 'M', u'դ'), (0x535, 'M', u'ե'), (0x536, 'M', u'զ'), (0x537, 'M', u'է'), (0x538, 'M', u'ը'), (0x539, 'M', u'թ'), (0x53A, 'M', u'ժ'), (0x53B, 'M', u'ի'), (0x53C, 'M', u'լ'), (0x53D, 'M', u'խ'), (0x53E, 'M', u'ծ'), (0x53F, 'M', u'կ'), (0x540, 'M', u'հ'), (0x541, 'M', u'ձ'), (0x542, 'M', u'ղ'), (0x543, 'M', u'ճ'), (0x544, 'M', u'մ'), (0x545, 'M', u'յ'), (0x546, 'M', u'ն'), (0x547, 'M', u'շ'), (0x548, 'M', u'ո'), (0x549, 'M', u'չ'), (0x54A, 'M', u'պ'), (0x54B, 'M', u'ջ'), (0x54C, 'M', u'ռ'), (0x54D, 'M', u'ս'), (0x54E, 'M', u'վ'), (0x54F, 'M', u'տ'), (0x550, 'M', u'ր'), (0x551, 'M', u'ց'), (0x552, 'M', u'ւ'), (0x553, 'M', u'փ'), (0x554, 'M', u'ք'), (0x555, 'M', u'օ'), (0x556, 'M', u'ֆ'), (0x557, 'X'), (0x559, 'V'), (0x587, 'M', u'եւ'), (0x588, 'V'), (0x58B, 'X'), (0x58D, 'V'), (0x590, 'X'), (0x591, 'V'), (0x5C8, 'X'), (0x5D0, 'V'), (0x5EB, 'X'), (0x5EF, 'V'), (0x5F5, 'X'), (0x606, 'V'), (0x61C, 'X'), (0x61E, 'V'), ] def _seg_10(): return [ (0x675, 'M', u'اٴ'), (0x676, 'M', u'وٴ'), (0x677, 'M', u'ۇٴ'), (0x678, 'M', u'يٴ'), (0x679, 'V'), (0x6DD, 'X'), (0x6DE, 'V'), (0x70E, 'X'), (0x710, 'V'), (0x74B, 'X'), (0x74D, 'V'), (0x7B2, 'X'), (0x7C0, 'V'), (0x7FB, 'X'), (0x7FD, 'V'), (0x82E, 'X'), (0x830, 'V'), (0x83F, 'X'), (0x840, 'V'), (0x85C, 'X'), (0x85E, 'V'), (0x85F, 'X'), (0x860, 'V'), (0x86B, 'X'), (0x8A0, 'V'), (0x8B5, 'X'), (0x8B6, 'V'), (0x8BE, 'X'), (0x8D3, 'V'), (0x8E2, 'X'), (0x8E3, 'V'), (0x958, 'M', u'क़'), (0x959, 'M', u'ख़'), (0x95A, 'M', u'ग़'), (0x95B, 'M', u'ज़'), (0x95C, 'M', u'ड़'), (0x95D, 'M', u'ढ़'), (0x95E, 'M', u'फ़'), (0x95F, 'M', u'य़'), (0x960, 'V'), (0x984, 'X'), (0x985, 'V'), (0x98D, 'X'), (0x98F, 'V'), (0x991, 'X'), (0x993, 'V'), (0x9A9, 'X'), (0x9AA, 'V'), (0x9B1, 'X'), (0x9B2, 'V'), (0x9B3, 'X'), (0x9B6, 'V'), (0x9BA, 'X'), (0x9BC, 'V'), (0x9C5, 'X'), (0x9C7, 'V'), (0x9C9, 'X'), (0x9CB, 'V'), (0x9CF, 'X'), (0x9D7, 'V'), (0x9D8, 'X'), (0x9DC, 'M', u'ড়'), (0x9DD, 'M', u'ঢ়'), (0x9DE, 'X'), (0x9DF, 'M', u'য়'), (0x9E0, 'V'), (0x9E4, 'X'), (0x9E6, 'V'), (0x9FF, 'X'), (0xA01, 'V'), (0xA04, 'X'), (0xA05, 'V'), (0xA0B, 'X'), (0xA0F, 'V'), (0xA11, 'X'), (0xA13, 'V'), (0xA29, 'X'), (0xA2A, 'V'), (0xA31, 'X'), (0xA32, 'V'), (0xA33, 'M', u'ਲ਼'), (0xA34, 'X'), (0xA35, 'V'), (0xA36, 'M', u'ਸ਼'), (0xA37, 'X'), (0xA38, 'V'), (0xA3A, 'X'), (0xA3C, 'V'), (0xA3D, 'X'), (0xA3E, 'V'), (0xA43, 'X'), (0xA47, 'V'), (0xA49, 'X'), (0xA4B, 'V'), (0xA4E, 'X'), (0xA51, 'V'), (0xA52, 'X'), (0xA59, 'M', u'ਖ਼'), (0xA5A, 'M', u'ਗ਼'), (0xA5B, 'M', u'ਜ਼'), ] def _seg_11(): return [ (0xA5C, 'V'), (0xA5D, 'X'), (0xA5E, 'M', u'ਫ਼'), (0xA5F, 'X'), (0xA66, 'V'), (0xA77, 'X'), (0xA81, 'V'), (0xA84, 'X'), (0xA85, 'V'), (0xA8E, 'X'), (0xA8F, 'V'), (0xA92, 'X'), (0xA93, 'V'), (0xAA9, 'X'), (0xAAA, 'V'), (0xAB1, 'X'), (0xAB2, 'V'), (0xAB4, 'X'), (0xAB5, 'V'), (0xABA, 'X'), (0xABC, 'V'), (0xAC6, 'X'), (0xAC7, 'V'), (0xACA, 'X'), (0xACB, 'V'), (0xACE, 'X'), (0xAD0, 'V'), (0xAD1, 'X'), (0xAE0, 'V'), (0xAE4, 'X'), (0xAE6, 'V'), (0xAF2, 'X'), (0xAF9, 'V'), (0xB00, 'X'), (0xB01, 'V'), (0xB04, 'X'), (0xB05, 'V'), (0xB0D, 'X'), (0xB0F, 'V'), (0xB11, 'X'), (0xB13, 'V'), (0xB29, 'X'), (0xB2A, 'V'), (0xB31, 'X'), (0xB32, 'V'), (0xB34, 'X'), (0xB35, 'V'), (0xB3A, 'X'), (0xB3C, 'V'), (0xB45, 'X'), (0xB47, 'V'), (0xB49, 'X'), (0xB4B, 'V'), (0xB4E, 'X'), (0xB56, 'V'), (0xB58, 'X'), (0xB5C, 'M', u'ଡ଼'), (0xB5D, 'M', u'ଢ଼'), (0xB5E, 'X'), (0xB5F, 'V'), (0xB64, 'X'), (0xB66, 'V'), (0xB78, 'X'), (0xB82, 'V'), (0xB84, 'X'), (0xB85, 'V'), (0xB8B, 'X'), (0xB8E, 'V'), (0xB91, 'X'), (0xB92, 'V'), (0xB96, 'X'), (0xB99, 'V'), (0xB9B, 'X'), (0xB9C, 'V'), (0xB9D, 'X'), (0xB9E, 'V'), (0xBA0, 'X'), (0xBA3, 'V'), (0xBA5, 'X'), (0xBA8, 'V'), (0xBAB, 'X'), (0xBAE, 'V'), (0xBBA, 'X'), (0xBBE, 'V'), (0xBC3, 'X'), (0xBC6, 'V'), (0xBC9, 'X'), (0xBCA, 'V'), (0xBCE, 'X'), (0xBD0, 'V'), (0xBD1, 'X'), (0xBD7, 'V'), (0xBD8, 'X'), (0xBE6, 'V'), (0xBFB, 'X'), (0xC00, 'V'), (0xC0D, 'X'), (0xC0E, 'V'), (0xC11, 'X'), (0xC12, 'V'), ] def _seg_12(): return [ (0xC29, 'X'), (0xC2A, 'V'), (0xC3A, 'X'), (0xC3D, 'V'), (0xC45, 'X'), (0xC46, 'V'), (0xC49, 'X'), (0xC4A, 'V'), (0xC4E, 'X'), (0xC55, 'V'), (0xC57, 'X'), (0xC58, 'V'), (0xC5B, 'X'), (0xC60, 'V'), (0xC64, 'X'), (0xC66, 'V'), (0xC70, 'X'), (0xC78, 'V'), (0xC8D, 'X'), (0xC8E, 'V'), (0xC91, 'X'), (0xC92, 'V'), (0xCA9, 'X'), (0xCAA, 'V'), (0xCB4, 'X'), (0xCB5, 'V'), (0xCBA, 'X'), (0xCBC, 'V'), (0xCC5, 'X'), (0xCC6, 'V'), (0xCC9, 'X'), (0xCCA, 'V'), (0xCCE, 'X'), (0xCD5, 'V'), (0xCD7, 'X'), (0xCDE, 'V'), (0xCDF, 'X'), (0xCE0, 'V'), (0xCE4, 'X'), (0xCE6, 'V'), (0xCF0, 'X'), (0xCF1, 'V'), (0xCF3, 'X'), (0xD00, 'V'), (0xD04, 'X'), (0xD05, 'V'), (0xD0D, 'X'), (0xD0E, 'V'), (0xD11, 'X'), (0xD12, 'V'), (0xD45, 'X'), (0xD46, 'V'), (0xD49, 'X'), (0xD4A, 'V'), (0xD50, 'X'), (0xD54, 'V'), (0xD64, 'X'), (0xD66, 'V'), (0xD80, 'X'), (0xD82, 'V'), (0xD84, 'X'), (0xD85, 'V'), (0xD97, 'X'), (0xD9A, 'V'), (0xDB2, 'X'), (0xDB3, 'V'), (0xDBC, 'X'), (0xDBD, 'V'), (0xDBE, 'X'), (0xDC0, 'V'), (0xDC7, 'X'), (0xDCA, 'V'), (0xDCB, 'X'), (0xDCF, 'V'), (0xDD5, 'X'), (0xDD6, 'V'), (0xDD7, 'X'), (0xDD8, 'V'), (0xDE0, 'X'), (0xDE6, 'V'), (0xDF0, 'X'), (0xDF2, 'V'), (0xDF5, 'X'), (0xE01, 'V'), (0xE33, 'M', u'ํา'), (0xE34, 'V'), (0xE3B, 'X'), (0xE3F, 'V'), (0xE5C, 'X'), (0xE81, 'V'), (0xE83, 'X'), (0xE84, 'V'), (0xE85, 'X'), (0xE87, 'V'), (0xE89, 'X'), (0xE8A, 'V'), (0xE8B, 'X'), (0xE8D, 'V'), (0xE8E, 'X'), (0xE94, 'V'), ] def _seg_13(): return [ (0xE98, 'X'), (0xE99, 'V'), (0xEA0, 'X'), (0xEA1, 'V'), (0xEA4, 'X'), (0xEA5, 'V'), (0xEA6, 'X'), (0xEA7, 'V'), (0xEA8, 'X'), (0xEAA, 'V'), (0xEAC, 'X'), (0xEAD, 'V'), (0xEB3, 'M', u'ໍາ'), (0xEB4, 'V'), (0xEBA, 'X'), (0xEBB, 'V'), (0xEBE, 'X'), (0xEC0, 'V'), (0xEC5, 'X'), (0xEC6, 'V'), (0xEC7, 'X'), (0xEC8, 'V'), (0xECE, 'X'), (0xED0, 'V'), (0xEDA, 'X'), (0xEDC, 'M', u'ຫນ'), (0xEDD, 'M', u'ຫມ'), (0xEDE, 'V'), (0xEE0, 'X'), (0xF00, 'V'), (0xF0C, 'M', u'་'), (0xF0D, 'V'), (0xF43, 'M', u'གྷ'), (0xF44, 'V'), (0xF48, 'X'), (0xF49, 'V'), (0xF4D, 'M', u'ཌྷ'), (0xF4E, 'V'), (0xF52, 'M', u'དྷ'), (0xF53, 'V'), (0xF57, 'M', u'བྷ'), (0xF58, 'V'), (0xF5C, 'M', u'ཛྷ'), (0xF5D, 'V'), (0xF69, 'M', u'ཀྵ'), (0xF6A, 'V'), (0xF6D, 'X'), (0xF71, 'V'), (0xF73, 'M', u'ཱི'), (0xF74, 'V'), (0xF75, 'M', u'ཱུ'), (0xF76, 'M', u'ྲྀ'), (0xF77, 'M', u'ྲཱྀ'), (0xF78, 'M', u'ླྀ'), (0xF79, 'M', u'ླཱྀ'), (0xF7A, 'V'), (0xF81, 'M', u'ཱྀ'), (0xF82, 'V'), (0xF93, 'M', u'ྒྷ'), (0xF94, 'V'), (0xF98, 'X'), (0xF99, 'V'), (0xF9D, 'M', u'ྜྷ'), (0xF9E, 'V'), (0xFA2, 'M', u'ྡྷ'), (0xFA3, 'V'), (0xFA7, 'M', u'ྦྷ'), (0xFA8, 'V'), (0xFAC, 'M', u'ྫྷ'), (0xFAD, 'V'), (0xFB9, 'M', u'ྐྵ'), (0xFBA, 'V'), (0xFBD, 'X'), (0xFBE, 'V'), (0xFCD, 'X'), (0xFCE, 'V'), (0xFDB, 'X'), (0x1000, 'V'), (0x10A0, 'X'), (0x10C7, 'M', u'ⴧ'), (0x10C8, 'X'), (0x10CD, 'M', u'ⴭ'), (0x10CE, 'X'), (0x10D0, 'V'), (0x10FC, 'M', u'ნ'), (0x10FD, 'V'), (0x115F, 'X'), (0x1161, 'V'), (0x1249, 'X'), (0x124A, 'V'), (0x124E, 'X'), (0x1250, 'V'), (0x1257, 'X'), (0x1258, 'V'), (0x1259, 'X'), (0x125A, 'V'), (0x125E, 'X'), (0x1260, 'V'), (0x1289, 'X'), (0x128A, 'V'), ] def _seg_14(): return [ (0x128E, 'X'), (0x1290, 'V'), (0x12B1, 'X'), (0x12B2, 'V'), (0x12B6, 'X'), (0x12B8, 'V'), (0x12BF, 'X'), (0x12C0, 'V'), (0x12C1, 'X'), (0x12C2, 'V'), (0x12C6, 'X'), (0x12C8, 'V'), (0x12D7, 'X'), (0x12D8, 'V'), (0x1311, 'X'), (0x1312, 'V'), (0x1316, 'X'), (0x1318, 'V'), (0x135B, 'X'), (0x135D, 'V'), (0x137D, 'X'), (0x1380, 'V'), (0x139A, 'X'), (0x13A0, 'V'), (0x13F6, 'X'), (0x13F8, 'M', u'Ᏸ'), (0x13F9, 'M', u'Ᏹ'), (0x13FA, 'M', u'Ᏺ'), (0x13FB, 'M', u'Ᏻ'), (0x13FC, 'M', u'Ᏼ'), (0x13FD, 'M', u'Ᏽ'), (0x13FE, 'X'), (0x1400, 'V'), (0x1680, 'X'), (0x1681, 'V'), (0x169D, 'X'), (0x16A0, 'V'), (0x16F9, 'X'), (0x1700, 'V'), (0x170D, 'X'), (0x170E, 'V'), (0x1715, 'X'), (0x1720, 'V'), (0x1737, 'X'), (0x1740, 'V'), (0x1754, 'X'), (0x1760, 'V'), (0x176D, 'X'), (0x176E, 'V'), (0x1771, 'X'), (0x1772, 'V'), (0x1774, 'X'), (0x1780, 'V'), (0x17B4, 'X'), (0x17B6, 'V'), (0x17DE, 'X'), (0x17E0, 'V'), (0x17EA, 'X'), (0x17F0, 'V'), (0x17FA, 'X'), (0x1800, 'V'), (0x1806, 'X'), (0x1807, 'V'), (0x180B, 'I'), (0x180E, 'X'), (0x1810, 'V'), (0x181A, 'X'), (0x1820, 'V'), (0x1879, 'X'), (0x1880, 'V'), (0x18AB, 'X'), (0x18B0, 'V'), (0x18F6, 'X'), (0x1900, 'V'), (0x191F, 'X'), (0x1920, 'V'), (0x192C, 'X'), (0x1930, 'V'), (0x193C, 'X'), (0x1940, 'V'), (0x1941, 'X'), (0x1944, 'V'), (0x196E, 'X'), (0x1970, 'V'), (0x1975, 'X'), (0x1980, 'V'), (0x19AC, 'X'), (0x19B0, 'V'), (0x19CA, 'X'), (0x19D0, 'V'), (0x19DB, 'X'), (0x19DE, 'V'), (0x1A1C, 'X'), (0x1A1E, 'V'), (0x1A5F, 'X'), (0x1A60, 'V'), (0x1A7D, 'X'), (0x1A7F, 'V'), (0x1A8A, 'X'), (0x1A90, 'V'), ] def _seg_15(): return [ (0x1A9A, 'X'), (0x1AA0, 'V'), (0x1AAE, 'X'), (0x1AB0, 'V'), (0x1ABF, 'X'), (0x1B00, 'V'), (0x1B4C, 'X'), (0x1B50, 'V'), (0x1B7D, 'X'), (0x1B80, 'V'), (0x1BF4, 'X'), (0x1BFC, 'V'), (0x1C38, 'X'), (0x1C3B, 'V'), (0x1C4A, 'X'), (0x1C4D, 'V'), (0x1C80, 'M', u'в'), (0x1C81, 'M', u'д'), (0x1C82, 'M', u'о'), (0x1C83, 'M', u'с'), (0x1C84, 'M', u'т'), (0x1C86, 'M', u'ъ'), (0x1C87, 'M', u'ѣ'), (0x1C88, 'M', u'ꙋ'), (0x1C89, 'X'), (0x1CC0, 'V'), (0x1CC8, 'X'), (0x1CD0, 'V'), (0x1CFA, 'X'), (0x1D00, 'V'), (0x1D2C, 'M', u'a'), (0x1D2D, 'M', u'æ'), (0x1D2E, 'M', u'b'), (0x1D2F, 'V'), (0x1D30, 'M', u'd'), (0x1D31, 'M', u'e'), (0x1D32, 'M', u'ǝ'), (0x1D33, 'M', u'g'), (0x1D34, 'M', u'h'), (0x1D35, 'M', u'i'), (0x1D36, 'M', u'j'), (0x1D37, 'M', u'k'), (0x1D38, 'M', u'l'), (0x1D39, 'M', u'm'), (0x1D3A, 'M', u'n'), (0x1D3B, 'V'), (0x1D3C, 'M', u'o'), (0x1D3D, 'M', u'ȣ'), (0x1D3E, 'M', u'p'), (0x1D3F, 'M', u'r'), (0x1D40, 'M', u't'), (0x1D41, 'M', u'u'), (0x1D42, 'M', u'w'), (0x1D43, 'M', u'a'), (0x1D44, 'M', u'ɐ'), (0x1D45, 'M', u'ɑ'), (0x1D46, 'M', u'ᴂ'), (0x1D47, 'M', u'b'), (0x1D48, 'M', u'd'), (0x1D49, 'M', u'e'), (0x1D4A, 'M', u'ə'), (0x1D4B, 'M', u'ɛ'), (0x1D4C, 'M', u'ɜ'), (0x1D4D, 'M', u'g'), (0x1D4E, 'V'), (0x1D4F, 'M', u'k'), (0x1D50, 'M', u'm'), (0x1D51, 'M', u'ŋ'), (0x1D52, 'M', u'o'), (0x1D53, 'M', u'ɔ'), (0x1D54, 'M', u'ᴖ'), (0x1D55, 'M', u'ᴗ'), (0x1D56, 'M', u'p'), (0x1D57, 'M', u't'), (0x1D58, 'M', u'u'), (0x1D59, 'M', u'ᴝ'), (0x1D5A, 'M', u'ɯ'), (0x1D5B, 'M', u'v'), (0x1D5C, 'M', u'ᴥ'), (0x1D5D, 'M', u'β'), (0x1D5E, 'M', u'γ'), (0x1D5F, 'M', u'δ'), (0x1D60, 'M', u'φ'), (0x1D61, 'M', u'χ'), (0x1D62, 'M', u'i'), (0x1D63, 'M', u'r'), (0x1D64, 'M', u'u'), (0x1D65, 'M', u'v'), (0x1D66, 'M', u'β'), (0x1D67, 'M', u'γ'), (0x1D68, 'M', u'ρ'), (0x1D69, 'M', u'φ'), (0x1D6A, 'M', u'χ'), (0x1D6B, 'V'), (0x1D78, 'M', u'н'), (0x1D79, 'V'), (0x1D9B, 'M', u'ɒ'), (0x1D9C, 'M', u'c'), (0x1D9D, 'M', u'ɕ'), (0x1D9E, 'M', u'ð'), ] def _seg_16(): return [ (0x1D9F, 'M', u'ɜ'), (0x1DA0, 'M', u'f'), (0x1DA1, 'M', u'ɟ'), (0x1DA2, 'M', u'ɡ'), (0x1DA3, 'M', u'ɥ'), (0x1DA4, 'M', u'ɨ'), (0x1DA5, 'M', u'ɩ'), (0x1DA6, 'M', u'ɪ'), (0x1DA7, 'M', u'ᵻ'), (0x1DA8, 'M', u'ʝ'), (0x1DA9, 'M', u'ɭ'), (0x1DAA, 'M', u'ᶅ'), (0x1DAB, 'M', u'ʟ'), (0x1DAC, 'M', u'ɱ'), (0x1DAD, 'M', u'ɰ'), (0x1DAE, 'M', u'ɲ'), (0x1DAF, 'M', u'ɳ'), (0x1DB0, 'M', u'ɴ'), (0x1DB1, 'M', u'ɵ'), (0x1DB2, 'M', u'ɸ'), (0x1DB3, 'M', u'ʂ'), (0x1DB4, 'M', u'ʃ'), (0x1DB5, 'M', u'ƫ'), (0x1DB6, 'M', u'ʉ'), (0x1DB7, 'M', u'ʊ'), (0x1DB8, 'M', u'ᴜ'), (0x1DB9, 'M', u'ʋ'), (0x1DBA, 'M', u'ʌ'), (0x1DBB, 'M', u'z'), (0x1DBC, 'M', u'ʐ'), (0x1DBD, 'M', u'ʑ'), (0x1DBE, 'M', u'ʒ'), (0x1DBF, 'M', u'θ'), (0x1DC0, 'V'), (0x1DFA, 'X'), (0x1DFB, 'V'), (0x1E00, 'M', u'ḁ'), (0x1E01, 'V'), (0x1E02, 'M', u'ḃ'), (0x1E03, 'V'), (0x1E04, 'M', u'ḅ'), (0x1E05, 'V'), (0x1E06, 'M', u'ḇ'), (0x1E07, 'V'), (0x1E08, 'M', u'ḉ'), (0x1E09, 'V'), (0x1E0A, 'M', u'ḋ'), (0x1E0B, 'V'), (0x1E0C, 'M', u'ḍ'), (0x1E0D, 'V'), (0x1E0E, 'M', u'ḏ'), (0x1E0F, 'V'), (0x1E10, 'M', u'ḑ'), (0x1E11, 'V'), (0x1E12, 'M', u'ḓ'), (0x1E13, 'V'), (0x1E14, 'M', u'ḕ'), (0x1E15, 'V'), (0x1E16, 'M', u'ḗ'), (0x1E17, 'V'), (0x1E18, 'M', u'ḙ'), (0x1E19, 'V'), (0x1E1A, 'M', u'ḛ'), (0x1E1B, 'V'), (0x1E1C, 'M', u'ḝ'), (0x1E1D, 'V'), (0x1E1E, 'M', u'ḟ'), (0x1E1F, 'V'), (0x1E20, 'M', u'ḡ'), (0x1E21, 'V'), (0x1E22, 'M', u'ḣ'), (0x1E23, 'V'), (0x1E24, 'M', u'ḥ'), (0x1E25, 'V'), (0x1E26, 'M', u'ḧ'), (0x1E27, 'V'), (0x1E28, 'M', u'ḩ'), (0x1E29, 'V'), (0x1E2A, 'M', u'ḫ'), (0x1E2B, 'V'), (0x1E2C, 'M', u'ḭ'), (0x1E2D, 'V'), (0x1E2E, 'M', u'ḯ'), (0x1E2F, 'V'), (0x1E30, 'M', u'ḱ'), (0x1E31, 'V'), (0x1E32, 'M', u'ḳ'), (0x1E33, 'V'), (0x1E34, 'M', u'ḵ'), (0x1E35, 'V'), (0x1E36, 'M', u'ḷ'), (0x1E37, 'V'), (0x1E38, 'M', u'ḹ'), (0x1E39, 'V'), (0x1E3A, 'M', u'ḻ'), (0x1E3B, 'V'), (0x1E3C, 'M', u'ḽ'), (0x1E3D, 'V'), (0x1E3E, 'M', u'ḿ'), (0x1E3F, 'V'), ] def _seg_17(): return [ (0x1E40, 'M', u'ṁ'), (0x1E41, 'V'), (0x1E42, 'M', u'ṃ'), (0x1E43, 'V'), (0x1E44, 'M', u'ṅ'), (0x1E45, 'V'), (0x1E46, 'M', u'ṇ'), (0x1E47, 'V'), (0x1E48, 'M', u'ṉ'), (0x1E49, 'V'), (0x1E4A, 'M', u'ṋ'), (0x1E4B, 'V'), (0x1E4C, 'M', u'ṍ'), (0x1E4D, 'V'), (0x1E4E, 'M', u'ṏ'), (0x1E4F, 'V'), (0x1E50, 'M', u'ṑ'), (0x1E51, 'V'), (0x1E52, 'M', u'ṓ'), (0x1E53, 'V'), (0x1E54, 'M', u'ṕ'), (0x1E55, 'V'), (0x1E56, 'M', u'ṗ'), (0x1E57, 'V'), (0x1E58, 'M', u'ṙ'), (0x1E59, 'V'), (0x1E5A, 'M', u'ṛ'), (0x1E5B, 'V'), (0x1E5C, 'M', u'ṝ'), (0x1E5D, 'V'), (0x1E5E, 'M', u'ṟ'), (0x1E5F, 'V'), (0x1E60, 'M', u'ṡ'), (0x1E61, 'V'), (0x1E62, 'M', u'ṣ'), (0x1E63, 'V'), (0x1E64, 'M', u'ṥ'), (0x1E65, 'V'), (0x1E66, 'M', u'ṧ'), (0x1E67, 'V'), (0x1E68, 'M', u'ṩ'), (0x1E69, 'V'), (0x1E6A, 'M', u'ṫ'), (0x1E6B, 'V'), (0x1E6C, 'M', u'ṭ'), (0x1E6D, 'V'), (0x1E6E, 'M', u'ṯ'), (0x1E6F, 'V'), (0x1E70, 'M', u'ṱ'), (0x1E71, 'V'), (0x1E72, 'M', u'ṳ'), (0x1E73, 'V'), (0x1E74, 'M', u'ṵ'), (0x1E75, 'V'), (0x1E76, 'M', u'ṷ'), (0x1E77, 'V'), (0x1E78, 'M', u'ṹ'), (0x1E79, 'V'), (0x1E7A, 'M', u'ṻ'), (0x1E7B, 'V'), (0x1E7C, 'M', u'ṽ'), (0x1E7D, 'V'), (0x1E7E, 'M', u'ṿ'), (0x1E7F, 'V'), (0x1E80, 'M', u'ẁ'), (0x1E81, 'V'), (0x1E82, 'M', u'ẃ'), (0x1E83, 'V'), (0x1E84, 'M', u'ẅ'), (0x1E85, 'V'), (0x1E86, 'M', u'ẇ'), (0x1E87, 'V'), (0x1E88, 'M', u'ẉ'), (0x1E89, 'V'), (0x1E8A, 'M', u'ẋ'), (0x1E8B, 'V'), (0x1E8C, 'M', u'ẍ'), (0x1E8D, 'V'), (0x1E8E, 'M', u'ẏ'), (0x1E8F, 'V'), (0x1E90, 'M', u'ẑ'), (0x1E91, 'V'), (0x1E92, 'M', u'ẓ'), (0x1E93, 'V'), (0x1E94, 'M', u'ẕ'), (0x1E95, 'V'), (0x1E9A, 'M', u'aʾ'), (0x1E9B, 'M', u'ṡ'), (0x1E9C, 'V'), (0x1E9E, 'M', u'ss'), (0x1E9F, 'V'), (0x1EA0, 'M', u'ạ'), (0x1EA1, 'V'), (0x1EA2, 'M', u'ả'), (0x1EA3, 'V'), (0x1EA4, 'M', u'ấ'), (0x1EA5, 'V'), (0x1EA6, 'M', u'ầ'), (0x1EA7, 'V'), (0x1EA8, 'M', u'ẩ'), ] def _seg_18(): return [ (0x1EA9, 'V'), (0x1EAA, 'M', u'ẫ'), (0x1EAB, 'V'), (0x1EAC, 'M', u'ậ'), (0x1EAD, 'V'), (0x1EAE, 'M', u'ắ'), (0x1EAF, 'V'), (0x1EB0, 'M', u'ằ'), (0x1EB1, 'V'), (0x1EB2, 'M', u'ẳ'), (0x1EB3, 'V'), (0x1EB4, 'M', u'ẵ'), (0x1EB5, 'V'), (0x1EB6, 'M', u'ặ'), (0x1EB7, 'V'), (0x1EB8, 'M', u'ẹ'), (0x1EB9, 'V'), (0x1EBA, 'M', u'ẻ'), (0x1EBB, 'V'), (0x1EBC, 'M', u'ẽ'), (0x1EBD, 'V'), (0x1EBE, 'M', u'ế'), (0x1EBF, 'V'), (0x1EC0, 'M', u'ề'), (0x1EC1, 'V'), (0x1EC2, 'M', u'ể'), (0x1EC3, 'V'), (0x1EC4, 'M', u'ễ'), (0x1EC5, 'V'), (0x1EC6, 'M', u'ệ'), (0x1EC7, 'V'), (0x1EC8, 'M', u'ỉ'), (0x1EC9, 'V'), (0x1ECA, 'M', u'ị'), (0x1ECB, 'V'), (0x1ECC, 'M', u'ọ'), (0x1ECD, 'V'), (0x1ECE, 'M', u'ỏ'), (0x1ECF, 'V'), (0x1ED0, 'M', u'ố'), (0x1ED1, 'V'), (0x1ED2, 'M', u'ồ'), (0x1ED3, 'V'), (0x1ED4, 'M', u'ổ'), (0x1ED5, 'V'), (0x1ED6, 'M', u'ỗ'), (0x1ED7, 'V'), (0x1ED8, 'M', u'ộ'), (0x1ED9, 'V'), (0x1EDA, 'M', u'ớ'), (0x1EDB, 'V'), (0x1EDC, 'M', u'ờ'), (0x1EDD, 'V'), (0x1EDE, 'M', u'ở'), (0x1EDF, 'V'), (0x1EE0, 'M', u'ỡ'), (0x1EE1, 'V'), (0x1EE2, 'M', u'ợ'), (0x1EE3, 'V'), (0x1EE4, 'M', u'ụ'), (0x1EE5, 'V'), (0x1EE6, 'M', u'ủ'), (0x1EE7, 'V'), (0x1EE8, 'M', u'ứ'), (0x1EE9, 'V'), (0x1EEA, 'M', u'ừ'), (0x1EEB, 'V'), (0x1EEC, 'M', u'ử'), (0x1EED, 'V'), (0x1EEE, 'M', u'ữ'), (0x1EEF, 'V'), (0x1EF0, 'M', u'ự'), (0x1EF1, 'V'), (0x1EF2, 'M', u'ỳ'), (0x1EF3, 'V'), (0x1EF4, 'M', u'ỵ'), (0x1EF5, 'V'), (0x1EF6, 'M', u'ỷ'), (0x1EF7, 'V'), (0x1EF8, 'M', u'ỹ'), (0x1EF9, 'V'), (0x1EFA, 'M', u'ỻ'), (0x1EFB, 'V'), (0x1EFC, 'M', u'ỽ'), (0x1EFD, 'V'), (0x1EFE, 'M', u'ỿ'), (0x1EFF, 'V'), (0x1F08, 'M', u'ἀ'), (0x1F09, 'M', u'ἁ'), (0x1F0A, 'M', u'ἂ'), (0x1F0B, 'M', u'ἃ'), (0x1F0C, 'M', u'ἄ'), (0x1F0D, 'M', u'ἅ'), (0x1F0E, 'M', u'ἆ'), (0x1F0F, 'M', u'ἇ'), (0x1F10, 'V'), (0x1F16, 'X'), (0x1F18, 'M', u'ἐ'), (0x1F19, 'M', u'ἑ'), (0x1F1A, 'M', u'ἒ'), ] def _seg_19(): return [ (0x1F1B, 'M', u'ἓ'), (0x1F1C, 'M', u'ἔ'), (0x1F1D, 'M', u'ἕ'), (0x1F1E, 'X'), (0x1F20, 'V'), (0x1F28, 'M', u'ἠ'), (0x1F29, 'M', u'ἡ'), (0x1F2A, 'M', u'ἢ'), (0x1F2B, 'M', u'ἣ'), (0x1F2C, 'M', u'ἤ'), (0x1F2D, 'M', u'ἥ'), (0x1F2E, 'M', u'ἦ'), (0x1F2F, 'M', u'ἧ'), (0x1F30, 'V'), (0x1F38, 'M', u'ἰ'), (0x1F39, 'M', u'ἱ'), (0x1F3A, 'M', u'ἲ'), (0x1F3B, 'M', u'ἳ'), (0x1F3C, 'M', u'ἴ'), (0x1F3D, 'M', u'ἵ'), (0x1F3E, 'M', u'ἶ'), (0x1F3F, 'M', u'ἷ'), (0x1F40, 'V'), (0x1F46, 'X'), (0x1F48, 'M', u'ὀ'), (0x1F49, 'M', u'ὁ'), (0x1F4A, 'M', u'ὂ'), (0x1F4B, 'M', u'ὃ'), (0x1F4C, 'M', u'ὄ'), (0x1F4D, 'M', u'ὅ'), (0x1F4E, 'X'), (0x1F50, 'V'), (0x1F58, 'X'), (0x1F59, 'M', u'ὑ'), (0x1F5A, 'X'), (0x1F5B, 'M', u'ὓ'), (0x1F5C, 'X'), (0x1F5D, 'M', u'ὕ'), (0x1F5E, 'X'), (0x1F5F, 'M', u'ὗ'), (0x1F60, 'V'), (0x1F68, 'M', u'ὠ'), (0x1F69, 'M', u'ὡ'), (0x1F6A, 'M', u'ὢ'), (0x1F6B, 'M', u'ὣ'), (0x1F6C, 'M', u'ὤ'), (0x1F6D, 'M', u'ὥ'), (0x1F6E, 'M', u'ὦ'), (0x1F6F, 'M', u'ὧ'), (0x1F70, 'V'), (0x1F71, 'M', u'ά'), (0x1F72, 'V'), (0x1F73, 'M', u'έ'), (0x1F74, 'V'), (0x1F75, 'M', u'ή'), (0x1F76, 'V'), (0x1F77, 'M', u'ί'), (0x1F78, 'V'), (0x1F79, 'M', u'ό'), (0x1F7A, 'V'), (0x1F7B, 'M', u'ύ'), (0x1F7C, 'V'), (0x1F7D, 'M', u'ώ'), (0x1F7E, 'X'), (0x1F80, 'M', u'ἀι'), (0x1F81, 'M', u'ἁι'), (0x1F82, 'M', u'ἂι'), (0x1F83, 'M', u'ἃι'), (0x1F84, 'M', u'ἄι'), (0x1F85, 'M', u'ἅι'), (0x1F86, 'M', u'ἆι'), (0x1F87, 'M', u'ἇι'), (0x1F88, 'M', u'ἀι'), (0x1F89, 'M', u'ἁι'), (0x1F8A, 'M', u'ἂι'), (0x1F8B, 'M', u'ἃι'), (0x1F8C, 'M', u'ἄι'), (0x1F8D, 'M', u'ἅι'), (0x1F8E, 'M', u'ἆι'), (0x1F8F, 'M', u'ἇι'), (0x1F90, 'M', u'ἠι'), (0x1F91, 'M', u'ἡι'), (0x1F92, 'M', u'ἢι'), (0x1F93, 'M', u'ἣι'), (0x1F94, 'M', u'ἤι'), (0x1F95, 'M', u'ἥι'), (0x1F96, 'M', u'ἦι'), (0x1F97, 'M', u'ἧι'), (0x1F98, 'M', u'ἠι'), (0x1F99, 'M', u'ἡι'), (0x1F9A, 'M', u'ἢι'), (0x1F9B, 'M', u'ἣι'), (0x1F9C, 'M', u'ἤι'), (0x1F9D, 'M', u'ἥι'), (0x1F9E, 'M', u'ἦι'), (0x1F9F, 'M', u'ἧι'), (0x1FA0, 'M', u'ὠι'), (0x1FA1, 'M', u'ὡι'), (0x1FA2, 'M', u'ὢι'), (0x1FA3, 'M', u'ὣι'), ] def _seg_20(): return [ (0x1FA4, 'M', u'ὤι'), (0x1FA5, 'M', u'ὥι'), (0x1FA6, 'M', u'ὦι'), (0x1FA7, 'M', u'ὧι'), (0x1FA8, 'M', u'ὠι'), (0x1FA9, 'M', u'ὡι'), (0x1FAA, 'M', u'ὢι'), (0x1FAB, 'M', u'ὣι'), (0x1FAC, 'M', u'ὤι'), (0x1FAD, 'M', u'ὥι'), (0x1FAE, 'M', u'ὦι'), (0x1FAF, 'M', u'ὧι'), (0x1FB0, 'V'), (0x1FB2, 'M', u'ὰι'), (0x1FB3, 'M', u'αι'), (0x1FB4, 'M', u'άι'), (0x1FB5, 'X'), (0x1FB6, 'V'), (0x1FB7, 'M', u'ᾶι'), (0x1FB8, 'M', u'ᾰ'), (0x1FB9, 'M', u'ᾱ'), (0x1FBA, 'M', u'ὰ'), (0x1FBB, 'M', u'ά'), (0x1FBC, 'M', u'αι'), (0x1FBD, '3', u' ̓'), (0x1FBE, 'M', u'ι'), (0x1FBF, '3', u' ̓'), (0x1FC0, '3', u' ͂'), (0x1FC1, '3', u' ̈͂'), (0x1FC2, 'M', u'ὴι'), (0x1FC3, 'M', u'ηι'), (0x1FC4, 'M', u'ήι'), (0x1FC5, 'X'), (0x1FC6, 'V'), (0x1FC7, 'M', u'ῆι'), (0x1FC8, 'M', u'ὲ'), (0x1FC9, 'M', u'έ'), (0x1FCA, 'M', u'ὴ'), (0x1FCB, 'M', u'ή'), (0x1FCC, 'M', u'ηι'), (0x1FCD, '3', u' ̓̀'), (0x1FCE, '3', u' ̓́'), (0x1FCF, '3', u' ̓͂'), (0x1FD0, 'V'), (0x1FD3, 'M', u'ΐ'), (0x1FD4, 'X'), (0x1FD6, 'V'), (0x1FD8, 'M', u'ῐ'), (0x1FD9, 'M', u'ῑ'), (0x1FDA, 'M', u'ὶ'), (0x1FDB, 'M', u'ί'), (0x1FDC, 'X'), (0x1FDD, '3', u' ̔̀'), (0x1FDE, '3', u' ̔́'), (0x1FDF, '3', u' ̔͂'), (0x1FE0, 'V'), (0x1FE3, 'M', u'ΰ'), (0x1FE4, 'V'), (0x1FE8, 'M', u'ῠ'), (0x1FE9, 'M', u'ῡ'), (0x1FEA, 'M', u'ὺ'), (0x1FEB, 'M', u'ύ'), (0x1FEC, 'M', u'ῥ'), (0x1FED, '3', u' ̈̀'), (0x1FEE, '3', u' ̈́'), (0x1FEF, '3', u'`'), (0x1FF0, 'X'), (0x1FF2, 'M', u'ὼι'), (0x1FF3, 'M', u'ωι'), (0x1FF4, 'M', u'ώι'), (0x1FF5, 'X'), (0x1FF6, 'V'), (0x1FF7, 'M', u'ῶι'), (0x1FF8, 'M', u'ὸ'), (0x1FF9, 'M', u'ό'), (0x1FFA, 'M', u'ὼ'), (0x1FFB, 'M', u'ώ'), (0x1FFC, 'M', u'ωι'), (0x1FFD, '3', u' ́'), (0x1FFE, '3', u' ̔'), (0x1FFF, 'X'), (0x2000, '3', u' '), (0x200B, 'I'), (0x200C, 'D', u''), (0x200E, 'X'), (0x2010, 'V'), (0x2011, 'M', u'‐'), (0x2012, 'V'), (0x2017, '3', u' ̳'), (0x2018, 'V'), (0x2024, 'X'), (0x2027, 'V'), (0x2028, 'X'), (0x202F, '3', u' '), (0x2030, 'V'), (0x2033, 'M', u'′′'), (0x2034, 'M', u'′′′'), (0x2035, 'V'), (0x2036, 'M', u'‵‵'), (0x2037, 'M', u'‵‵‵'), ] def _seg_21(): return [ (0x2038, 'V'), (0x203C, '3', u'!!'), (0x203D, 'V'), (0x203E, '3', u' ̅'), (0x203F, 'V'), (0x2047, '3', u'??'), (0x2048, '3', u'?!'), (0x2049, '3', u'!?'), (0x204A, 'V'), (0x2057, 'M', u'′′′′'), (0x2058, 'V'), (0x205F, '3', u' '), (0x2060, 'I'), (0x2061, 'X'), (0x2064, 'I'), (0x2065, 'X'), (0x2070, 'M', u'0'), (0x2071, 'M', u'i'), (0x2072, 'X'), (0x2074, 'M', u'4'), (0x2075, 'M', u'5'), (0x2076, 'M', u'6'), (0x2077, 'M', u'7'), (0x2078, 'M', u'8'), (0x2079, 'M', u'9'), (0x207A, '3', u'+'), (0x207B, 'M', u'−'), (0x207C, '3', u'='), (0x207D, '3', u'('), (0x207E, '3', u')'), (0x207F, 'M', u'n'), (0x2080, 'M', u'0'), (0x2081, 'M', u'1'), (0x2082, 'M', u'2'), (0x2083, 'M', u'3'), (0x2084, 'M', u'4'), (0x2085, 'M', u'5'), (0x2086, 'M', u'6'), (0x2087, 'M', u'7'), (0x2088, 'M', u'8'), (0x2089, 'M', u'9'), (0x208A, '3', u'+'), (0x208B, 'M', u'−'), (0x208C, '3', u'='), (0x208D, '3', u'('), (0x208E, '3', u')'), (0x208F, 'X'), (0x2090, 'M', u'a'), (0x2091, 'M', u'e'), (0x2092, 'M', u'o'), (0x2093, 'M', u'x'), (0x2094, 'M', u'ə'), (0x2095, 'M', u'h'), (0x2096, 'M', u'k'), (0x2097, 'M', u'l'), (0x2098, 'M', u'm'), (0x2099, 'M', u'n'), (0x209A, 'M', u'p'), (0x209B, 'M', u's'), (0x209C, 'M', u't'), (0x209D, 'X'), (0x20A0, 'V'), (0x20A8, 'M', u'rs'), (0x20A9, 'V'), (0x20C0, 'X'), (0x20D0, 'V'), (0x20F1, 'X'), (0x2100, '3', u'a/c'), (0x2101, '3', u'a/s'), (0x2102, 'M', u'c'), (0x2103, 'M', u'°c'), (0x2104, 'V'), (0x2105, '3', u'c/o'), (0x2106, '3', u'c/u'), (0x2107, 'M', u'ɛ'), (0x2108, 'V'), (0x2109, 'M', u'°f'), (0x210A, 'M', u'g'), (0x210B, 'M', u'h'), (0x210F, 'M', u'ħ'), (0x2110, 'M', u'i'), (0x2112, 'M', u'l'), (0x2114, 'V'), (0x2115, 'M', u'n'), (0x2116, 'M', u'no'), (0x2117, 'V'), (0x2119, 'M', u'p'), (0x211A, 'M', u'q'), (0x211B, 'M', u'r'), (0x211E, 'V'), (0x2120, 'M', u'sm'), (0x2121, 'M', u'tel'), (0x2122, 'M', u'tm'), (0x2123, 'V'), (0x2124, 'M', u'z'), (0x2125, 'V'), (0x2126, 'M', u'ω'), (0x2127, 'V'), (0x2128, 'M', u'z'), (0x2129, 'V'), ] def _seg_22(): return [ (0x212A, 'M', u'k'), (0x212B, 'M', u'å'), (0x212C, 'M', u'b'), (0x212D, 'M', u'c'), (0x212E, 'V'), (0x212F, 'M', u'e'), (0x2131, 'M', u'f'), (0x2132, 'X'), (0x2133, 'M', u'm'), (0x2134, 'M', u'o'), (0x2135, 'M', u'א'), (0x2136, 'M', u'ב'), (0x2137, 'M', u'ג'), (0x2138, 'M', u'ד'), (0x2139, 'M', u'i'), (0x213A, 'V'), (0x213B, 'M', u'fax'), (0x213C, 'M', u'π'), (0x213D, 'M', u'γ'), (0x213F, 'M', u'π'), (0x2140, 'M', u'∑'), (0x2141, 'V'), (0x2145, 'M', u'd'), (0x2147, 'M', u'e'), (0x2148, 'M', u'i'), (0x2149, 'M', u'j'), (0x214A, 'V'), (0x2150, 'M', u'1⁄7'), (0x2151, 'M', u'1⁄9'), (0x2152, 'M', u'1⁄10'), (0x2153, 'M', u'1⁄3'), (0x2154, 'M', u'2⁄3'), (0x2155, 'M', u'1⁄5'), (0x2156, 'M', u'2⁄5'), (0x2157, 'M', u'3⁄5'), (0x2158, 'M', u'4⁄5'), (0x2159, 'M', u'1⁄6'), (0x215A, 'M', u'5⁄6'), (0x215B, 'M', u'1⁄8'), (0x215C, 'M', u'3⁄8'), (0x215D, 'M', u'5⁄8'), (0x215E, 'M', u'7⁄8'), (0x215F, 'M', u'1⁄'), (0x2160, 'M', u'i'), (0x2161, 'M', u'ii'), (0x2162, 'M', u'iii'), (0x2163, 'M', u'iv'), (0x2164, 'M', u'v'), (0x2165, 'M', u'vi'), (0x2166, 'M', u'vii'), (0x2167, 'M', u'viii'), (0x2168, 'M', u'ix'), (0x2169, 'M', u'x'), (0x216A, 'M', u'xi'), (0x216B, 'M', u'xii'), (0x216C, 'M', u'l'), (0x216D, 'M', u'c'), (0x216E, 'M', u'd'), (0x216F, 'M', u'm'), (0x2170, 'M', u'i'), (0x2171, 'M', u'ii'), (0x2172, 'M', u'iii'), (0x2173, 'M', u'iv'), (0x2174, 'M', u'v'), (0x2175, 'M', u'vi'), (0x2176, 'M', u'vii'), (0x2177, 'M', u'viii'), (0x2178, 'M', u'ix'), (0x2179, 'M', u'x'), (0x217A, 'M', u'xi'), (0x217B, 'M', u'xii'), (0x217C, 'M', u'l'), (0x217D, 'M', u'c'), (0x217E, 'M', u'd'), (0x217F, 'M', u'm'), (0x2180, 'V'), (0x2183, 'X'), (0x2184, 'V'), (0x2189, 'M', u'0⁄3'), (0x218A, 'V'), (0x218C, 'X'), (0x2190, 'V'), (0x222C, 'M', u'∫∫'), (0x222D, 'M', u'∫∫∫'), (0x222E, 'V'), (0x222F, 'M', u'∮∮'), (0x2230, 'M', u'∮∮∮'), (0x2231, 'V'), (0x2260, '3'), (0x2261, 'V'), (0x226E, '3'), (0x2270, 'V'), (0x2329, 'M', u'〈'), (0x232A, 'M', u'〉'), (0x232B, 'V'), (0x2427, 'X'), (0x2440, 'V'), (0x244B, 'X'), (0x2460, 'M', u'1'), (0x2461, 'M', u'2'), ] def _seg_23(): return [ (0x2462, 'M', u'3'), (0x2463, 'M', u'4'), (0x2464, 'M', u'5'), (0x2465, 'M', u'6'), (0x2466, 'M', u'7'), (0x2467, 'M', u'8'), (0x2468, 'M', u'9'), (0x2469, 'M', u'10'), (0x246A, 'M', u'11'), (0x246B, 'M', u'12'), (0x246C, 'M', u'13'), (0x246D, 'M', u'14'), (0x246E, 'M', u'15'), (0x246F, 'M', u'16'), (0x2470, 'M', u'17'), (0x2471, 'M', u'18'), (0x2472, 'M', u'19'), (0x2473, 'M', u'20'), (0x2474, '3', u'(1)'), (0x2475, '3', u'(2)'), (0x2476, '3', u'(3)'), (0x2477, '3', u'(4)'), (0x2478, '3', u'(5)'), (0x2479, '3', u'(6)'), (0x247A, '3', u'(7)'), (0x247B, '3', u'(8)'), (0x247C, '3', u'(9)'), (0x247D, '3', u'(10)'), (0x247E, '3', u'(11)'), (0x247F, '3', u'(12)'), (0x2480, '3', u'(13)'), (0x2481, '3', u'(14)'), (0x2482, '3', u'(15)'), (0x2483, '3', u'(16)'), (0x2484, '3', u'(17)'), (0x2485, '3', u'(18)'), (0x2486, '3', u'(19)'), (0x2487, '3', u'(20)'), (0x2488, 'X'), (0x249C, '3', u'(a)'), (0x249D, '3', u'(b)'), (0x249E, '3', u'(c)'), (0x249F, '3', u'(d)'), (0x24A0, '3', u'(e)'), (0x24A1, '3', u'(f)'), (0x24A2, '3', u'(g)'), (0x24A3, '3', u'(h)'), (0x24A4, '3', u'(i)'), (0x24A5, '3', u'(j)'), (0x24A6, '3', u'(k)'), (0x24A7, '3', u'(l)'), (0x24A8, '3', u'(m)'), (0x24A9, '3', u'(n)'), (0x24AA, '3', u'(o)'), (0x24AB, '3', u'(p)'), (0x24AC, '3', u'(q)'), (0x24AD, '3', u'(r)'), (0x24AE, '3', u'(s)'), (0x24AF, '3', u'(t)'), (0x24B0, '3', u'(u)'), (0x24B1, '3', u'(v)'), (0x24B2, '3', u'(w)'), (0x24B3, '3', u'(x)'), (0x24B4, '3', u'(y)'), (0x24B5, '3', u'(z)'), (0x24B6, 'M', u'a'), (0x24B7, 'M', u'b'), (0x24B8, 'M', u'c'), (0x24B9, 'M', u'd'), (0x24BA, 'M', u'e'), (0x24BB, 'M', u'f'), (0x24BC, 'M', u'g'), (0x24BD, 'M', u'h'), (0x24BE, 'M', u'i'), (0x24BF, 'M', u'j'), (0x24C0, 'M', u'k'), (0x24C1, 'M', u'l'), (0x24C2, 'M', u'm'), (0x24C3, 'M', u'n'), (0x24C4, 'M', u'o'), (0x24C5, 'M', u'p'), (0x24C6, 'M', u'q'), (0x24C7, 'M', u'r'), (0x24C8, 'M', u's'), (0x24C9, 'M', u't'), (0x24CA, 'M', u'u'), (0x24CB, 'M', u'v'), (0x24CC, 'M', u'w'), (0x24CD, 'M', u'x'), (0x24CE, 'M', u'y'), (0x24CF, 'M', u'z'), (0x24D0, 'M', u'a'), (0x24D1, 'M', u'b'), (0x24D2, 'M', u'c'), (0x24D3, 'M', u'd'), (0x24D4, 'M', u'e'), (0x24D5, 'M', u'f'), (0x24D6, 'M', u'g'), (0x24D7, 'M', u'h'), (0x24D8, 'M', u'i'), ] def _seg_24(): return [ (0x24D9, 'M', u'j'), (0x24DA, 'M', u'k'), (0x24DB, 'M', u'l'), (0x24DC, 'M', u'm'), (0x24DD, 'M', u'n'), (0x24DE, 'M', u'o'), (0x24DF, 'M', u'p'), (0x24E0, 'M', u'q'), (0x24E1, 'M', u'r'), (0x24E2, 'M', u's'), (0x24E3, 'M', u't'), (0x24E4, 'M', u'u'), (0x24E5, 'M', u'v'), (0x24E6, 'M', u'w'), (0x24E7, 'M', u'x'), (0x24E8, 'M', u'y'), (0x24E9, 'M', u'z'), (0x24EA, 'M', u'0'), (0x24EB, 'V'), (0x2A0C, 'M', u'∫∫∫∫'), (0x2A0D, 'V'), (0x2A74, '3', u'::='), (0x2A75, '3', u'=='), (0x2A76, '3', u'==='), (0x2A77, 'V'), (0x2ADC, 'M', u'⫝̸'), (0x2ADD, 'V'), (0x2B74, 'X'), (0x2B76, 'V'), (0x2B96, 'X'), (0x2B98, 'V'), (0x2BC9, 'X'), (0x2BCA, 'V'), (0x2BFF, 'X'), (0x2C00, 'M', u'ⰰ'), (0x2C01, 'M', u'ⰱ'), (0x2C02, 'M', u'ⰲ'), (0x2C03, 'M', u'ⰳ'), (0x2C04, 'M', u'ⰴ'), (0x2C05, 'M', u'ⰵ'), (0x2C06, 'M', u'ⰶ'), (0x2C07, 'M', u'ⰷ'), (0x2C08, 'M', u'ⰸ'), (0x2C09, 'M', u'ⰹ'), (0x2C0A, 'M', u'ⰺ'), (0x2C0B, 'M', u'ⰻ'), (0x2C0C, 'M', u'ⰼ'), (0x2C0D, 'M', u'ⰽ'), (0x2C0E, 'M', u'ⰾ'), (0x2C0F, 'M', u'ⰿ'), (0x2C10, 'M', u'ⱀ'), (0x2C11, 'M', u'ⱁ'), (0x2C12, 'M', u'ⱂ'), (0x2C13, 'M', u'ⱃ'), (0x2C14, 'M', u'ⱄ'), (0x2C15, 'M', u'ⱅ'), (0x2C16, 'M', u'ⱆ'), (0x2C17, 'M', u'ⱇ'), (0x2C18, 'M', u'ⱈ'), (0x2C19, 'M', u'ⱉ'), (0x2C1A, 'M', u'ⱊ'), (0x2C1B, 'M', u'ⱋ'), (0x2C1C, 'M', u'ⱌ'), (0x2C1D, 'M', u'ⱍ'), (0x2C1E, 'M', u'ⱎ'), (0x2C1F, 'M', u'ⱏ'), (0x2C20, 'M', u'ⱐ'), (0x2C21, 'M', u'ⱑ'), (0x2C22, 'M', u'ⱒ'), (0x2C23, 'M', u'ⱓ'), (0x2C24, 'M', u'ⱔ'), (0x2C25, 'M', u'ⱕ'), (0x2C26, 'M', u'ⱖ'), (0x2C27, 'M', u'ⱗ'), (0x2C28, 'M', u'ⱘ'), (0x2C29, 'M', u'ⱙ'), (0x2C2A, 'M', u'ⱚ'), (0x2C2B, 'M', u'ⱛ'), (0x2C2C, 'M', u'ⱜ'), (0x2C2D, 'M', u'ⱝ'), (0x2C2E, 'M', u'ⱞ'), (0x2C2F, 'X'), (0x2C30, 'V'), (0x2C5F, 'X'), (0x2C60, 'M', u'ⱡ'), (0x2C61, 'V'), (0x2C62, 'M', u'ɫ'), (0x2C63, 'M', u'ᵽ'), (0x2C64, 'M', u'ɽ'), (0x2C65, 'V'), (0x2C67, 'M', u'ⱨ'), (0x2C68, 'V'), (0x2C69, 'M', u'ⱪ'), (0x2C6A, 'V'), (0x2C6B, 'M', u'ⱬ'), (0x2C6C, 'V'), (0x2C6D, 'M', u'ɑ'), (0x2C6E, 'M', u'ɱ'), (0x2C6F, 'M', u'ɐ'), (0x2C70, 'M', u'ɒ'), ] def _seg_25(): return [ (0x2C71, 'V'), (0x2C72, 'M', u'ⱳ'), (0x2C73, 'V'), (0x2C75, 'M', u'ⱶ'), (0x2C76, 'V'), (0x2C7C, 'M', u'j'), (0x2C7D, 'M', u'v'), (0x2C7E, 'M', u'ȿ'), (0x2C7F, 'M', u'ɀ'), (0x2C80, 'M', u'ⲁ'), (0x2C81, 'V'), (0x2C82, 'M', u'ⲃ'), (0x2C83, 'V'), (0x2C84, 'M', u'ⲅ'), (0x2C85, 'V'), (0x2C86, 'M', u'ⲇ'), (0x2C87, 'V'), (0x2C88, 'M', u'ⲉ'), (0x2C89, 'V'), (0x2C8A, 'M', u'ⲋ'), (0x2C8B, 'V'), (0x2C8C, 'M', u'ⲍ'), (0x2C8D, 'V'), (0x2C8E, 'M', u'ⲏ'), (0x2C8F, 'V'), (0x2C90, 'M', u'ⲑ'), (0x2C91, 'V'), (0x2C92, 'M', u'ⲓ'), (0x2C93, 'V'), (0x2C94, 'M', u'ⲕ'), (0x2C95, 'V'), (0x2C96, 'M', u'ⲗ'), (0x2C97, 'V'), (0x2C98, 'M', u'ⲙ'), (0x2C99, 'V'), (0x2C9A, 'M', u'ⲛ'), (0x2C9B, 'V'), (0x2C9C, 'M', u'ⲝ'), (0x2C9D, 'V'), (0x2C9E, 'M', u'ⲟ'), (0x2C9F, 'V'), (0x2CA0, 'M', u'ⲡ'), (0x2CA1, 'V'), (0x2CA2, 'M', u'ⲣ'), (0x2CA3, 'V'), (0x2CA4, 'M', u'ⲥ'), (0x2CA5, 'V'), (0x2CA6, 'M', u'ⲧ'), (0x2CA7, 'V'), (0x2CA8, 'M', u'ⲩ'), (0x2CA9, 'V'), (0x2CAA, 'M', u'ⲫ'), (0x2CAB, 'V'), (0x2CAC, 'M', u'ⲭ'), (0x2CAD, 'V'), (0x2CAE, 'M', u'ⲯ'), (0x2CAF, 'V'), (0x2CB0, 'M', u'ⲱ'), (0x2CB1, 'V'), (0x2CB2, 'M', u'ⲳ'), (0x2CB3, 'V'), (0x2CB4, 'M', u'ⲵ'), (0x2CB5, 'V'), (0x2CB6, 'M', u'ⲷ'), (0x2CB7, 'V'), (0x2CB8, 'M', u'ⲹ'), (0x2CB9, 'V'), (0x2CBA, 'M', u'ⲻ'), (0x2CBB, 'V'), (0x2CBC, 'M', u'ⲽ'), (0x2CBD, 'V'), (0x2CBE, 'M', u'ⲿ'), (0x2CBF, 'V'), (0x2CC0, 'M', u'ⳁ'), (0x2CC1, 'V'), (0x2CC2, 'M', u'ⳃ'), (0x2CC3, 'V'), (0x2CC4, 'M', u'ⳅ'), (0x2CC5, 'V'), (0x2CC6, 'M', u'ⳇ'), (0x2CC7, 'V'), (0x2CC8, 'M', u'ⳉ'), (0x2CC9, 'V'), (0x2CCA, 'M', u'ⳋ'), (0x2CCB, 'V'), (0x2CCC, 'M', u'ⳍ'), (0x2CCD, 'V'), (0x2CCE, 'M', u'ⳏ'), (0x2CCF, 'V'), (0x2CD0, 'M', u'ⳑ'), (0x2CD1, 'V'), (0x2CD2, 'M', u'ⳓ'), (0x2CD3, 'V'), (0x2CD4, 'M', u'ⳕ'), (0x2CD5, 'V'), (0x2CD6, 'M', u'ⳗ'), (0x2CD7, 'V'), (0x2CD8, 'M', u'ⳙ'), (0x2CD9, 'V'), (0x2CDA, 'M', u'ⳛ'), ] def _seg_26(): return [ (0x2CDB, 'V'), (0x2CDC, 'M', u'ⳝ'), (0x2CDD, 'V'), (0x2CDE, 'M', u'ⳟ'), (0x2CDF, 'V'), (0x2CE0, 'M', u'ⳡ'), (0x2CE1, 'V'), (0x2CE2, 'M', u'ⳣ'), (0x2CE3, 'V'), (0x2CEB, 'M', u'ⳬ'), (0x2CEC, 'V'), (0x2CED, 'M', u'ⳮ'), (0x2CEE, 'V'), (0x2CF2, 'M', u'ⳳ'), (0x2CF3, 'V'), (0x2CF4, 'X'), (0x2CF9, 'V'), (0x2D26, 'X'), (0x2D27, 'V'), (0x2D28, 'X'), (0x2D2D, 'V'), (0x2D2E, 'X'), (0x2D30, 'V'), (0x2D68, 'X'), (0x2D6F, 'M', u'ⵡ'), (0x2D70, 'V'), (0x2D71, 'X'), (0x2D7F, 'V'), (0x2D97, 'X'), (0x2DA0, 'V'), (0x2DA7, 'X'), (0x2DA8, 'V'), (0x2DAF, 'X'), (0x2DB0, 'V'), (0x2DB7, 'X'), (0x2DB8, 'V'), (0x2DBF, 'X'), (0x2DC0, 'V'), (0x2DC7, 'X'), (0x2DC8, 'V'), (0x2DCF, 'X'), (0x2DD0, 'V'), (0x2DD7, 'X'), (0x2DD8, 'V'), (0x2DDF, 'X'), (0x2DE0, 'V'), (0x2E4F, 'X'), (0x2E80, 'V'), (0x2E9A, 'X'), (0x2E9B, 'V'), (0x2E9F, 'M', u'母'), (0x2EA0, 'V'), (0x2EF3, 'M', u'龟'), (0x2EF4, 'X'), (0x2F00, 'M', u'一'), (0x2F01, 'M', u'丨'), (0x2F02, 'M', u'丶'), (0x2F03, 'M', u'丿'), (0x2F04, 'M', u'乙'), (0x2F05, 'M', u'亅'), (0x2F06, 'M', u'二'), (0x2F07, 'M', u'亠'), (0x2F08, 'M', u'人'), (0x2F09, 'M', u'儿'), (0x2F0A, 'M', u'入'), (0x2F0B, 'M', u'八'), (0x2F0C, 'M', u'冂'), (0x2F0D, 'M', u'冖'), (0x2F0E, 'M', u'冫'), (0x2F0F, 'M', u'几'), (0x2F10, 'M', u'凵'), (0x2F11, 'M', u'刀'), (0x2F12, 'M', u'力'), (0x2F13, 'M', u'勹'), (0x2F14, 'M', u'匕'), (0x2F15, 'M', u'匚'), (0x2F16, 'M', u'匸'), (0x2F17, 'M', u'十'), (0x2F18, 'M', u'卜'), (0x2F19, 'M', u'卩'), (0x2F1A, 'M', u'厂'), (0x2F1B, 'M', u'厶'), (0x2F1C, 'M', u'又'), (0x2F1D, 'M', u'口'), (0x2F1E, 'M', u'囗'), (0x2F1F, 'M', u'土'), (0x2F20, 'M', u'士'), (0x2F21, 'M', u'夂'), (0x2F22, 'M', u'夊'), (0x2F23, 'M', u'夕'), (0x2F24, 'M', u'大'), (0x2F25, 'M', u'女'), (0x2F26, 'M', u'子'), (0x2F27, 'M', u'宀'), (0x2F28, 'M', u'寸'), (0x2F29, 'M', u'小'), (0x2F2A, 'M', u'尢'), (0x2F2B, 'M', u'尸'), (0x2F2C, 'M', u'屮'), (0x2F2D, 'M', u'山'), ] def _seg_27(): return [ (0x2F2E, 'M', u'巛'), (0x2F2F, 'M', u'工'), (0x2F30, 'M', u'己'), (0x2F31, 'M', u'巾'), (0x2F32, 'M', u'干'), (0x2F33, 'M', u'幺'), (0x2F34, 'M', u'广'), (0x2F35, 'M', u'廴'), (0x2F36, 'M', u'廾'), (0x2F37, 'M', u'弋'), (0x2F38, 'M', u'弓'), (0x2F39, 'M', u'彐'), (0x2F3A, 'M', u'彡'), (0x2F3B, 'M', u'彳'), (0x2F3C, 'M', u'心'), (0x2F3D, 'M', u'戈'), (0x2F3E, 'M', u'戶'), (0x2F3F, 'M', u'手'), (0x2F40, 'M', u'支'), (0x2F41, 'M', u'攴'), (0x2F42, 'M', u'文'), (0x2F43, 'M', u'斗'), (0x2F44, 'M', u'斤'), (0x2F45, 'M', u'方'), (0x2F46, 'M', u'无'), (0x2F47, 'M', u'日'), (0x2F48, 'M', u'曰'), (0x2F49, 'M', u'月'), (0x2F4A, 'M', u'木'), (0x2F4B, 'M', u'欠'), (0x2F4C, 'M', u'止'), (0x2F4D, 'M', u'歹'), (0x2F4E, 'M', u'殳'), (0x2F4F, 'M', u'毋'), (0x2F50, 'M', u'比'), (0x2F51, 'M', u'毛'), (0x2F52, 'M', u'氏'), (0x2F53, 'M', u'气'), (0x2F54, 'M', u'水'), (0x2F55, 'M', u'火'), (0x2F56, 'M', u'爪'), (0x2F57, 'M', u'父'), (0x2F58, 'M', u'爻'), (0x2F59, 'M', u'爿'), (0x2F5A, 'M', u'片'), (0x2F5B, 'M', u'牙'), (0x2F5C, 'M', u'牛'), (0x2F5D, 'M', u'犬'), (0x2F5E, 'M', u'玄'), (0x2F5F, 'M', u'玉'), (0x2F60, 'M', u'瓜'), (0x2F61, 'M', u'瓦'), (0x2F62, 'M', u'甘'), (0x2F63, 'M', u'生'), (0x2F64, 'M', u'用'), (0x2F65, 'M', u'田'), (0x2F66, 'M', u'疋'), (0x2F67, 'M', u'疒'), (0x2F68, 'M', u'癶'), (0x2F69, 'M', u'白'), (0x2F6A, 'M', u'皮'), (0x2F6B, 'M', u'皿'), (0x2F6C, 'M', u'目'), (0x2F6D, 'M', u'矛'), (0x2F6E, 'M', u'矢'), (0x2F6F, 'M', u'石'), (0x2F70, 'M', u'示'), (0x2F71, 'M', u'禸'), (0x2F72, 'M', u'禾'), (0x2F73, 'M', u'穴'), (0x2F74, 'M', u'立'), (0x2F75, 'M', u'竹'), (0x2F76, 'M', u'米'), (0x2F77, 'M', u'糸'), (0x2F78, 'M', u'缶'), (0x2F79, 'M', u'网'), (0x2F7A, 'M', u'羊'), (0x2F7B, 'M', u'羽'), (0x2F7C, 'M', u'老'), (0x2F7D, 'M', u'而'), (0x2F7E, 'M', u'耒'), (0x2F7F, 'M', u'耳'), (0x2F80, 'M', u'聿'), (0x2F81, 'M', u'肉'), (0x2F82, 'M', u'臣'), (0x2F83, 'M', u'自'), (0x2F84, 'M', u'至'), (0x2F85, 'M', u'臼'), (0x2F86, 'M', u'舌'), (0x2F87, 'M', u'舛'), (0x2F88, 'M', u'舟'), (0x2F89, 'M', u'艮'), (0x2F8A, 'M', u'色'), (0x2F8B, 'M', u'艸'), (0x2F8C, 'M', u'虍'), (0x2F8D, 'M', u'虫'), (0x2F8E, 'M', u'血'), (0x2F8F, 'M', u'行'), (0x2F90, 'M', u'衣'), (0x2F91, 'M', u'襾'), ] def _seg_28(): return [ (0x2F92, 'M', u'見'), (0x2F93, 'M', u'角'), (0x2F94, 'M', u'言'), (0x2F95, 'M', u'谷'), (0x2F96, 'M', u'豆'), (0x2F97, 'M', u'豕'), (0x2F98, 'M', u'豸'), (0x2F99, 'M', u'貝'), (0x2F9A, 'M', u'赤'), (0x2F9B, 'M', u'走'), (0x2F9C, 'M', u'足'), (0x2F9D, 'M', u'身'), (0x2F9E, 'M', u'車'), (0x2F9F, 'M', u'辛'), (0x2FA0, 'M', u'辰'), (0x2FA1, 'M', u'辵'), (0x2FA2, 'M', u'邑'), (0x2FA3, 'M', u'酉'), (0x2FA4, 'M', u'釆'), (0x2FA5, 'M', u'里'), (0x2FA6, 'M', u'金'), (0x2FA7, 'M', u'長'), (0x2FA8, 'M', u'門'), (0x2FA9, 'M', u'阜'), (0x2FAA, 'M', u'隶'), (0x2FAB, 'M', u'隹'), (0x2FAC, 'M', u'雨'), (0x2FAD, 'M', u'靑'), (0x2FAE, 'M', u'非'), (0x2FAF, 'M', u'面'), (0x2FB0, 'M', u'革'), (0x2FB1, 'M', u'韋'), (0x2FB2, 'M', u'韭'), (0x2FB3, 'M', u'音'), (0x2FB4, 'M', u'頁'), (0x2FB5, 'M', u'風'), (0x2FB6, 'M', u'飛'), (0x2FB7, 'M', u'食'), (0x2FB8, 'M', u'首'), (0x2FB9, 'M', u'香'), (0x2FBA, 'M', u'馬'), (0x2FBB, 'M', u'骨'), (0x2FBC, 'M', u'高'), (0x2FBD, 'M', u'髟'), (0x2FBE, 'M', u'鬥'), (0x2FBF, 'M', u'鬯'), (0x2FC0, 'M', u'鬲'), (0x2FC1, 'M', u'鬼'), (0x2FC2, 'M', u'魚'), (0x2FC3, 'M', u'鳥'), (0x2FC4, 'M', u'鹵'), (0x2FC5, 'M', u'鹿'), (0x2FC6, 'M', u'麥'), (0x2FC7, 'M', u'麻'), (0x2FC8, 'M', u'黃'), (0x2FC9, 'M', u'黍'), (0x2FCA, 'M', u'黑'), (0x2FCB, 'M', u'黹'), (0x2FCC, 'M', u'黽'), (0x2FCD, 'M', u'鼎'), (0x2FCE, 'M', u'鼓'), (0x2FCF, 'M', u'鼠'), (0x2FD0, 'M', u'鼻'), (0x2FD1, 'M', u'齊'), (0x2FD2, 'M', u'齒'), (0x2FD3, 'M', u'龍'), (0x2FD4, 'M', u'龜'), (0x2FD5, 'M', u'龠'), (0x2FD6, 'X'), (0x3000, '3', u' '), (0x3001, 'V'), (0x3002, 'M', u'.'), (0x3003, 'V'), (0x3036, 'M', u'〒'), (0x3037, 'V'), (0x3038, 'M', u'十'), (0x3039, 'M', u'卄'), (0x303A, 'M', u'卅'), (0x303B, 'V'), (0x3040, 'X'), (0x3041, 'V'), (0x3097, 'X'), (0x3099, 'V'), (0x309B, '3', u' ゙'), (0x309C, '3', u' ゚'), (0x309D, 'V'), (0x309F, 'M', u'より'), (0x30A0, 'V'), (0x30FF, 'M', u'コト'), (0x3100, 'X'), (0x3105, 'V'), (0x3130, 'X'), (0x3131, 'M', u'ᄀ'), (0x3132, 'M', u'ᄁ'), (0x3133, 'M', u'ᆪ'), (0x3134, 'M', u'ᄂ'), (0x3135, 'M', u'ᆬ'), (0x3136, 'M', u'ᆭ'), (0x3137, 'M', u'ᄃ'), (0x3138, 'M', u'ᄄ'), ] def _seg_29(): return [ (0x3139, 'M', u'ᄅ'), (0x313A, 'M', u'ᆰ'), (0x313B, 'M', u'ᆱ'), (0x313C, 'M', u'ᆲ'), (0x313D, 'M', u'ᆳ'), (0x313E, 'M', u'ᆴ'), (0x313F, 'M', u'ᆵ'), (0x3140, 'M', u'ᄚ'), (0x3141, 'M', u'ᄆ'), (0x3142, 'M', u'ᄇ'), (0x3143, 'M', u'ᄈ'), (0x3144, 'M', u'ᄡ'), (0x3145, 'M', u'ᄉ'), (0x3146, 'M', u'ᄊ'), (0x3147, 'M', u'ᄋ'), (0x3148, 'M', u'ᄌ'), (0x3149, 'M', u'ᄍ'), (0x314A, 'M', u'ᄎ'), (0x314B, 'M', u'ᄏ'), (0x314C, 'M', u'ᄐ'), (0x314D, 'M', u'ᄑ'), (0x314E, 'M', u'ᄒ'), (0x314F, 'M', u'ᅡ'), (0x3150, 'M', u'ᅢ'), (0x3151, 'M', u'ᅣ'), (0x3152, 'M', u'ᅤ'), (0x3153, 'M', u'ᅥ'), (0x3154, 'M', u'ᅦ'), (0x3155, 'M', u'ᅧ'), (0x3156, 'M', u'ᅨ'), (0x3157, 'M', u'ᅩ'), (0x3158, 'M', u'ᅪ'), (0x3159, 'M', u'ᅫ'), (0x315A, 'M', u'ᅬ'), (0x315B, 'M', u'ᅭ'), (0x315C, 'M', u'ᅮ'), (0x315D, 'M', u'ᅯ'), (0x315E, 'M', u'ᅰ'), (0x315F, 'M', u'ᅱ'), (0x3160, 'M', u'ᅲ'), (0x3161, 'M', u'ᅳ'), (0x3162, 'M', u'ᅴ'), (0x3163, 'M', u'ᅵ'), (0x3164, 'X'), (0x3165, 'M', u'ᄔ'), (0x3166, 'M', u'ᄕ'), (0x3167, 'M', u'ᇇ'), (0x3168, 'M', u'ᇈ'), (0x3169, 'M', u'ᇌ'), (0x316A, 'M', u'ᇎ'), (0x316B, 'M', u'ᇓ'), (0x316C, 'M', u'ᇗ'), (0x316D, 'M', u'ᇙ'), (0x316E, 'M', u'ᄜ'), (0x316F, 'M', u'ᇝ'), (0x3170, 'M', u'ᇟ'), (0x3171, 'M', u'ᄝ'), (0x3172, 'M', u'ᄞ'), (0x3173, 'M', u'ᄠ'), (0x3174, 'M', u'ᄢ'), (0x3175, 'M', u'ᄣ'), (0x3176, 'M', u'ᄧ'), (0x3177, 'M', u'ᄩ'), (0x3178, 'M', u'ᄫ'), (0x3179, 'M', u'ᄬ'), (0x317A, 'M', u'ᄭ'), (0x317B, 'M', u'ᄮ'), (0x317C, 'M', u'ᄯ'), (0x317D, 'M', u'ᄲ'), (0x317E, 'M', u'ᄶ'), (0x317F, 'M', u'ᅀ'), (0x3180, 'M', u'ᅇ'), (0x3181, 'M', u'ᅌ'), (0x3182, 'M', u'ᇱ'), (0x3183, 'M', u'ᇲ'), (0x3184, 'M', u'ᅗ'), (0x3185, 'M', u'ᅘ'), (0x3186, 'M', u'ᅙ'), (0x3187, 'M', u'ᆄ'), (0x3188, 'M', u'ᆅ'), (0x3189, 'M', u'ᆈ'), (0x318A, 'M', u'ᆑ'), (0x318B, 'M', u'ᆒ'), (0x318C, 'M', u'ᆔ'), (0x318D, 'M', u'ᆞ'), (0x318E, 'M', u'ᆡ'), (0x318F, 'X'), (0x3190, 'V'), (0x3192, 'M', u'一'), (0x3193, 'M', u'二'), (0x3194, 'M', u'三'), (0x3195, 'M', u'四'), (0x3196, 'M', u'上'), (0x3197, 'M', u'中'), (0x3198, 'M', u'下'), (0x3199, 'M', u'甲'), (0x319A, 'M', u'乙'), (0x319B, 'M', u'丙'), (0x319C, 'M', u'丁'), (0x319D, 'M', u'天'), ] def _seg_30(): return [ (0x319E, 'M', u'地'), (0x319F, 'M', u'人'), (0x31A0, 'V'), (0x31BB, 'X'), (0x31C0, 'V'), (0x31E4, 'X'), (0x31F0, 'V'), (0x3200, '3', u'(ᄀ)'), (0x3201, '3', u'(ᄂ)'), (0x3202, '3', u'(ᄃ)'), (0x3203, '3', u'(ᄅ)'), (0x3204, '3', u'(ᄆ)'), (0x3205, '3', u'(ᄇ)'), (0x3206, '3', u'(ᄉ)'), (0x3207, '3', u'(ᄋ)'), (0x3208, '3', u'(ᄌ)'), (0x3209, '3', u'(ᄎ)'), (0x320A, '3', u'(ᄏ)'), (0x320B, '3', u'(ᄐ)'), (0x320C, '3', u'(ᄑ)'), (0x320D, '3', u'(ᄒ)'), (0x320E, '3', u'(가)'), (0x320F, '3', u'(나)'), (0x3210, '3', u'(다)'), (0x3211, '3', u'(라)'), (0x3212, '3', u'(마)'), (0x3213, '3', u'(바)'), (0x3214, '3', u'(사)'), (0x3215, '3', u'(아)'), (0x3216, '3', u'(자)'), (0x3217, '3', u'(차)'), (0x3218, '3', u'(카)'), (0x3219, '3', u'(타)'), (0x321A, '3', u'(파)'), (0x321B, '3', u'(하)'), (0x321C, '3', u'(주)'), (0x321D, '3', u'(오전)'), (0x321E, '3', u'(오후)'), (0x321F, 'X'), (0x3220, '3', u'(一)'), (0x3221, '3', u'(二)'), (0x3222, '3', u'(三)'), (0x3223, '3', u'(四)'), (0x3224, '3', u'(五)'), (0x3225, '3', u'(六)'), (0x3226, '3', u'(七)'), (0x3227, '3', u'(八)'), (0x3228, '3', u'(九)'), (0x3229, '3', u'(十)'), (0x322A, '3', u'(月)'), (0x322B, '3', u'(火)'), (0x322C, '3', u'(水)'), (0x322D, '3', u'(木)'), (0x322E, '3', u'(金)'), (0x322F, '3', u'(土)'), (0x3230, '3', u'(日)'), (0x3231, '3', u'(株)'), (0x3232, '3', u'(有)'), (0x3233, '3', u'(社)'), (0x3234, '3', u'(名)'), (0x3235, '3', u'(特)'), (0x3236, '3', u'(財)'), (0x3237, '3', u'(祝)'), (0x3238, '3', u'(労)'), (0x3239, '3', u'(代)'), (0x323A, '3', u'(呼)'), (0x323B, '3', u'(学)'), (0x323C, '3', u'(監)'), (0x323D, '3', u'(企)'), (0x323E, '3', u'(資)'), (0x323F, '3', u'(協)'), (0x3240, '3', u'(祭)'), (0x3241, '3', u'(休)'), (0x3242, '3', u'(自)'), (0x3243, '3', u'(至)'), (0x3244, 'M', u'問'), (0x3245, 'M', u'幼'), (0x3246, 'M', u'文'), (0x3247, 'M', u'箏'), (0x3248, 'V'), (0x3250, 'M', u'pte'), (0x3251, 'M', u'21'), (0x3252, 'M', u'22'), (0x3253, 'M', u'23'), (0x3254, 'M', u'24'), (0x3255, 'M', u'25'), (0x3256, 'M', u'26'), (0x3257, 'M', u'27'), (0x3258, 'M', u'28'), (0x3259, 'M', u'29'), (0x325A, 'M', u'30'), (0x325B, 'M', u'31'), (0x325C, 'M', u'32'), (0x325D, 'M', u'33'), (0x325E, 'M', u'34'), (0x325F, 'M', u'35'), (0x3260, 'M', u'ᄀ'), (0x3261, 'M', u'ᄂ'), (0x3262, 'M', u'ᄃ'), (0x3263, 'M', u'ᄅ'), ] def _seg_31(): return [ (0x3264, 'M', u'ᄆ'), (0x3265, 'M', u'ᄇ'), (0x3266, 'M', u'ᄉ'), (0x3267, 'M', u'ᄋ'), (0x3268, 'M', u'ᄌ'), (0x3269, 'M', u'ᄎ'), (0x326A, 'M', u'ᄏ'), (0x326B, 'M', u'ᄐ'), (0x326C, 'M', u'ᄑ'), (0x326D, 'M', u'ᄒ'), (0x326E, 'M', u'가'), (0x326F, 'M', u'나'), (0x3270, 'M', u'다'), (0x3271, 'M', u'라'), (0x3272, 'M', u'마'), (0x3273, 'M', u'바'), (0x3274, 'M', u'사'), (0x3275, 'M', u'아'), (0x3276, 'M', u'자'), (0x3277, 'M', u'차'), (0x3278, 'M', u'카'), (0x3279, 'M', u'타'), (0x327A, 'M', u'파'), (0x327B, 'M', u'하'), (0x327C, 'M', u'참고'), (0x327D, 'M', u'주의'), (0x327E, 'M', u'우'), (0x327F, 'V'), (0x3280, 'M', u'一'), (0x3281, 'M', u'二'), (0x3282, 'M', u'三'), (0x3283, 'M', u'四'), (0x3284, 'M', u'五'), (0x3285, 'M', u'六'), (0x3286, 'M', u'七'), (0x3287, 'M', u'八'), (0x3288, 'M', u'九'), (0x3289, 'M', u'十'), (0x328A, 'M', u'月'), (0x328B, 'M', u'火'), (0x328C, 'M', u'水'), (0x328D, 'M', u'木'), (0x328E, 'M', u'金'), (0x328F, 'M', u'土'), (0x3290, 'M', u'日'), (0x3291, 'M', u'株'), (0x3292, 'M', u'有'), (0x3293, 'M', u'社'), (0x3294, 'M', u'名'), (0x3295, 'M', u'特'), (0x3296, 'M', u'財'), (0x3297, 'M', u'祝'), (0x3298, 'M', u'労'), (0x3299, 'M', u'秘'), (0x329A, 'M', u'男'), (0x329B, 'M', u'女'), (0x329C, 'M', u'適'), (0x329D, 'M', u'優'), (0x329E, 'M', u'印'), (0x329F, 'M', u'注'), (0x32A0, 'M', u'項'), (0x32A1, 'M', u'休'), (0x32A2, 'M', u'写'), (0x32A3, 'M', u'正'), (0x32A4, 'M', u'上'), (0x32A5, 'M', u'中'), (0x32A6, 'M', u'下'), (0x32A7, 'M', u'左'), (0x32A8, 'M', u'右'), (0x32A9, 'M', u'医'), (0x32AA, 'M', u'宗'), (0x32AB, 'M', u'学'), (0x32AC, 'M', u'監'), (0x32AD, 'M', u'企'), (0x32AE, 'M', u'資'), (0x32AF, 'M', u'協'), (0x32B0, 'M', u'夜'), (0x32B1, 'M', u'36'), (0x32B2, 'M', u'37'), (0x32B3, 'M', u'38'), (0x32B4, 'M', u'39'), (0x32B5, 'M', u'40'), (0x32B6, 'M', u'41'), (0x32B7, 'M', u'42'), (0x32B8, 'M', u'43'), (0x32B9, 'M', u'44'), (0x32BA, 'M', u'45'), (0x32BB, 'M', u'46'), (0x32BC, 'M', u'47'), (0x32BD, 'M', u'48'), (0x32BE, 'M', u'49'), (0x32BF, 'M', u'50'), (0x32C0, 'M', u'1月'), (0x32C1, 'M', u'2月'), (0x32C2, 'M', u'3月'), (0x32C3, 'M', u'4月'), (0x32C4, 'M', u'5月'), (0x32C5, 'M', u'6月'), (0x32C6, 'M', u'7月'), (0x32C7, 'M', u'8月'), ] def _seg_32(): return [ (0x32C8, 'M', u'9月'), (0x32C9, 'M', u'10月'), (0x32CA, 'M', u'11月'), (0x32CB, 'M', u'12月'), (0x32CC, 'M', u'hg'), (0x32CD, 'M', u'erg'), (0x32CE, 'M', u'ev'), (0x32CF, 'M', u'ltd'), (0x32D0, 'M', u'ア'), (0x32D1, 'M', u'イ'), (0x32D2, 'M', u'ウ'), (0x32D3, 'M', u'エ'), (0x32D4, 'M', u'オ'), (0x32D5, 'M', u'カ'), (0x32D6, 'M', u'キ'), (0x32D7, 'M', u'ク'), (0x32D8, 'M', u'ケ'), (0x32D9, 'M', u'コ'), (0x32DA, 'M', u'サ'), (0x32DB, 'M', u'シ'), (0x32DC, 'M', u'ス'), (0x32DD, 'M', u'セ'), (0x32DE, 'M', u'ソ'), (0x32DF, 'M', u'タ'), (0x32E0, 'M', u'チ'), (0x32E1, 'M', u'ツ'), (0x32E2, 'M', u'テ'), (0x32E3, 'M', u'ト'), (0x32E4, 'M', u'ナ'), (0x32E5, 'M', u'ニ'), (0x32E6, 'M', u'ヌ'), (0x32E7, 'M', u'ネ'), (0x32E8, 'M', u'ノ'), (0x32E9, 'M', u'ハ'), (0x32EA, 'M', u'ヒ'), (0x32EB, 'M', u'フ'), (0x32EC, 'M', u'ヘ'), (0x32ED, 'M', u'ホ'), (0x32EE, 'M', u'マ'), (0x32EF, 'M', u'ミ'), (0x32F0, 'M', u'ム'), (0x32F1, 'M', u'メ'), (0x32F2, 'M', u'モ'), (0x32F3, 'M', u'ヤ'), (0x32F4, 'M', u'ユ'), (0x32F5, 'M', u'ヨ'), (0x32F6, 'M', u'ラ'), (0x32F7, 'M', u'リ'), (0x32F8, 'M', u'ル'), (0x32F9, 'M', u'レ'), (0x32FA, 'M', u'ロ'), (0x32FB, 'M', u'ワ'), (0x32FC, 'M', u'ヰ'), (0x32FD, 'M', u'ヱ'), (0x32FE, 'M', u'ヲ'), (0x32FF, 'X'), (0x3300, 'M', u'アパート'), (0x3301, 'M', u'アルファ'), (0x3302, 'M', u'アンペア'), (0x3303, 'M', u'アール'), (0x3304, 'M', u'イニング'), (0x3305, 'M', u'インチ'), (0x3306, 'M', u'ウォン'), (0x3307, 'M', u'エスクード'), (0x3308, 'M', u'エーカー'), (0x3309, 'M', u'オンス'), (0x330A, 'M', u'オーム'), (0x330B, 'M', u'カイリ'), (0x330C, 'M', u'カラット'), (0x330D, 'M', u'カロリー'), (0x330E, 'M', u'ガロン'), (0x330F, 'M', u'ガンマ'), (0x3310, 'M', u'ギガ'), (0x3311, 'M', u'ギニー'), (0x3312, 'M', u'キュリー'), (0x3313, 'M', u'ギルダー'), (0x3314, 'M', u'キロ'), (0x3315, 'M', u'キログラム'), (0x3316, 'M', u'キロメートル'), (0x3317, 'M', u'キロワット'), (0x3318, 'M', u'グラム'), (0x3319, 'M', u'グラムトン'), (0x331A, 'M', u'クルゼイロ'), (0x331B, 'M', u'クローネ'), (0x331C, 'M', u'ケース'), (0x331D, 'M', u'コルナ'), (0x331E, 'M', u'コーポ'), (0x331F, 'M', u'サイクル'), (0x3320, 'M', u'サンチーム'), (0x3321, 'M', u'シリング'), (0x3322, 'M', u'センチ'), (0x3323, 'M', u'セント'), (0x3324, 'M', u'ダース'), (0x3325, 'M', u'デシ'), (0x3326, 'M', u'ドル'), (0x3327, 'M', u'トン'), (0x3328, 'M', u'ナノ'), (0x3329, 'M', u'ノット'), (0x332A, 'M', u'ハイツ'), (0x332B, 'M', u'パーセント'), ] def _seg_33(): return [ (0x332C, 'M', u'パーツ'), (0x332D, 'M', u'バーレル'), (0x332E, 'M', u'ピアストル'), (0x332F, 'M', u'ピクル'), (0x3330, 'M', u'ピコ'), (0x3331, 'M', u'ビル'), (0x3332, 'M', u'ファラッド'), (0x3333, 'M', u'フィート'), (0x3334, 'M', u'ブッシェル'), (0x3335, 'M', u'フラン'), (0x3336, 'M', u'ヘクタール'), (0x3337, 'M', u'ペソ'), (0x3338, 'M', u'ペニヒ'), (0x3339, 'M', u'ヘルツ'), (0x333A, 'M', u'ペンス'), (0x333B, 'M', u'ページ'), (0x333C, 'M', u'ベータ'), (0x333D, 'M', u'ポイント'), (0x333E, 'M', u'ボルト'), (0x333F, 'M', u'ホン'), (0x3340, 'M', u'ポンド'), (0x3341, 'M', u'ホール'), (0x3342, 'M', u'ホーン'), (0x3343, 'M', u'マイクロ'), (0x3344, 'M', u'マイル'), (0x3345, 'M', u'マッハ'), (0x3346, 'M', u'マルク'), (0x3347, 'M', u'マンション'), (0x3348, 'M', u'ミクロン'), (0x3349, 'M', u'ミリ'), (0x334A, 'M', u'ミリバール'), (0x334B, 'M', u'メガ'), (0x334C, 'M', u'メガトン'), (0x334D, 'M', u'メートル'), (0x334E, 'M', u'ヤード'), (0x334F, 'M', u'ヤール'), (0x3350, 'M', u'ユアン'), (0x3351, 'M', u'リットル'), (0x3352, 'M', u'リラ'), (0x3353, 'M', u'ルピー'), (0x3354, 'M', u'ルーブル'), (0x3355, 'M', u'レム'), (0x3356, 'M', u'レントゲン'), (0x3357, 'M', u'ワット'), (0x3358, 'M', u'0点'), (0x3359, 'M', u'1点'), (0x335A, 'M', u'2点'), (0x335B, 'M', u'3点'), (0x335C, 'M', u'4点'), (0x335D, 'M', u'5点'), (0x335E, 'M', u'6点'), (0x335F, 'M', u'7点'), (0x3360, 'M', u'8点'), (0x3361, 'M', u'9点'), (0x3362, 'M', u'10点'), (0x3363, 'M', u'11点'), (0x3364, 'M', u'12点'), (0x3365, 'M', u'13点'), (0x3366, 'M', u'14点'), (0x3367, 'M', u'15点'), (0x3368, 'M', u'16点'), (0x3369, 'M', u'17点'), (0x336A, 'M', u'18点'), (0x336B, 'M', u'19点'), (0x336C, 'M', u'20点'), (0x336D, 'M', u'21点'), (0x336E, 'M', u'22点'), (0x336F, 'M', u'23点'), (0x3370, 'M', u'24点'), (0x3371, 'M', u'hpa'), (0x3372, 'M', u'da'), (0x3373, 'M', u'au'), (0x3374, 'M', u'bar'), (0x3375, 'M', u'ov'), (0x3376, 'M', u'pc'), (0x3377, 'M', u'dm'), (0x3378, 'M', u'dm2'), (0x3379, 'M', u'dm3'), (0x337A, 'M', u'iu'), (0x337B, 'M', u'平成'), (0x337C, 'M', u'昭和'), (0x337D, 'M', u'大正'), (0x337E, 'M', u'明治'), (0x337F, 'M', u'株式会社'), (0x3380, 'M', u'pa'), (0x3381, 'M', u'na'), (0x3382, 'M', u'μa'), (0x3383, 'M', u'ma'), (0x3384, 'M', u'ka'), (0x3385, 'M', u'kb'), (0x3386, 'M', u'mb'), (0x3387, 'M', u'gb'), (0x3388, 'M', u'cal'), (0x3389, 'M', u'kcal'), (0x338A, 'M', u'pf'), (0x338B, 'M', u'nf'), (0x338C, 'M', u'μf'), (0x338D, 'M', u'μg'), (0x338E, 'M', u'mg'), (0x338F, 'M', u'kg'), ] def _seg_34(): return [ (0x3390, 'M', u'hz'), (0x3391, 'M', u'khz'), (0x3392, 'M', u'mhz'), (0x3393, 'M', u'ghz'), (0x3394, 'M', u'thz'), (0x3395, 'M', u'μl'), (0x3396, 'M', u'ml'), (0x3397, 'M', u'dl'), (0x3398, 'M', u'kl'), (0x3399, 'M', u'fm'), (0x339A, 'M', u'nm'), (0x339B, 'M', u'μm'), (0x339C, 'M', u'mm'), (0x339D, 'M', u'cm'), (0x339E, 'M', u'km'), (0x339F, 'M', u'mm2'), (0x33A0, 'M', u'cm2'), (0x33A1, 'M', u'm2'), (0x33A2, 'M', u'km2'), (0x33A3, 'M', u'mm3'), (0x33A4, 'M', u'cm3'), (0x33A5, 'M', u'm3'), (0x33A6, 'M', u'km3'), (0x33A7, 'M', u'm∕s'), (0x33A8, 'M', u'm∕s2'), (0x33A9, 'M', u'pa'), (0x33AA, 'M', u'kpa'), (0x33AB, 'M', u'mpa'), (0x33AC, 'M', u'gpa'), (0x33AD, 'M', u'rad'), (0x33AE, 'M', u'rad∕s'), (0x33AF, 'M', u'rad∕s2'), (0x33B0, 'M', u'ps'), (0x33B1, 'M', u'ns'), (0x33B2, 'M', u'μs'), (0x33B3, 'M', u'ms'), (0x33B4, 'M', u'pv'), (0x33B5, 'M', u'nv'), (0x33B6, 'M', u'μv'), (0x33B7, 'M', u'mv'), (0x33B8, 'M', u'kv'), (0x33B9, 'M', u'mv'), (0x33BA, 'M', u'pw'), (0x33BB, 'M', u'nw'), (0x33BC, 'M', u'μw'), (0x33BD, 'M', u'mw'), (0x33BE, 'M', u'kw'), (0x33BF, 'M', u'mw'), (0x33C0, 'M', u'kω'), (0x33C1, 'M', u'mω'), (0x33C2, 'X'), (0x33C3, 'M', u'bq'), (0x33C4, 'M', u'cc'), (0x33C5, 'M', u'cd'), (0x33C6, 'M', u'c∕kg'), (0x33C7, 'X'), (0x33C8, 'M', u'db'), (0x33C9, 'M', u'gy'), (0x33CA, 'M', u'ha'), (0x33CB, 'M', u'hp'), (0x33CC, 'M', u'in'), (0x33CD, 'M', u'kk'), (0x33CE, 'M', u'km'), (0x33CF, 'M', u'kt'), (0x33D0, 'M', u'lm'), (0x33D1, 'M', u'ln'), (0x33D2, 'M', u'log'), (0x33D3, 'M', u'lx'), (0x33D4, 'M', u'mb'), (0x33D5, 'M', u'mil'), (0x33D6, 'M', u'mol'), (0x33D7, 'M', u'ph'), (0x33D8, 'X'), (0x33D9, 'M', u'ppm'), (0x33DA, 'M', u'pr'), (0x33DB, 'M', u'sr'), (0x33DC, 'M', u'sv'), (0x33DD, 'M', u'wb'), (0x33DE, 'M', u'v∕m'), (0x33DF, 'M', u'a∕m'), (0x33E0, 'M', u'1日'), (0x33E1, 'M', u'2日'), (0x33E2, 'M', u'3日'), (0x33E3, 'M', u'4日'), (0x33E4, 'M', u'5日'), (0x33E5, 'M', u'6日'), (0x33E6, 'M', u'7日'), (0x33E7, 'M', u'8日'), (0x33E8, 'M', u'9日'), (0x33E9, 'M', u'10日'), (0x33EA, 'M', u'11日'), (0x33EB, 'M', u'12日'), (0x33EC, 'M', u'13日'), (0x33ED, 'M', u'14日'), (0x33EE, 'M', u'15日'), (0x33EF, 'M', u'16日'), (0x33F0, 'M', u'17日'), (0x33F1, 'M', u'18日'), (0x33F2, 'M', u'19日'), (0x33F3, 'M', u'20日'), ] def _seg_35(): return [ (0x33F4, 'M', u'21日'), (0x33F5, 'M', u'22日'), (0x33F6, 'M', u'23日'), (0x33F7, 'M', u'24日'), (0x33F8, 'M', u'25日'), (0x33F9, 'M', u'26日'), (0x33FA, 'M', u'27日'), (0x33FB, 'M', u'28日'), (0x33FC, 'M', u'29日'), (0x33FD, 'M', u'30日'), (0x33FE, 'M', u'31日'), (0x33FF, 'M', u'gal'), (0x3400, 'V'), (0x4DB6, 'X'), (0x4DC0, 'V'), (0x9FF0, 'X'), (0xA000, 'V'), (0xA48D, 'X'), (0xA490, 'V'), (0xA4C7, 'X'), (0xA4D0, 'V'), (0xA62C, 'X'), (0xA640, 'M', u'ꙁ'), (0xA641, 'V'), (0xA642, 'M', u'ꙃ'), (0xA643, 'V'), (0xA644, 'M', u'ꙅ'), (0xA645, 'V'), (0xA646, 'M', u'ꙇ'), (0xA647, 'V'), (0xA648, 'M', u'ꙉ'), (0xA649, 'V'), (0xA64A, 'M', u'ꙋ'), (0xA64B, 'V'), (0xA64C, 'M', u'ꙍ'), (0xA64D, 'V'), (0xA64E, 'M', u'ꙏ'), (0xA64F, 'V'), (0xA650, 'M', u'ꙑ'), (0xA651, 'V'), (0xA652, 'M', u'ꙓ'), (0xA653, 'V'), (0xA654, 'M', u'ꙕ'), (0xA655, 'V'), (0xA656, 'M', u'ꙗ'), (0xA657, 'V'), (0xA658, 'M', u'ꙙ'), (0xA659, 'V'), (0xA65A, 'M', u'ꙛ'), (0xA65B, 'V'), (0xA65C, 'M', u'ꙝ'), (0xA65D, 'V'), (0xA65E, 'M', u'ꙟ'), (0xA65F, 'V'), (0xA660, 'M', u'ꙡ'), (0xA661, 'V'), (0xA662, 'M', u'ꙣ'), (0xA663, 'V'), (0xA664, 'M', u'ꙥ'), (0xA665, 'V'), (0xA666, 'M', u'ꙧ'), (0xA667, 'V'), (0xA668, 'M', u'ꙩ'), (0xA669, 'V'), (0xA66A, 'M', u'ꙫ'), (0xA66B, 'V'), (0xA66C, 'M', u'ꙭ'), (0xA66D, 'V'), (0xA680, 'M', u'ꚁ'), (0xA681, 'V'), (0xA682, 'M', u'ꚃ'), (0xA683, 'V'), (0xA684, 'M', u'ꚅ'), (0xA685, 'V'), (0xA686, 'M', u'ꚇ'), (0xA687, 'V'), (0xA688, 'M', u'ꚉ'), (0xA689, 'V'), (0xA68A, 'M', u'ꚋ'), (0xA68B, 'V'), (0xA68C, 'M', u'ꚍ'), (0xA68D, 'V'), (0xA68E, 'M', u'ꚏ'), (0xA68F, 'V'), (0xA690, 'M', u'ꚑ'), (0xA691, 'V'), (0xA692, 'M', u'ꚓ'), (0xA693, 'V'), (0xA694, 'M', u'ꚕ'), (0xA695, 'V'), (0xA696, 'M', u'ꚗ'), (0xA697, 'V'), (0xA698, 'M', u'ꚙ'), (0xA699, 'V'), (0xA69A, 'M', u'ꚛ'), (0xA69B, 'V'), (0xA69C, 'M', u'ъ'), (0xA69D, 'M', u'ь'), (0xA69E, 'V'), (0xA6F8, 'X'), ] def _seg_36(): return [ (0xA700, 'V'), (0xA722, 'M', u'ꜣ'), (0xA723, 'V'), (0xA724, 'M', u'ꜥ'), (0xA725, 'V'), (0xA726, 'M', u'ꜧ'), (0xA727, 'V'), (0xA728, 'M', u'ꜩ'), (0xA729, 'V'), (0xA72A, 'M', u'ꜫ'), (0xA72B, 'V'), (0xA72C, 'M', u'ꜭ'), (0xA72D, 'V'), (0xA72E, 'M', u'ꜯ'), (0xA72F, 'V'), (0xA732, 'M', u'ꜳ'), (0xA733, 'V'), (0xA734, 'M', u'ꜵ'), (0xA735, 'V'), (0xA736, 'M', u'ꜷ'), (0xA737, 'V'), (0xA738, 'M', u'ꜹ'), (0xA739, 'V'), (0xA73A, 'M', u'ꜻ'), (0xA73B, 'V'), (0xA73C, 'M', u'ꜽ'), (0xA73D, 'V'), (0xA73E, 'M', u'ꜿ'), (0xA73F, 'V'), (0xA740, 'M', u'ꝁ'), (0xA741, 'V'), (0xA742, 'M', u'ꝃ'), (0xA743, 'V'), (0xA744, 'M', u'ꝅ'), (0xA745, 'V'), (0xA746, 'M', u'ꝇ'), (0xA747, 'V'), (0xA748, 'M', u'ꝉ'), (0xA749, 'V'), (0xA74A, 'M', u'ꝋ'), (0xA74B, 'V'), (0xA74C, 'M', u'ꝍ'), (0xA74D, 'V'), (0xA74E, 'M', u'ꝏ'), (0xA74F, 'V'), (0xA750, 'M', u'ꝑ'), (0xA751, 'V'), (0xA752, 'M', u'ꝓ'), (0xA753, 'V'), (0xA754, 'M', u'ꝕ'), (0xA755, 'V'), (0xA756, 'M', u'ꝗ'), (0xA757, 'V'), (0xA758, 'M', u'ꝙ'), (0xA759, 'V'), (0xA75A, 'M', u'ꝛ'), (0xA75B, 'V'), (0xA75C, 'M', u'ꝝ'), (0xA75D, 'V'), (0xA75E, 'M', u'ꝟ'), (0xA75F, 'V'), (0xA760, 'M', u'ꝡ'), (0xA761, 'V'), (0xA762, 'M', u'ꝣ'), (0xA763, 'V'), (0xA764, 'M', u'ꝥ'), (0xA765, 'V'), (0xA766, 'M', u'ꝧ'), (0xA767, 'V'), (0xA768, 'M', u'ꝩ'), (0xA769, 'V'), (0xA76A, 'M', u'ꝫ'), (0xA76B, 'V'), (0xA76C, 'M', u'ꝭ'), (0xA76D, 'V'), (0xA76E, 'M', u'ꝯ'), (0xA76F, 'V'), (0xA770, 'M', u'ꝯ'), (0xA771, 'V'), (0xA779, 'M', u'ꝺ'), (0xA77A, 'V'), (0xA77B, 'M', u'ꝼ'), (0xA77C, 'V'), (0xA77D, 'M', u'ᵹ'), (0xA77E, 'M', u'ꝿ'), (0xA77F, 'V'), (0xA780, 'M', u'ꞁ'), (0xA781, 'V'), (0xA782, 'M', u'ꞃ'), (0xA783, 'V'), (0xA784, 'M', u'ꞅ'), (0xA785, 'V'), (0xA786, 'M', u'ꞇ'), (0xA787, 'V'), (0xA78B, 'M', u'ꞌ'), (0xA78C, 'V'), (0xA78D, 'M', u'ɥ'), (0xA78E, 'V'), (0xA790, 'M', u'ꞑ'), (0xA791, 'V'), ] def _seg_37(): return [ (0xA792, 'M', u'ꞓ'), (0xA793, 'V'), (0xA796, 'M', u'ꞗ'), (0xA797, 'V'), (0xA798, 'M', u'ꞙ'), (0xA799, 'V'), (0xA79A, 'M', u'ꞛ'), (0xA79B, 'V'), (0xA79C, 'M', u'ꞝ'), (0xA79D, 'V'), (0xA79E, 'M', u'ꞟ'), (0xA79F, 'V'), (0xA7A0, 'M', u'ꞡ'), (0xA7A1, 'V'), (0xA7A2, 'M', u'ꞣ'), (0xA7A3, 'V'), (0xA7A4, 'M', u'ꞥ'), (0xA7A5, 'V'), (0xA7A6, 'M', u'ꞧ'), (0xA7A7, 'V'), (0xA7A8, 'M', u'ꞩ'), (0xA7A9, 'V'), (0xA7AA, 'M', u'ɦ'), (0xA7AB, 'M', u'ɜ'), (0xA7AC, 'M', u'ɡ'), (0xA7AD, 'M', u'ɬ'), (0xA7AE, 'M', u'ɪ'), (0xA7AF, 'V'), (0xA7B0, 'M', u'ʞ'), (0xA7B1, 'M', u'ʇ'), (0xA7B2, 'M', u'ʝ'), (0xA7B3, 'M', u'ꭓ'), (0xA7B4, 'M', u'ꞵ'), (0xA7B5, 'V'), (0xA7B6, 'M', u'ꞷ'), (0xA7B7, 'V'), (0xA7B8, 'X'), (0xA7B9, 'V'), (0xA7BA, 'X'), (0xA7F7, 'V'), (0xA7F8, 'M', u'ħ'), (0xA7F9, 'M', u'œ'), (0xA7FA, 'V'), (0xA82C, 'X'), (0xA830, 'V'), (0xA83A, 'X'), (0xA840, 'V'), (0xA878, 'X'), (0xA880, 'V'), (0xA8C6, 'X'), (0xA8CE, 'V'), (0xA8DA, 'X'), (0xA8E0, 'V'), (0xA954, 'X'), (0xA95F, 'V'), (0xA97D, 'X'), (0xA980, 'V'), (0xA9CE, 'X'), (0xA9CF, 'V'), (0xA9DA, 'X'), (0xA9DE, 'V'), (0xA9FF, 'X'), (0xAA00, 'V'), (0xAA37, 'X'), (0xAA40, 'V'), (0xAA4E, 'X'), (0xAA50, 'V'), (0xAA5A, 'X'), (0xAA5C, 'V'), (0xAAC3, 'X'), (0xAADB, 'V'), (0xAAF7, 'X'), (0xAB01, 'V'), (0xAB07, 'X'), (0xAB09, 'V'), (0xAB0F, 'X'), (0xAB11, 'V'), (0xAB17, 'X'), (0xAB20, 'V'), (0xAB27, 'X'), (0xAB28, 'V'), (0xAB2F, 'X'), (0xAB30, 'V'), (0xAB5C, 'M', u'ꜧ'), (0xAB5D, 'M', u'ꬷ'), (0xAB5E, 'M', u'ɫ'), (0xAB5F, 'M', u'ꭒ'), (0xAB60, 'V'), (0xAB66, 'X'), (0xAB70, 'M', u'Ꭰ'), (0xAB71, 'M', u'Ꭱ'), (0xAB72, 'M', u'Ꭲ'), (0xAB73, 'M', u'Ꭳ'), (0xAB74, 'M', u'Ꭴ'), (0xAB75, 'M', u'Ꭵ'), (0xAB76, 'M', u'Ꭶ'), (0xAB77, 'M', u'Ꭷ'), (0xAB78, 'M', u'Ꭸ'), (0xAB79, 'M', u'Ꭹ'), (0xAB7A, 'M', u'Ꭺ'), ] def _seg_38(): return [ (0xAB7B, 'M', u'Ꭻ'), (0xAB7C, 'M', u'Ꭼ'), (0xAB7D, 'M', u'Ꭽ'), (0xAB7E, 'M', u'Ꭾ'), (0xAB7F, 'M', u'Ꭿ'), (0xAB80, 'M', u'Ꮀ'), (0xAB81, 'M', u'Ꮁ'), (0xAB82, 'M', u'Ꮂ'), (0xAB83, 'M', u'Ꮃ'), (0xAB84, 'M', u'Ꮄ'), (0xAB85, 'M', u'Ꮅ'), (0xAB86, 'M', u'Ꮆ'), (0xAB87, 'M', u'Ꮇ'), (0xAB88, 'M', u'Ꮈ'), (0xAB89, 'M', u'Ꮉ'), (0xAB8A, 'M', u'Ꮊ'), (0xAB8B, 'M', u'Ꮋ'), (0xAB8C, 'M', u'Ꮌ'), (0xAB8D, 'M', u'Ꮍ'), (0xAB8E, 'M', u'Ꮎ'), (0xAB8F, 'M', u'Ꮏ'), (0xAB90, 'M', u'Ꮐ'), (0xAB91, 'M', u'Ꮑ'), (0xAB92, 'M', u'Ꮒ'), (0xAB93, 'M', u'Ꮓ'), (0xAB94, 'M', u'Ꮔ'), (0xAB95, 'M', u'Ꮕ'), (0xAB96, 'M', u'Ꮖ'), (0xAB97, 'M', u'Ꮗ'), (0xAB98, 'M', u'Ꮘ'), (0xAB99, 'M', u'Ꮙ'), (0xAB9A, 'M', u'Ꮚ'), (0xAB9B, 'M', u'Ꮛ'), (0xAB9C, 'M', u'Ꮜ'), (0xAB9D, 'M', u'Ꮝ'), (0xAB9E, 'M', u'Ꮞ'), (0xAB9F, 'M', u'Ꮟ'), (0xABA0, 'M', u'Ꮠ'), (0xABA1, 'M', u'Ꮡ'), (0xABA2, 'M', u'Ꮢ'), (0xABA3, 'M', u'Ꮣ'), (0xABA4, 'M', u'Ꮤ'), (0xABA5, 'M', u'Ꮥ'), (0xABA6, 'M', u'Ꮦ'), (0xABA7, 'M', u'Ꮧ'), (0xABA8, 'M', u'Ꮨ'), (0xABA9, 'M', u'Ꮩ'), (0xABAA, 'M', u'Ꮪ'), (0xABAB, 'M', u'Ꮫ'), (0xABAC, 'M', u'Ꮬ'), (0xABAD, 'M', u'Ꮭ'), (0xABAE, 'M', u'Ꮮ'), (0xABAF, 'M', u'Ꮯ'), (0xABB0, 'M', u'Ꮰ'), (0xABB1, 'M', u'Ꮱ'), (0xABB2, 'M', u'Ꮲ'), (0xABB3, 'M', u'Ꮳ'), (0xABB4, 'M', u'Ꮴ'), (0xABB5, 'M', u'Ꮵ'), (0xABB6, 'M', u'Ꮶ'), (0xABB7, 'M', u'Ꮷ'), (0xABB8, 'M', u'Ꮸ'), (0xABB9, 'M', u'Ꮹ'), (0xABBA, 'M', u'Ꮺ'), (0xABBB, 'M', u'Ꮻ'), (0xABBC, 'M', u'Ꮼ'), (0xABBD, 'M', u'Ꮽ'), (0xABBE, 'M', u'Ꮾ'), (0xABBF, 'M', u'Ꮿ'), (0xABC0, 'V'), (0xABEE, 'X'), (0xABF0, 'V'), (0xABFA, 'X'), (0xAC00, 'V'), (0xD7A4, 'X'), (0xD7B0, 'V'), (0xD7C7, 'X'), (0xD7CB, 'V'), (0xD7FC, 'X'), (0xF900, 'M', u'豈'), (0xF901, 'M', u'更'), (0xF902, 'M', u'車'), (0xF903, 'M', u'賈'), (0xF904, 'M', u'滑'), (0xF905, 'M', u'串'), (0xF906, 'M', u'句'), (0xF907, 'M', u'龜'), (0xF909, 'M', u'契'), (0xF90A, 'M', u'金'), (0xF90B, 'M', u'喇'), (0xF90C, 'M', u'奈'), (0xF90D, 'M', u'懶'), (0xF90E, 'M', u'癩'), (0xF90F, 'M', u'羅'), (0xF910, 'M', u'蘿'), (0xF911, 'M', u'螺'), (0xF912, 'M', u'裸'), (0xF913, 'M', u'邏'), (0xF914, 'M', u'樂'), (0xF915, 'M', u'洛'), ] def _seg_39(): return [ (0xF916, 'M', u'烙'), (0xF917, 'M', u'珞'), (0xF918, 'M', u'落'), (0xF919, 'M', u'酪'), (0xF91A, 'M', u'駱'), (0xF91B, 'M', u'亂'), (0xF91C, 'M', u'卵'), (0xF91D, 'M', u'欄'), (0xF91E, 'M', u'爛'), (0xF91F, 'M', u'蘭'), (0xF920, 'M', u'鸞'), (0xF921, 'M', u'嵐'), (0xF922, 'M', u'濫'), (0xF923, 'M', u'藍'), (0xF924, 'M', u'襤'), (0xF925, 'M', u'拉'), (0xF926, 'M', u'臘'), (0xF927, 'M', u'蠟'), (0xF928, 'M', u'廊'), (0xF929, 'M', u'朗'), (0xF92A, 'M', u'浪'), (0xF92B, 'M', u'狼'), (0xF92C, 'M', u'郎'), (0xF92D, 'M', u'來'), (0xF92E, 'M', u'冷'), (0xF92F, 'M', u'勞'), (0xF930, 'M', u'擄'), (0xF931, 'M', u'櫓'), (0xF932, 'M', u'爐'), (0xF933, 'M', u'盧'), (0xF934, 'M', u'老'), (0xF935, 'M', u'蘆'), (0xF936, 'M', u'虜'), (0xF937, 'M', u'路'), (0xF938, 'M', u'露'), (0xF939, 'M', u'魯'), (0xF93A, 'M', u'鷺'), (0xF93B, 'M', u'碌'), (0xF93C, 'M', u'祿'), (0xF93D, 'M', u'綠'), (0xF93E, 'M', u'菉'), (0xF93F, 'M', u'錄'), (0xF940, 'M', u'鹿'), (0xF941, 'M', u'論'), (0xF942, 'M', u'壟'), (0xF943, 'M', u'弄'), (0xF944, 'M', u'籠'), (0xF945, 'M', u'聾'), (0xF946, 'M', u'牢'), (0xF947, 'M', u'磊'), (0xF948, 'M', u'賂'), (0xF949, 'M', u'雷'), (0xF94A, 'M', u'壘'), (0xF94B, 'M', u'屢'), (0xF94C, 'M', u'樓'), (0xF94D, 'M', u'淚'), (0xF94E, 'M', u'漏'), (0xF94F, 'M', u'累'), (0xF950, 'M', u'縷'), (0xF951, 'M', u'陋'), (0xF952, 'M', u'勒'), (0xF953, 'M', u'肋'), (0xF954, 'M', u'凜'), (0xF955, 'M', u'凌'), (0xF956, 'M', u'稜'), (0xF957, 'M', u'綾'), (0xF958, 'M', u'菱'), (0xF959, 'M', u'陵'), (0xF95A, 'M', u'讀'), (0xF95B, 'M', u'拏'), (0xF95C, 'M', u'樂'), (0xF95D, 'M', u'諾'), (0xF95E, 'M', u'丹'), (0xF95F, 'M', u'寧'), (0xF960, 'M', u'怒'), (0xF961, 'M', u'率'), (0xF962, 'M', u'異'), (0xF963, 'M', u'北'), (0xF964, 'M', u'磻'), (0xF965, 'M', u'便'), (0xF966, 'M', u'復'), (0xF967, 'M', u'不'), (0xF968, 'M', u'泌'), (0xF969, 'M', u'數'), (0xF96A, 'M', u'索'), (0xF96B, 'M', u'參'), (0xF96C, 'M', u'塞'), (0xF96D, 'M', u'省'), (0xF96E, 'M', u'葉'), (0xF96F, 'M', u'說'), (0xF970, 'M', u'殺'), (0xF971, 'M', u'辰'), (0xF972, 'M', u'沈'), (0xF973, 'M', u'拾'), (0xF974, 'M', u'若'), (0xF975, 'M', u'掠'), (0xF976, 'M', u'略'), (0xF977, 'M', u'亮'), (0xF978, 'M', u'兩'), (0xF979, 'M', u'凉'), ] def _seg_40(): return [ (0xF97A, 'M', u'梁'), (0xF97B, 'M', u'糧'), (0xF97C, 'M', u'良'), (0xF97D, 'M', u'諒'), (0xF97E, 'M', u'量'), (0xF97F, 'M', u'勵'), (0xF980, 'M', u'呂'), (0xF981, 'M', u'女'), (0xF982, 'M', u'廬'), (0xF983, 'M', u'旅'), (0xF984, 'M', u'濾'), (0xF985, 'M', u'礪'), (0xF986, 'M', u'閭'), (0xF987, 'M', u'驪'), (0xF988, 'M', u'麗'), (0xF989, 'M', u'黎'), (0xF98A, 'M', u'力'), (0xF98B, 'M', u'曆'), (0xF98C, 'M', u'歷'), (0xF98D, 'M', u'轢'), (0xF98E, 'M', u'年'), (0xF98F, 'M', u'憐'), (0xF990, 'M', u'戀'), (0xF991, 'M', u'撚'), (0xF992, 'M', u'漣'), (0xF993, 'M', u'煉'), (0xF994, 'M', u'璉'), (0xF995, 'M', u'秊'), (0xF996, 'M', u'練'), (0xF997, 'M', u'聯'), (0xF998, 'M', u'輦'), (0xF999, 'M', u'蓮'), (0xF99A, 'M', u'連'), (0xF99B, 'M', u'鍊'), (0xF99C, 'M', u'列'), (0xF99D, 'M', u'劣'), (0xF99E, 'M', u'咽'), (0xF99F, 'M', u'烈'), (0xF9A0, 'M', u'裂'), (0xF9A1, 'M', u'說'), (0xF9A2, 'M', u'廉'), (0xF9A3, 'M', u'念'), (0xF9A4, 'M', u'捻'), (0xF9A5, 'M', u'殮'), (0xF9A6, 'M', u'簾'), (0xF9A7, 'M', u'獵'), (0xF9A8, 'M', u'令'), (0xF9A9, 'M', u'囹'), (0xF9AA, 'M', u'寧'), (0xF9AB, 'M', u'嶺'), (0xF9AC, 'M', u'怜'), (0xF9AD, 'M', u'玲'), (0xF9AE, 'M', u'瑩'), (0xF9AF, 'M', u'羚'), (0xF9B0, 'M', u'聆'), (0xF9B1, 'M', u'鈴'), (0xF9B2, 'M', u'零'), (0xF9B3, 'M', u'靈'), (0xF9B4, 'M', u'領'), (0xF9B5, 'M', u'例'), (0xF9B6, 'M', u'禮'), (0xF9B7, 'M', u'醴'), (0xF9B8, 'M', u'隸'), (0xF9B9, 'M', u'惡'), (0xF9BA, 'M', u'了'), (0xF9BB, 'M', u'僚'), (0xF9BC, 'M', u'寮'), (0xF9BD, 'M', u'尿'), (0xF9BE, 'M', u'料'), (0xF9BF, 'M', u'樂'), (0xF9C0, 'M', u'燎'), (0xF9C1, 'M', u'療'), (0xF9C2, 'M', u'蓼'), (0xF9C3, 'M', u'遼'), (0xF9C4, 'M', u'龍'), (0xF9C5, 'M', u'暈'), (0xF9C6, 'M', u'阮'), (0xF9C7, 'M', u'劉'), (0xF9C8, 'M', u'杻'), (0xF9C9, 'M', u'柳'), (0xF9CA, 'M', u'流'), (0xF9CB, 'M', u'溜'), (0xF9CC, 'M', u'琉'), (0xF9CD, 'M', u'留'), (0xF9CE, 'M', u'硫'), (0xF9CF, 'M', u'紐'), (0xF9D0, 'M', u'類'), (0xF9D1, 'M', u'六'), (0xF9D2, 'M', u'戮'), (0xF9D3, 'M', u'陸'), (0xF9D4, 'M', u'倫'), (0xF9D5, 'M', u'崙'), (0xF9D6, 'M', u'淪'), (0xF9D7, 'M', u'輪'), (0xF9D8, 'M', u'律'), (0xF9D9, 'M', u'慄'), (0xF9DA, 'M', u'栗'), (0xF9DB, 'M', u'率'), (0xF9DC, 'M', u'隆'), (0xF9DD, 'M', u'利'), ] def _seg_41(): return [ (0xF9DE, 'M', u'吏'), (0xF9DF, 'M', u'履'), (0xF9E0, 'M', u'易'), (0xF9E1, 'M', u'李'), (0xF9E2, 'M', u'梨'), (0xF9E3, 'M', u'泥'), (0xF9E4, 'M', u'理'), (0xF9E5, 'M', u'痢'), (0xF9E6, 'M', u'罹'), (0xF9E7, 'M', u'裏'), (0xF9E8, 'M', u'裡'), (0xF9E9, 'M', u'里'), (0xF9EA, 'M', u'離'), (0xF9EB, 'M', u'匿'), (0xF9EC, 'M', u'溺'), (0xF9ED, 'M', u'吝'), (0xF9EE, 'M', u'燐'), (0xF9EF, 'M', u'璘'), (0xF9F0, 'M', u'藺'), (0xF9F1, 'M', u'隣'), (0xF9F2, 'M', u'鱗'), (0xF9F3, 'M', u'麟'), (0xF9F4, 'M', u'林'), (0xF9F5, 'M', u'淋'), (0xF9F6, 'M', u'臨'), (0xF9F7, 'M', u'立'), (0xF9F8, 'M', u'笠'), (0xF9F9, 'M', u'粒'), (0xF9FA, 'M', u'狀'), (0xF9FB, 'M', u'炙'), (0xF9FC, 'M', u'識'), (0xF9FD, 'M', u'什'), (0xF9FE, 'M', u'茶'), (0xF9FF, 'M', u'刺'), (0xFA00, 'M', u'切'), (0xFA01, 'M', u'度'), (0xFA02, 'M', u'拓'), (0xFA03, 'M', u'糖'), (0xFA04, 'M', u'宅'), (0xFA05, 'M', u'洞'), (0xFA06, 'M', u'暴'), (0xFA07, 'M', u'輻'), (0xFA08, 'M', u'行'), (0xFA09, 'M', u'降'), (0xFA0A, 'M', u'見'), (0xFA0B, 'M', u'廓'), (0xFA0C, 'M', u'兀'), (0xFA0D, 'M', u'嗀'), (0xFA0E, 'V'), (0xFA10, 'M', u'塚'), (0xFA11, 'V'), (0xFA12, 'M', u'晴'), (0xFA13, 'V'), (0xFA15, 'M', u'凞'), (0xFA16, 'M', u'猪'), (0xFA17, 'M', u'益'), (0xFA18, 'M', u'礼'), (0xFA19, 'M', u'神'), (0xFA1A, 'M', u'祥'), (0xFA1B, 'M', u'福'), (0xFA1C, 'M', u'靖'), (0xFA1D, 'M', u'精'), (0xFA1E, 'M', u'羽'), (0xFA1F, 'V'), (0xFA20, 'M', u'蘒'), (0xFA21, 'V'), (0xFA22, 'M', u'諸'), (0xFA23, 'V'), (0xFA25, 'M', u'逸'), (0xFA26, 'M', u'都'), (0xFA27, 'V'), (0xFA2A, 'M', u'飯'), (0xFA2B, 'M', u'飼'), (0xFA2C, 'M', u'館'), (0xFA2D, 'M', u'鶴'), (0xFA2E, 'M', u'郞'), (0xFA2F, 'M', u'隷'), (0xFA30, 'M', u'侮'), (0xFA31, 'M', u'僧'), (0xFA32, 'M', u'免'), (0xFA33, 'M', u'勉'), (0xFA34, 'M', u'勤'), (0xFA35, 'M', u'卑'), (0xFA36, 'M', u'喝'), (0xFA37, 'M', u'嘆'), (0xFA38, 'M', u'器'), (0xFA39, 'M', u'塀'), (0xFA3A, 'M', u'墨'), (0xFA3B, 'M', u'層'), (0xFA3C, 'M', u'屮'), (0xFA3D, 'M', u'悔'), (0xFA3E, 'M', u'慨'), (0xFA3F, 'M', u'憎'), (0xFA40, 'M', u'懲'), (0xFA41, 'M', u'敏'), (0xFA42, 'M', u'既'), (0xFA43, 'M', u'暑'), (0xFA44, 'M', u'梅'), (0xFA45, 'M', u'海'), (0xFA46, 'M', u'渚'), ] def _seg_42(): return [ (0xFA47, 'M', u'漢'), (0xFA48, 'M', u'煮'), (0xFA49, 'M', u'爫'), (0xFA4A, 'M', u'琢'), (0xFA4B, 'M', u'碑'), (0xFA4C, 'M', u'社'), (0xFA4D, 'M', u'祉'), (0xFA4E, 'M', u'祈'), (0xFA4F, 'M', u'祐'), (0xFA50, 'M', u'祖'), (0xFA51, 'M', u'祝'), (0xFA52, 'M', u'禍'), (0xFA53, 'M', u'禎'), (0xFA54, 'M', u'穀'), (0xFA55, 'M', u'突'), (0xFA56, 'M', u'節'), (0xFA57, 'M', u'練'), (0xFA58, 'M', u'縉'), (0xFA59, 'M', u'繁'), (0xFA5A, 'M', u'署'), (0xFA5B, 'M', u'者'), (0xFA5C, 'M', u'臭'), (0xFA5D, 'M', u'艹'), (0xFA5F, 'M', u'著'), (0xFA60, 'M', u'褐'), (0xFA61, 'M', u'視'), (0xFA62, 'M', u'謁'), (0xFA63, 'M', u'謹'), (0xFA64, 'M', u'賓'), (0xFA65, 'M', u'贈'), (0xFA66, 'M', u'辶'), (0xFA67, 'M', u'逸'), (0xFA68, 'M', u'難'), (0xFA69, 'M', u'響'), (0xFA6A, 'M', u'頻'), (0xFA6B, 'M', u'恵'), (0xFA6C, 'M', u'𤋮'), (0xFA6D, 'M', u'舘'), (0xFA6E, 'X'), (0xFA70, 'M', u'並'), (0xFA71, 'M', u'况'), (0xFA72, 'M', u'全'), (0xFA73, 'M', u'侀'), (0xFA74, 'M', u'充'), (0xFA75, 'M', u'冀'), (0xFA76, 'M', u'勇'), (0xFA77, 'M', u'勺'), (0xFA78, 'M', u'喝'), (0xFA79, 'M', u'啕'), (0xFA7A, 'M', u'喙'), (0xFA7B, 'M', u'嗢'), (0xFA7C, 'M', u'塚'), (0xFA7D, 'M', u'墳'), (0xFA7E, 'M', u'奄'), (0xFA7F, 'M', u'奔'), (0xFA80, 'M', u'婢'), (0xFA81, 'M', u'嬨'), (0xFA82, 'M', u'廒'), (0xFA83, 'M', u'廙'), (0xFA84, 'M', u'彩'), (0xFA85, 'M', u'徭'), (0xFA86, 'M', u'惘'), (0xFA87, 'M', u'慎'), (0xFA88, 'M', u'愈'), (0xFA89, 'M', u'憎'), (0xFA8A, 'M', u'慠'), (0xFA8B, 'M', u'懲'), (0xFA8C, 'M', u'戴'), (0xFA8D, 'M', u'揄'), (0xFA8E, 'M', u'搜'), (0xFA8F, 'M', u'摒'), (0xFA90, 'M', u'敖'), (0xFA91, 'M', u'晴'), (0xFA92, 'M', u'朗'), (0xFA93, 'M', u'望'), (0xFA94, 'M', u'杖'), (0xFA95, 'M', u'歹'), (0xFA96, 'M', u'殺'), (0xFA97, 'M', u'流'), (0xFA98, 'M', u'滛'), (0xFA99, 'M', u'滋'), (0xFA9A, 'M', u'漢'), (0xFA9B, 'M', u'瀞'), (0xFA9C, 'M', u'煮'), (0xFA9D, 'M', u'瞧'), (0xFA9E, 'M', u'爵'), (0xFA9F, 'M', u'犯'), (0xFAA0, 'M', u'猪'), (0xFAA1, 'M', u'瑱'), (0xFAA2, 'M', u'甆'), (0xFAA3, 'M', u'画'), (0xFAA4, 'M', u'瘝'), (0xFAA5, 'M', u'瘟'), (0xFAA6, 'M', u'益'), (0xFAA7, 'M', u'盛'), (0xFAA8, 'M', u'直'), (0xFAA9, 'M', u'睊'), (0xFAAA, 'M', u'着'), (0xFAAB, 'M', u'磌'), (0xFAAC, 'M', u'窱'), ] def _seg_43(): return [ (0xFAAD, 'M', u'節'), (0xFAAE, 'M', u'类'), (0xFAAF, 'M', u'絛'), (0xFAB0, 'M', u'練'), (0xFAB1, 'M', u'缾'), (0xFAB2, 'M', u'者'), (0xFAB3, 'M', u'荒'), (0xFAB4, 'M', u'華'), (0xFAB5, 'M', u'蝹'), (0xFAB6, 'M', u'襁'), (0xFAB7, 'M', u'覆'), (0xFAB8, 'M', u'視'), (0xFAB9, 'M', u'調'), (0xFABA, 'M', u'諸'), (0xFABB, 'M', u'請'), (0xFABC, 'M', u'謁'), (0xFABD, 'M', u'諾'), (0xFABE, 'M', u'諭'), (0xFABF, 'M', u'謹'), (0xFAC0, 'M', u'變'), (0xFAC1, 'M', u'贈'), (0xFAC2, 'M', u'輸'), (0xFAC3, 'M', u'遲'), (0xFAC4, 'M', u'醙'), (0xFAC5, 'M', u'鉶'), (0xFAC6, 'M', u'陼'), (0xFAC7, 'M', u'難'), (0xFAC8, 'M', u'靖'), (0xFAC9, 'M', u'韛'), (0xFACA, 'M', u'響'), (0xFACB, 'M', u'頋'), (0xFACC, 'M', u'頻'), (0xFACD, 'M', u'鬒'), (0xFACE, 'M', u'龜'), (0xFACF, 'M', u'𢡊'), (0xFAD0, 'M', u'𢡄'), (0xFAD1, 'M', u'𣏕'), (0xFAD2, 'M', u'㮝'), (0xFAD3, 'M', u'䀘'), (0xFAD4, 'M', u'䀹'), (0xFAD5, 'M', u'𥉉'), (0xFAD6, 'M', u'𥳐'), (0xFAD7, 'M', u'𧻓'), (0xFAD8, 'M', u'齃'), (0xFAD9, 'M', u'龎'), (0xFADA, 'X'), (0xFB00, 'M', u'ff'), (0xFB01, 'M', u'fi'), (0xFB02, 'M', u'fl'), (0xFB03, 'M', u'ffi'), (0xFB04, 'M', u'ffl'), (0xFB05, 'M', u'st'), (0xFB07, 'X'), (0xFB13, 'M', u'մն'), (0xFB14, 'M', u'մե'), (0xFB15, 'M', u'մի'), (0xFB16, 'M', u'վն'), (0xFB17, 'M', u'մխ'), (0xFB18, 'X'), (0xFB1D, 'M', u'יִ'), (0xFB1E, 'V'), (0xFB1F, 'M', u'ײַ'), (0xFB20, 'M', u'ע'), (0xFB21, 'M', u'א'), (0xFB22, 'M', u'ד'), (0xFB23, 'M', u'ה'), (0xFB24, 'M', u'כ'), (0xFB25, 'M', u'ל'), (0xFB26, 'M', u'ם'), (0xFB27, 'M', u'ר'), (0xFB28, 'M', u'ת'), (0xFB29, '3', u'+'), (0xFB2A, 'M', u'שׁ'), (0xFB2B, 'M', u'שׂ'), (0xFB2C, 'M', u'שּׁ'), (0xFB2D, 'M', u'שּׂ'), (0xFB2E, 'M', u'אַ'), (0xFB2F, 'M', u'אָ'), (0xFB30, 'M', u'אּ'), (0xFB31, 'M', u'בּ'), (0xFB32, 'M', u'גּ'), (0xFB33, 'M', u'דּ'), (0xFB34, 'M', u'הּ'), (0xFB35, 'M', u'וּ'), (0xFB36, 'M', u'זּ'), (0xFB37, 'X'), (0xFB38, 'M', u'טּ'), (0xFB39, 'M', u'יּ'), (0xFB3A, 'M', u'ךּ'), (0xFB3B, 'M', u'כּ'), (0xFB3C, 'M', u'לּ'), (0xFB3D, 'X'), (0xFB3E, 'M', u'מּ'), (0xFB3F, 'X'), (0xFB40, 'M', u'נּ'), (0xFB41, 'M', u'סּ'), (0xFB42, 'X'), (0xFB43, 'M', u'ףּ'), (0xFB44, 'M', u'פּ'), (0xFB45, 'X'), ] def _seg_44(): return [ (0xFB46, 'M', u'צּ'), (0xFB47, 'M', u'קּ'), (0xFB48, 'M', u'רּ'), (0xFB49, 'M', u'שּ'), (0xFB4A, 'M', u'תּ'), (0xFB4B, 'M', u'וֹ'), (0xFB4C, 'M', u'בֿ'), (0xFB4D, 'M', u'כֿ'), (0xFB4E, 'M', u'פֿ'), (0xFB4F, 'M', u'אל'), (0xFB50, 'M', u'ٱ'), (0xFB52, 'M', u'ٻ'), (0xFB56, 'M', u'پ'), (0xFB5A, 'M', u'ڀ'), (0xFB5E, 'M', u'ٺ'), (0xFB62, 'M', u'ٿ'), (0xFB66, 'M', u'ٹ'), (0xFB6A, 'M', u'ڤ'), (0xFB6E, 'M', u'ڦ'), (0xFB72, 'M', u'ڄ'), (0xFB76, 'M', u'ڃ'), (0xFB7A, 'M', u'چ'), (0xFB7E, 'M', u'ڇ'), (0xFB82, 'M', u'ڍ'), (0xFB84, 'M', u'ڌ'), (0xFB86, 'M', u'ڎ'), (0xFB88, 'M', u'ڈ'), (0xFB8A, 'M', u'ژ'), (0xFB8C, 'M', u'ڑ'), (0xFB8E, 'M', u'ک'), (0xFB92, 'M', u'گ'), (0xFB96, 'M', u'ڳ'), (0xFB9A, 'M', u'ڱ'), (0xFB9E, 'M', u'ں'), (0xFBA0, 'M', u'ڻ'), (0xFBA4, 'M', u'ۀ'), (0xFBA6, 'M', u'ہ'), (0xFBAA, 'M', u'ھ'), (0xFBAE, 'M', u'ے'), (0xFBB0, 'M', u'ۓ'), (0xFBB2, 'V'), (0xFBC2, 'X'), (0xFBD3, 'M', u'ڭ'), (0xFBD7, 'M', u'ۇ'), (0xFBD9, 'M', u'ۆ'), (0xFBDB, 'M', u'ۈ'), (0xFBDD, 'M', u'ۇٴ'), (0xFBDE, 'M', u'ۋ'), (0xFBE0, 'M', u'ۅ'), (0xFBE2, 'M', u'ۉ'), (0xFBE4, 'M', u'ې'), (0xFBE8, 'M', u'ى'), (0xFBEA, 'M', u'ئا'), (0xFBEC, 'M', u'ئە'), (0xFBEE, 'M', u'ئو'), (0xFBF0, 'M', u'ئۇ'), (0xFBF2, 'M', u'ئۆ'), (0xFBF4, 'M', u'ئۈ'), (0xFBF6, 'M', u'ئې'), (0xFBF9, 'M', u'ئى'), (0xFBFC, 'M', u'ی'), (0xFC00, 'M', u'ئج'), (0xFC01, 'M', u'ئح'), (0xFC02, 'M', u'ئم'), (0xFC03, 'M', u'ئى'), (0xFC04, 'M', u'ئي'), (0xFC05, 'M', u'بج'), (0xFC06, 'M', u'بح'), (0xFC07, 'M', u'بخ'), (0xFC08, 'M', u'بم'), (0xFC09, 'M', u'بى'), (0xFC0A, 'M', u'بي'), (0xFC0B, 'M', u'تج'), (0xFC0C, 'M', u'تح'), (0xFC0D, 'M', u'تخ'), (0xFC0E, 'M', u'تم'), (0xFC0F, 'M', u'تى'), (0xFC10, 'M', u'تي'), (0xFC11, 'M', u'ثج'), (0xFC12, 'M', u'ثم'), (0xFC13, 'M', u'ثى'), (0xFC14, 'M', u'ثي'), (0xFC15, 'M', u'جح'), (0xFC16, 'M', u'جم'), (0xFC17, 'M', u'حج'), (0xFC18, 'M', u'حم'), (0xFC19, 'M', u'خج'), (0xFC1A, 'M', u'خح'), (0xFC1B, 'M', u'خم'), (0xFC1C, 'M', u'سج'), (0xFC1D, 'M', u'سح'), (0xFC1E, 'M', u'سخ'), (0xFC1F, 'M', u'سم'), (0xFC20, 'M', u'صح'), (0xFC21, 'M', u'صم'), (0xFC22, 'M', u'ضج'), (0xFC23, 'M', u'ضح'), (0xFC24, 'M', u'ضخ'), (0xFC25, 'M', u'ضم'), (0xFC26, 'M', u'طح'), ] def _seg_45(): return [ (0xFC27, 'M', u'طم'), (0xFC28, 'M', u'ظم'), (0xFC29, 'M', u'عج'), (0xFC2A, 'M', u'عم'), (0xFC2B, 'M', u'غج'), (0xFC2C, 'M', u'غم'), (0xFC2D, 'M', u'فج'), (0xFC2E, 'M', u'فح'), (0xFC2F, 'M', u'فخ'), (0xFC30, 'M', u'فم'), (0xFC31, 'M', u'فى'), (0xFC32, 'M', u'في'), (0xFC33, 'M', u'قح'), (0xFC34, 'M', u'قم'), (0xFC35, 'M', u'قى'), (0xFC36, 'M', u'قي'), (0xFC37, 'M', u'كا'), (0xFC38, 'M', u'كج'), (0xFC39, 'M', u'كح'), (0xFC3A, 'M', u'كخ'), (0xFC3B, 'M', u'كل'), (0xFC3C, 'M', u'كم'), (0xFC3D, 'M', u'كى'), (0xFC3E, 'M', u'كي'), (0xFC3F, 'M', u'لج'), (0xFC40, 'M', u'لح'), (0xFC41, 'M', u'لخ'), (0xFC42, 'M', u'لم'), (0xFC43, 'M', u'لى'), (0xFC44, 'M', u'لي'), (0xFC45, 'M', u'مج'), (0xFC46, 'M', u'مح'), (0xFC47, 'M', u'مخ'), (0xFC48, 'M', u'مم'), (0xFC49, 'M', u'مى'), (0xFC4A, 'M', u'مي'), (0xFC4B, 'M', u'نج'), (0xFC4C, 'M', u'نح'), (0xFC4D, 'M', u'نخ'), (0xFC4E, 'M', u'نم'), (0xFC4F, 'M', u'نى'), (0xFC50, 'M', u'ني'), (0xFC51, 'M', u'هج'), (0xFC52, 'M', u'هم'), (0xFC53, 'M', u'هى'), (0xFC54, 'M', u'هي'), (0xFC55, 'M', u'يج'), (0xFC56, 'M', u'يح'), (0xFC57, 'M', u'يخ'), (0xFC58, 'M', u'يم'), (0xFC59, 'M', u'يى'), (0xFC5A, 'M', u'يي'), (0xFC5B, 'M', u'ذٰ'), (0xFC5C, 'M', u'رٰ'), (0xFC5D, 'M', u'ىٰ'), (0xFC5E, '3', u' ٌّ'), (0xFC5F, '3', u' ٍّ'), (0xFC60, '3', u' َّ'), (0xFC61, '3', u' ُّ'), (0xFC62, '3', u' ِّ'), (0xFC63, '3', u' ّٰ'), (0xFC64, 'M', u'ئر'), (0xFC65, 'M', u'ئز'), (0xFC66, 'M', u'ئم'), (0xFC67, 'M', u'ئن'), (0xFC68, 'M', u'ئى'), (0xFC69, 'M', u'ئي'), (0xFC6A, 'M', u'بر'), (0xFC6B, 'M', u'بز'), (0xFC6C, 'M', u'بم'), (0xFC6D, 'M', u'بن'), (0xFC6E, 'M', u'بى'), (0xFC6F, 'M', u'بي'), (0xFC70, 'M', u'تر'), (0xFC71, 'M', u'تز'), (0xFC72, 'M', u'تم'), (0xFC73, 'M', u'تن'), (0xFC74, 'M', u'تى'), (0xFC75, 'M', u'تي'), (0xFC76, 'M', u'ثر'), (0xFC77, 'M', u'ثز'), (0xFC78, 'M', u'ثم'), (0xFC79, 'M', u'ثن'), (0xFC7A, 'M', u'ثى'), (0xFC7B, 'M', u'ثي'), (0xFC7C, 'M', u'فى'), (0xFC7D, 'M', u'في'), (0xFC7E, 'M', u'قى'), (0xFC7F, 'M', u'قي'), (0xFC80, 'M', u'كا'), (0xFC81, 'M', u'كل'), (0xFC82, 'M', u'كم'), (0xFC83, 'M', u'كى'), (0xFC84, 'M', u'كي'), (0xFC85, 'M', u'لم'), (0xFC86, 'M', u'لى'), (0xFC87, 'M', u'لي'), (0xFC88, 'M', u'ما'), (0xFC89, 'M', u'مم'), (0xFC8A, 'M', u'نر'), ] def _seg_46(): return [ (0xFC8B, 'M', u'نز'), (0xFC8C, 'M', u'نم'), (0xFC8D, 'M', u'نن'), (0xFC8E, 'M', u'نى'), (0xFC8F, 'M', u'ني'), (0xFC90, 'M', u'ىٰ'), (0xFC91, 'M', u'ير'), (0xFC92, 'M', u'يز'), (0xFC93, 'M', u'يم'), (0xFC94, 'M', u'ين'), (0xFC95, 'M', u'يى'), (0xFC96, 'M', u'يي'), (0xFC97, 'M', u'ئج'), (0xFC98, 'M', u'ئح'), (0xFC99, 'M', u'ئخ'), (0xFC9A, 'M', u'ئم'), (0xFC9B, 'M', u'ئه'), (0xFC9C, 'M', u'بج'), (0xFC9D, 'M', u'بح'), (0xFC9E, 'M', u'بخ'), (0xFC9F, 'M', u'بم'), (0xFCA0, 'M', u'به'), (0xFCA1, 'M', u'تج'), (0xFCA2, 'M', u'تح'), (0xFCA3, 'M', u'تخ'), (0xFCA4, 'M', u'تم'), (0xFCA5, 'M', u'ته'), (0xFCA6, 'M', u'ثم'), (0xFCA7, 'M', u'جح'), (0xFCA8, 'M', u'جم'), (0xFCA9, 'M', u'حج'), (0xFCAA, 'M', u'حم'), (0xFCAB, 'M', u'خج'), (0xFCAC, 'M', u'خم'), (0xFCAD, 'M', u'سج'), (0xFCAE, 'M', u'سح'), (0xFCAF, 'M', u'سخ'), (0xFCB0, 'M', u'سم'), (0xFCB1, 'M', u'صح'), (0xFCB2, 'M', u'صخ'), (0xFCB3, 'M', u'صم'), (0xFCB4, 'M', u'ضج'), (0xFCB5, 'M', u'ضح'), (0xFCB6, 'M', u'ضخ'), (0xFCB7, 'M', u'ضم'), (0xFCB8, 'M', u'طح'), (0xFCB9, 'M', u'ظم'), (0xFCBA, 'M', u'عج'), (0xFCBB, 'M', u'عم'), (0xFCBC, 'M', u'غج'), (0xFCBD, 'M', u'غم'), (0xFCBE, 'M', u'فج'), (0xFCBF, 'M', u'فح'), (0xFCC0, 'M', u'فخ'), (0xFCC1, 'M', u'فم'), (0xFCC2, 'M', u'قح'), (0xFCC3, 'M', u'قم'), (0xFCC4, 'M', u'كج'), (0xFCC5, 'M', u'كح'), (0xFCC6, 'M', u'كخ'), (0xFCC7, 'M', u'كل'), (0xFCC8, 'M', u'كم'), (0xFCC9, 'M', u'لج'), (0xFCCA, 'M', u'لح'), (0xFCCB, 'M', u'لخ'), (0xFCCC, 'M', u'لم'), (0xFCCD, 'M', u'له'), (0xFCCE, 'M', u'مج'), (0xFCCF, 'M', u'مح'), (0xFCD0, 'M', u'مخ'), (0xFCD1, 'M', u'مم'), (0xFCD2, 'M', u'نج'), (0xFCD3, 'M', u'نح'), (0xFCD4, 'M', u'نخ'), (0xFCD5, 'M', u'نم'), (0xFCD6, 'M', u'نه'), (0xFCD7, 'M', u'هج'), (0xFCD8, 'M', u'هم'), (0xFCD9, 'M', u'هٰ'), (0xFCDA, 'M', u'يج'), (0xFCDB, 'M', u'يح'), (0xFCDC, 'M', u'يخ'), (0xFCDD, 'M', u'يم'), (0xFCDE, 'M', u'يه'), (0xFCDF, 'M', u'ئم'), (0xFCE0, 'M', u'ئه'), (0xFCE1, 'M', u'بم'), (0xFCE2, 'M', u'به'), (0xFCE3, 'M', u'تم'), (0xFCE4, 'M', u'ته'), (0xFCE5, 'M', u'ثم'), (0xFCE6, 'M', u'ثه'), (0xFCE7, 'M', u'سم'), (0xFCE8, 'M', u'سه'), (0xFCE9, 'M', u'شم'), (0xFCEA, 'M', u'شه'), (0xFCEB, 'M', u'كل'), (0xFCEC, 'M', u'كم'), (0xFCED, 'M', u'لم'), (0xFCEE, 'M', u'نم'), ] def _seg_47(): return [ (0xFCEF, 'M', u'نه'), (0xFCF0, 'M', u'يم'), (0xFCF1, 'M', u'يه'), (0xFCF2, 'M', u'ـَّ'), (0xFCF3, 'M', u'ـُّ'), (0xFCF4, 'M', u'ـِّ'), (0xFCF5, 'M', u'طى'), (0xFCF6, 'M', u'طي'), (0xFCF7, 'M', u'عى'), (0xFCF8, 'M', u'عي'), (0xFCF9, 'M', u'غى'), (0xFCFA, 'M', u'غي'), (0xFCFB, 'M', u'سى'), (0xFCFC, 'M', u'سي'), (0xFCFD, 'M', u'شى'), (0xFCFE, 'M', u'شي'), (0xFCFF, 'M', u'حى'), (0xFD00, 'M', u'حي'), (0xFD01, 'M', u'جى'), (0xFD02, 'M', u'جي'), (0xFD03, 'M', u'خى'), (0xFD04, 'M', u'خي'), (0xFD05, 'M', u'صى'), (0xFD06, 'M', u'صي'), (0xFD07, 'M', u'ضى'), (0xFD08, 'M', u'ضي'), (0xFD09, 'M', u'شج'), (0xFD0A, 'M', u'شح'), (0xFD0B, 'M', u'شخ'), (0xFD0C, 'M', u'شم'), (0xFD0D, 'M', u'شر'), (0xFD0E, 'M', u'سر'), (0xFD0F, 'M', u'صر'), (0xFD10, 'M', u'ضر'), (0xFD11, 'M', u'طى'), (0xFD12, 'M', u'طي'), (0xFD13, 'M', u'عى'), (0xFD14, 'M', u'عي'), (0xFD15, 'M', u'غى'), (0xFD16, 'M', u'غي'), (0xFD17, 'M', u'سى'), (0xFD18, 'M', u'سي'), (0xFD19, 'M', u'شى'), (0xFD1A, 'M', u'شي'), (0xFD1B, 'M', u'حى'), (0xFD1C, 'M', u'حي'), (0xFD1D, 'M', u'جى'), (0xFD1E, 'M', u'جي'), (0xFD1F, 'M', u'خى'), (0xFD20, 'M', u'خي'), (0xFD21, 'M', u'صى'), (0xFD22, 'M', u'صي'), (0xFD23, 'M', u'ضى'), (0xFD24, 'M', u'ضي'), (0xFD25, 'M', u'شج'), (0xFD26, 'M', u'شح'), (0xFD27, 'M', u'شخ'), (0xFD28, 'M', u'شم'), (0xFD29, 'M', u'شر'), (0xFD2A, 'M', u'سر'), (0xFD2B, 'M', u'صر'), (0xFD2C, 'M', u'ضر'), (0xFD2D, 'M', u'شج'), (0xFD2E, 'M', u'شح'), (0xFD2F, 'M', u'شخ'), (0xFD30, 'M', u'شم'), (0xFD31, 'M', u'سه'), (0xFD32, 'M', u'شه'), (0xFD33, 'M', u'طم'), (0xFD34, 'M', u'سج'), (0xFD35, 'M', u'سح'), (0xFD36, 'M', u'سخ'), (0xFD37, 'M', u'شج'), (0xFD38, 'M', u'شح'), (0xFD39, 'M', u'شخ'), (0xFD3A, 'M', u'طم'), (0xFD3B, 'M', u'ظم'), (0xFD3C, 'M', u'اً'), (0xFD3E, 'V'), (0xFD40, 'X'), (0xFD50, 'M', u'تجم'), (0xFD51, 'M', u'تحج'), (0xFD53, 'M', u'تحم'), (0xFD54, 'M', u'تخم'), (0xFD55, 'M', u'تمج'), (0xFD56, 'M', u'تمح'), (0xFD57, 'M', u'تمخ'), (0xFD58, 'M', u'جمح'), (0xFD5A, 'M', u'حمي'), (0xFD5B, 'M', u'حمى'), (0xFD5C, 'M', u'سحج'), (0xFD5D, 'M', u'سجح'), (0xFD5E, 'M', u'سجى'), (0xFD5F, 'M', u'سمح'), (0xFD61, 'M', u'سمج'), (0xFD62, 'M', u'سمم'), (0xFD64, 'M', u'صحح'), (0xFD66, 'M', u'صمم'), (0xFD67, 'M', u'شحم'), (0xFD69, 'M', u'شجي'), ] def _seg_48(): return [ (0xFD6A, 'M', u'شمخ'), (0xFD6C, 'M', u'شمم'), (0xFD6E, 'M', u'ضحى'), (0xFD6F, 'M', u'ضخم'), (0xFD71, 'M', u'طمح'), (0xFD73, 'M', u'طمم'), (0xFD74, 'M', u'طمي'), (0xFD75, 'M', u'عجم'), (0xFD76, 'M', u'عمم'), (0xFD78, 'M', u'عمى'), (0xFD79, 'M', u'غمم'), (0xFD7A, 'M', u'غمي'), (0xFD7B, 'M', u'غمى'), (0xFD7C, 'M', u'فخم'), (0xFD7E, 'M', u'قمح'), (0xFD7F, 'M', u'قمم'), (0xFD80, 'M', u'لحم'), (0xFD81, 'M', u'لحي'), (0xFD82, 'M', u'لحى'), (0xFD83, 'M', u'لجج'), (0xFD85, 'M', u'لخم'), (0xFD87, 'M', u'لمح'), (0xFD89, 'M', u'محج'), (0xFD8A, 'M', u'محم'), (0xFD8B, 'M', u'محي'), (0xFD8C, 'M', u'مجح'), (0xFD8D, 'M', u'مجم'), (0xFD8E, 'M', u'مخج'), (0xFD8F, 'M', u'مخم'), (0xFD90, 'X'), (0xFD92, 'M', u'مجخ'), (0xFD93, 'M', u'همج'), (0xFD94, 'M', u'همم'), (0xFD95, 'M', u'نحم'), (0xFD96, 'M', u'نحى'), (0xFD97, 'M', u'نجم'), (0xFD99, 'M', u'نجى'), (0xFD9A, 'M', u'نمي'), (0xFD9B, 'M', u'نمى'), (0xFD9C, 'M', u'يمم'), (0xFD9E, 'M', u'بخي'), (0xFD9F, 'M', u'تجي'), (0xFDA0, 'M', u'تجى'), (0xFDA1, 'M', u'تخي'), (0xFDA2, 'M', u'تخى'), (0xFDA3, 'M', u'تمي'), (0xFDA4, 'M', u'تمى'), (0xFDA5, 'M', u'جمي'), (0xFDA6, 'M', u'جحى'), (0xFDA7, 'M', u'جمى'), (0xFDA8, 'M', u'سخى'), (0xFDA9, 'M', u'صحي'), (0xFDAA, 'M', u'شحي'), (0xFDAB, 'M', u'ضحي'), (0xFDAC, 'M', u'لجي'), (0xFDAD, 'M', u'لمي'), (0xFDAE, 'M', u'يحي'), (0xFDAF, 'M', u'يجي'), (0xFDB0, 'M', u'يمي'), (0xFDB1, 'M', u'ممي'), (0xFDB2, 'M', u'قمي'), (0xFDB3, 'M', u'نحي'), (0xFDB4, 'M', u'قمح'), (0xFDB5, 'M', u'لحم'), (0xFDB6, 'M', u'عمي'), (0xFDB7, 'M', u'كمي'), (0xFDB8, 'M', u'نجح'), (0xFDB9, 'M', u'مخي'), (0xFDBA, 'M', u'لجم'), (0xFDBB, 'M', u'كمم'), (0xFDBC, 'M', u'لجم'), (0xFDBD, 'M', u'نجح'), (0xFDBE, 'M', u'جحي'), (0xFDBF, 'M', u'حجي'), (0xFDC0, 'M', u'مجي'), (0xFDC1, 'M', u'فمي'), (0xFDC2, 'M', u'بحي'), (0xFDC3, 'M', u'كمم'), (0xFDC4, 'M', u'عجم'), (0xFDC5, 'M', u'صمم'), (0xFDC6, 'M', u'سخي'), (0xFDC7, 'M', u'نجي'), (0xFDC8, 'X'), (0xFDF0, 'M', u'صلے'), (0xFDF1, 'M', u'قلے'), (0xFDF2, 'M', u'الله'), (0xFDF3, 'M', u'اكبر'), (0xFDF4, 'M', u'محمد'), (0xFDF5, 'M', u'صلعم'), (0xFDF6, 'M', u'رسول'), (0xFDF7, 'M', u'عليه'), (0xFDF8, 'M', u'وسلم'), (0xFDF9, 'M', u'صلى'), (0xFDFA, '3', u'صلى الله عليه وسلم'), (0xFDFB, '3', u'جل جلاله'), (0xFDFC, 'M', u'ریال'), (0xFDFD, 'V'), (0xFDFE, 'X'), (0xFE00, 'I'), (0xFE10, '3', u','), ] def _seg_49(): return [ (0xFE11, 'M', u'、'), (0xFE12, 'X'), (0xFE13, '3', u':'), (0xFE14, '3', u';'), (0xFE15, '3', u'!'), (0xFE16, '3', u'?'), (0xFE17, 'M', u'〖'), (0xFE18, 'M', u'〗'), (0xFE19, 'X'), (0xFE20, 'V'), (0xFE30, 'X'), (0xFE31, 'M', u'—'), (0xFE32, 'M', u'–'), (0xFE33, '3', u'_'), (0xFE35, '3', u'('), (0xFE36, '3', u')'), (0xFE37, '3', u'{'), (0xFE38, '3', u'}'), (0xFE39, 'M', u'〔'), (0xFE3A, 'M', u'〕'), (0xFE3B, 'M', u'【'), (0xFE3C, 'M', u'】'), (0xFE3D, 'M', u'《'), (0xFE3E, 'M', u'》'), (0xFE3F, 'M', u'〈'), (0xFE40, 'M', u'〉'), (0xFE41, 'M', u'「'), (0xFE42, 'M', u'」'), (0xFE43, 'M', u'『'), (0xFE44, 'M', u'』'), (0xFE45, 'V'), (0xFE47, '3', u'['), (0xFE48, '3', u']'), (0xFE49, '3', u' ̅'), (0xFE4D, '3', u'_'), (0xFE50, '3', u','), (0xFE51, 'M', u'、'), (0xFE52, 'X'), (0xFE54, '3', u';'), (0xFE55, '3', u':'), (0xFE56, '3', u'?'), (0xFE57, '3', u'!'), (0xFE58, 'M', u'—'), (0xFE59, '3', u'('), (0xFE5A, '3', u')'), (0xFE5B, '3', u'{'), (0xFE5C, '3', u'}'), (0xFE5D, 'M', u'〔'), (0xFE5E, 'M', u'〕'), (0xFE5F, '3', u'#'), (0xFE60, '3', u'&'), (0xFE61, '3', u'*'), (0xFE62, '3', u'+'), (0xFE63, 'M', u'-'), (0xFE64, '3', u'<'), (0xFE65, '3', u'>'), (0xFE66, '3', u'='), (0xFE67, 'X'), (0xFE68, '3', u'\\'), (0xFE69, '3', u'$'), (0xFE6A, '3', u'%'), (0xFE6B, '3', u'@'), (0xFE6C, 'X'), (0xFE70, '3', u' ً'), (0xFE71, 'M', u'ـً'), (0xFE72, '3', u' ٌ'), (0xFE73, 'V'), (0xFE74, '3', u' ٍ'), (0xFE75, 'X'), (0xFE76, '3', u' َ'), (0xFE77, 'M', u'ـَ'), (0xFE78, '3', u' ُ'), (0xFE79, 'M', u'ـُ'), (0xFE7A, '3', u' ِ'), (0xFE7B, 'M', u'ـِ'), (0xFE7C, '3', u' ّ'), (0xFE7D, 'M', u'ـّ'), (0xFE7E, '3', u' ْ'), (0xFE7F, 'M', u'ـْ'), (0xFE80, 'M', u'ء'), (0xFE81, 'M', u'آ'), (0xFE83, 'M', u'أ'), (0xFE85, 'M', u'ؤ'), (0xFE87, 'M', u'إ'), (0xFE89, 'M', u'ئ'), (0xFE8D, 'M', u'ا'), (0xFE8F, 'M', u'ب'), (0xFE93, 'M', u'ة'), (0xFE95, 'M', u'ت'), (0xFE99, 'M', u'ث'), (0xFE9D, 'M', u'ج'), (0xFEA1, 'M', u'ح'), (0xFEA5, 'M', u'خ'), (0xFEA9, 'M', u'د'), (0xFEAB, 'M', u'ذ'), (0xFEAD, 'M', u'ر'), (0xFEAF, 'M', u'ز'), (0xFEB1, 'M', u'س'), (0xFEB5, 'M', u'ش'), (0xFEB9, 'M', u'ص'), ] def _seg_50(): return [ (0xFEBD, 'M', u'ض'), (0xFEC1, 'M', u'ط'), (0xFEC5, 'M', u'ظ'), (0xFEC9, 'M', u'ع'), (0xFECD, 'M', u'غ'), (0xFED1, 'M', u'ف'), (0xFED5, 'M', u'ق'), (0xFED9, 'M', u'ك'), (0xFEDD, 'M', u'ل'), (0xFEE1, 'M', u'م'), (0xFEE5, 'M', u'ن'), (0xFEE9, 'M', u'ه'), (0xFEED, 'M', u'و'), (0xFEEF, 'M', u'ى'), (0xFEF1, 'M', u'ي'), (0xFEF5, 'M', u'لآ'), (0xFEF7, 'M', u'لأ'), (0xFEF9, 'M', u'لإ'), (0xFEFB, 'M', u'لا'), (0xFEFD, 'X'), (0xFEFF, 'I'), (0xFF00, 'X'), (0xFF01, '3', u'!'), (0xFF02, '3', u'"'), (0xFF03, '3', u'#'), (0xFF04, '3', u'$'), (0xFF05, '3', u'%'), (0xFF06, '3', u'&'), (0xFF07, '3', u'\''), (0xFF08, '3', u'('), (0xFF09, '3', u')'), (0xFF0A, '3', u'*'), (0xFF0B, '3', u'+'), (0xFF0C, '3', u','), (0xFF0D, 'M', u'-'), (0xFF0E, 'M', u'.'), (0xFF0F, '3', u'/'), (0xFF10, 'M', u'0'), (0xFF11, 'M', u'1'), (0xFF12, 'M', u'2'), (0xFF13, 'M', u'3'), (0xFF14, 'M', u'4'), (0xFF15, 'M', u'5'), (0xFF16, 'M', u'6'), (0xFF17, 'M', u'7'), (0xFF18, 'M', u'8'), (0xFF19, 'M', u'9'), (0xFF1A, '3', u':'), (0xFF1B, '3', u';'), (0xFF1C, '3', u'<'), (0xFF1D, '3', u'='), (0xFF1E, '3', u'>'), (0xFF1F, '3', u'?'), (0xFF20, '3', u'@'), (0xFF21, 'M', u'a'), (0xFF22, 'M', u'b'), (0xFF23, 'M', u'c'), (0xFF24, 'M', u'd'), (0xFF25, 'M', u'e'), (0xFF26, 'M', u'f'), (0xFF27, 'M', u'g'), (0xFF28, 'M', u'h'), (0xFF29, 'M', u'i'), (0xFF2A, 'M', u'j'), (0xFF2B, 'M', u'k'), (0xFF2C, 'M', u'l'), (0xFF2D, 'M', u'm'), (0xFF2E, 'M', u'n'), (0xFF2F, 'M', u'o'), (0xFF30, 'M', u'p'), (0xFF31, 'M', u'q'), (0xFF32, 'M', u'r'), (0xFF33, 'M', u's'), (0xFF34, 'M', u't'), (0xFF35, 'M', u'u'), (0xFF36, 'M', u'v'), (0xFF37, 'M', u'w'), (0xFF38, 'M', u'x'), (0xFF39, 'M', u'y'), (0xFF3A, 'M', u'z'), (0xFF3B, '3', u'['), (0xFF3C, '3', u'\\'), (0xFF3D, '3', u']'), (0xFF3E, '3', u'^'), (0xFF3F, '3', u'_'), (0xFF40, '3', u'`'), (0xFF41, 'M', u'a'), (0xFF42, 'M', u'b'), (0xFF43, 'M', u'c'), (0xFF44, 'M', u'd'), (0xFF45, 'M', u'e'), (0xFF46, 'M', u'f'), (0xFF47, 'M', u'g'), (0xFF48, 'M', u'h'), (0xFF49, 'M', u'i'), (0xFF4A, 'M', u'j'), (0xFF4B, 'M', u'k'), (0xFF4C, 'M', u'l'), (0xFF4D, 'M', u'm'), (0xFF4E, 'M', u'n'), ] def _seg_51(): return [ (0xFF4F, 'M', u'o'), (0xFF50, 'M', u'p'), (0xFF51, 'M', u'q'), (0xFF52, 'M', u'r'), (0xFF53, 'M', u's'), (0xFF54, 'M', u't'), (0xFF55, 'M', u'u'), (0xFF56, 'M', u'v'), (0xFF57, 'M', u'w'), (0xFF58, 'M', u'x'), (0xFF59, 'M', u'y'), (0xFF5A, 'M', u'z'), (0xFF5B, '3', u'{'), (0xFF5C, '3', u'|'), (0xFF5D, '3', u'}'), (0xFF5E, '3', u'~'), (0xFF5F, 'M', u'⦅'), (0xFF60, 'M', u'⦆'), (0xFF61, 'M', u'.'), (0xFF62, 'M', u'「'), (0xFF63, 'M', u'」'), (0xFF64, 'M', u'、'), (0xFF65, 'M', u'・'), (0xFF66, 'M', u'ヲ'), (0xFF67, 'M', u'ァ'), (0xFF68, 'M', u'ィ'), (0xFF69, 'M', u'ゥ'), (0xFF6A, 'M', u'ェ'), (0xFF6B, 'M', u'ォ'), (0xFF6C, 'M', u'ャ'), (0xFF6D, 'M', u'ュ'), (0xFF6E, 'M', u'ョ'), (0xFF6F, 'M', u'ッ'), (0xFF70, 'M', u'ー'), (0xFF71, 'M', u'ア'), (0xFF72, 'M', u'イ'), (0xFF73, 'M', u'ウ'), (0xFF74, 'M', u'エ'), (0xFF75, 'M', u'オ'), (0xFF76, 'M', u'カ'), (0xFF77, 'M', u'キ'), (0xFF78, 'M', u'ク'), (0xFF79, 'M', u'ケ'), (0xFF7A, 'M', u'コ'), (0xFF7B, 'M', u'サ'), (0xFF7C, 'M', u'シ'), (0xFF7D, 'M', u'ス'), (0xFF7E, 'M', u'セ'), (0xFF7F, 'M', u'ソ'), (0xFF80, 'M', u'タ'), (0xFF81, 'M', u'チ'), (0xFF82, 'M', u'ツ'), (0xFF83, 'M', u'テ'), (0xFF84, 'M', u'ト'), (0xFF85, 'M', u'ナ'), (0xFF86, 'M', u'ニ'), (0xFF87, 'M', u'ヌ'), (0xFF88, 'M', u'ネ'), (0xFF89, 'M', u'ノ'), (0xFF8A, 'M', u'ハ'), (0xFF8B, 'M', u'ヒ'), (0xFF8C, 'M', u'フ'), (0xFF8D, 'M', u'ヘ'), (0xFF8E, 'M', u'ホ'), (0xFF8F, 'M', u'マ'), (0xFF90, 'M', u'ミ'), (0xFF91, 'M', u'ム'), (0xFF92, 'M', u'メ'), (0xFF93, 'M', u'モ'), (0xFF94, 'M', u'ヤ'), (0xFF95, 'M', u'ユ'), (0xFF96, 'M', u'ヨ'), (0xFF97, 'M', u'ラ'), (0xFF98, 'M', u'リ'), (0xFF99, 'M', u'ル'), (0xFF9A, 'M', u'レ'), (0xFF9B, 'M', u'ロ'), (0xFF9C, 'M', u'ワ'), (0xFF9D, 'M', u'ン'), (0xFF9E, 'M', u'゙'), (0xFF9F, 'M', u'゚'), (0xFFA0, 'X'), (0xFFA1, 'M', u'ᄀ'), (0xFFA2, 'M', u'ᄁ'), (0xFFA3, 'M', u'ᆪ'), (0xFFA4, 'M', u'ᄂ'), (0xFFA5, 'M', u'ᆬ'), (0xFFA6, 'M', u'ᆭ'), (0xFFA7, 'M', u'ᄃ'), (0xFFA8, 'M', u'ᄄ'), (0xFFA9, 'M', u'ᄅ'), (0xFFAA, 'M', u'ᆰ'), (0xFFAB, 'M', u'ᆱ'), (0xFFAC, 'M', u'ᆲ'), (0xFFAD, 'M', u'ᆳ'), (0xFFAE, 'M', u'ᆴ'), (0xFFAF, 'M', u'ᆵ'), (0xFFB0, 'M', u'ᄚ'), (0xFFB1, 'M', u'ᄆ'), (0xFFB2, 'M', u'ᄇ'), ] def _seg_52(): return [ (0xFFB3, 'M', u'ᄈ'), (0xFFB4, 'M', u'ᄡ'), (0xFFB5, 'M', u'ᄉ'), (0xFFB6, 'M', u'ᄊ'), (0xFFB7, 'M', u'ᄋ'), (0xFFB8, 'M', u'ᄌ'), (0xFFB9, 'M', u'ᄍ'), (0xFFBA, 'M', u'ᄎ'), (0xFFBB, 'M', u'ᄏ'), (0xFFBC, 'M', u'ᄐ'), (0xFFBD, 'M', u'ᄑ'), (0xFFBE, 'M', u'ᄒ'), (0xFFBF, 'X'), (0xFFC2, 'M', u'ᅡ'), (0xFFC3, 'M', u'ᅢ'), (0xFFC4, 'M', u'ᅣ'), (0xFFC5, 'M', u'ᅤ'), (0xFFC6, 'M', u'ᅥ'), (0xFFC7, 'M', u'ᅦ'), (0xFFC8, 'X'), (0xFFCA, 'M', u'ᅧ'), (0xFFCB, 'M', u'ᅨ'), (0xFFCC, 'M', u'ᅩ'), (0xFFCD, 'M', u'ᅪ'), (0xFFCE, 'M', u'ᅫ'), (0xFFCF, 'M', u'ᅬ'), (0xFFD0, 'X'), (0xFFD2, 'M', u'ᅭ'), (0xFFD3, 'M', u'ᅮ'), (0xFFD4, 'M', u'ᅯ'), (0xFFD5, 'M', u'ᅰ'), (0xFFD6, 'M', u'ᅱ'), (0xFFD7, 'M', u'ᅲ'), (0xFFD8, 'X'), (0xFFDA, 'M', u'ᅳ'), (0xFFDB, 'M', u'ᅴ'), (0xFFDC, 'M', u'ᅵ'), (0xFFDD, 'X'), (0xFFE0, 'M', u'¢'), (0xFFE1, 'M', u'£'), (0xFFE2, 'M', u'¬'), (0xFFE3, '3', u' ̄'), (0xFFE4, 'M', u'¦'), (0xFFE5, 'M', u'¥'), (0xFFE6, 'M', u'₩'), (0xFFE7, 'X'), (0xFFE8, 'M', u'│'), (0xFFE9, 'M', u'←'), (0xFFEA, 'M', u'↑'), (0xFFEB, 'M', u'→'), (0xFFEC, 'M', u'↓'), (0xFFED, 'M', u'■'), (0xFFEE, 'M', u'○'), (0xFFEF, 'X'), (0x10000, 'V'), (0x1000C, 'X'), (0x1000D, 'V'), (0x10027, 'X'), (0x10028, 'V'), (0x1003B, 'X'), (0x1003C, 'V'), (0x1003E, 'X'), (0x1003F, 'V'), (0x1004E, 'X'), (0x10050, 'V'), (0x1005E, 'X'), (0x10080, 'V'), (0x100FB, 'X'), (0x10100, 'V'), (0x10103, 'X'), (0x10107, 'V'), (0x10134, 'X'), (0x10137, 'V'), (0x1018F, 'X'), (0x10190, 'V'), (0x1019C, 'X'), (0x101A0, 'V'), (0x101A1, 'X'), (0x101D0, 'V'), (0x101FE, 'X'), (0x10280, 'V'), (0x1029D, 'X'), (0x102A0, 'V'), (0x102D1, 'X'), (0x102E0, 'V'), (0x102FC, 'X'), (0x10300, 'V'), (0x10324, 'X'), (0x1032D, 'V'), (0x1034B, 'X'), (0x10350, 'V'), (0x1037B, 'X'), (0x10380, 'V'), (0x1039E, 'X'), (0x1039F, 'V'), (0x103C4, 'X'), (0x103C8, 'V'), (0x103D6, 'X'), (0x10400, 'M', u'𐐨'), (0x10401, 'M', u'𐐩'), ] def _seg_53(): return [ (0x10402, 'M', u'𐐪'), (0x10403, 'M', u'𐐫'), (0x10404, 'M', u'𐐬'), (0x10405, 'M', u'𐐭'), (0x10406, 'M', u'𐐮'), (0x10407, 'M', u'𐐯'), (0x10408, 'M', u'𐐰'), (0x10409, 'M', u'𐐱'), (0x1040A, 'M', u'𐐲'), (0x1040B, 'M', u'𐐳'), (0x1040C, 'M', u'𐐴'), (0x1040D, 'M', u'𐐵'), (0x1040E, 'M', u'𐐶'), (0x1040F, 'M', u'𐐷'), (0x10410, 'M', u'𐐸'), (0x10411, 'M', u'𐐹'), (0x10412, 'M', u'𐐺'), (0x10413, 'M', u'𐐻'), (0x10414, 'M', u'𐐼'), (0x10415, 'M', u'𐐽'), (0x10416, 'M', u'𐐾'), (0x10417, 'M', u'𐐿'), (0x10418, 'M', u'𐑀'), (0x10419, 'M', u'𐑁'), (0x1041A, 'M', u'𐑂'), (0x1041B, 'M', u'𐑃'), (0x1041C, 'M', u'𐑄'), (0x1041D, 'M', u'𐑅'), (0x1041E, 'M', u'𐑆'), (0x1041F, 'M', u'𐑇'), (0x10420, 'M', u'𐑈'), (0x10421, 'M', u'𐑉'), (0x10422, 'M', u'𐑊'), (0x10423, 'M', u'𐑋'), (0x10424, 'M', u'𐑌'), (0x10425, 'M', u'𐑍'), (0x10426, 'M', u'𐑎'), (0x10427, 'M', u'𐑏'), (0x10428, 'V'), (0x1049E, 'X'), (0x104A0, 'V'), (0x104AA, 'X'), (0x104B0, 'M', u'𐓘'), (0x104B1, 'M', u'𐓙'), (0x104B2, 'M', u'𐓚'), (0x104B3, 'M', u'𐓛'), (0x104B4, 'M', u'𐓜'), (0x104B5, 'M', u'𐓝'), (0x104B6, 'M', u'𐓞'), (0x104B7, 'M', u'𐓟'), (0x104B8, 'M', u'𐓠'), (0x104B9, 'M', u'𐓡'), (0x104BA, 'M', u'𐓢'), (0x104BB, 'M', u'𐓣'), (0x104BC, 'M', u'𐓤'), (0x104BD, 'M', u'𐓥'), (0x104BE, 'M', u'𐓦'), (0x104BF, 'M', u'𐓧'), (0x104C0, 'M', u'𐓨'), (0x104C1, 'M', u'𐓩'), (0x104C2, 'M', u'𐓪'), (0x104C3, 'M', u'𐓫'), (0x104C4, 'M', u'𐓬'), (0x104C5, 'M', u'𐓭'), (0x104C6, 'M', u'𐓮'), (0x104C7, 'M', u'𐓯'), (0x104C8, 'M', u'𐓰'), (0x104C9, 'M', u'𐓱'), (0x104CA, 'M', u'𐓲'), (0x104CB, 'M', u'𐓳'), (0x104CC, 'M', u'𐓴'), (0x104CD, 'M', u'𐓵'), (0x104CE, 'M', u'𐓶'), (0x104CF, 'M', u'𐓷'), (0x104D0, 'M', u'𐓸'), (0x104D1, 'M', u'𐓹'), (0x104D2, 'M', u'𐓺'), (0x104D3, 'M', u'𐓻'), (0x104D4, 'X'), (0x104D8, 'V'), (0x104FC, 'X'), (0x10500, 'V'), (0x10528, 'X'), (0x10530, 'V'), (0x10564, 'X'), (0x1056F, 'V'), (0x10570, 'X'), (0x10600, 'V'), (0x10737, 'X'), (0x10740, 'V'), (0x10756, 'X'), (0x10760, 'V'), (0x10768, 'X'), (0x10800, 'V'), (0x10806, 'X'), (0x10808, 'V'), (0x10809, 'X'), (0x1080A, 'V'), (0x10836, 'X'), (0x10837, 'V'), ] def _seg_54(): return [ (0x10839, 'X'), (0x1083C, 'V'), (0x1083D, 'X'), (0x1083F, 'V'), (0x10856, 'X'), (0x10857, 'V'), (0x1089F, 'X'), (0x108A7, 'V'), (0x108B0, 'X'), (0x108E0, 'V'), (0x108F3, 'X'), (0x108F4, 'V'), (0x108F6, 'X'), (0x108FB, 'V'), (0x1091C, 'X'), (0x1091F, 'V'), (0x1093A, 'X'), (0x1093F, 'V'), (0x10940, 'X'), (0x10980, 'V'), (0x109B8, 'X'), (0x109BC, 'V'), (0x109D0, 'X'), (0x109D2, 'V'), (0x10A04, 'X'), (0x10A05, 'V'), (0x10A07, 'X'), (0x10A0C, 'V'), (0x10A14, 'X'), (0x10A15, 'V'), (0x10A18, 'X'), (0x10A19, 'V'), (0x10A36, 'X'), (0x10A38, 'V'), (0x10A3B, 'X'), (0x10A3F, 'V'), (0x10A49, 'X'), (0x10A50, 'V'), (0x10A59, 'X'), (0x10A60, 'V'), (0x10AA0, 'X'), (0x10AC0, 'V'), (0x10AE7, 'X'), (0x10AEB, 'V'), (0x10AF7, 'X'), (0x10B00, 'V'), (0x10B36, 'X'), (0x10B39, 'V'), (0x10B56, 'X'), (0x10B58, 'V'), (0x10B73, 'X'), (0x10B78, 'V'), (0x10B92, 'X'), (0x10B99, 'V'), (0x10B9D, 'X'), (0x10BA9, 'V'), (0x10BB0, 'X'), (0x10C00, 'V'), (0x10C49, 'X'), (0x10C80, 'M', u'𐳀'), (0x10C81, 'M', u'𐳁'), (0x10C82, 'M', u'𐳂'), (0x10C83, 'M', u'𐳃'), (0x10C84, 'M', u'𐳄'), (0x10C85, 'M', u'𐳅'), (0x10C86, 'M', u'𐳆'), (0x10C87, 'M', u'𐳇'), (0x10C88, 'M', u'𐳈'), (0x10C89, 'M', u'𐳉'), (0x10C8A, 'M', u'𐳊'), (0x10C8B, 'M', u'𐳋'), (0x10C8C, 'M', u'𐳌'), (0x10C8D, 'M', u'𐳍'), (0x10C8E, 'M', u'𐳎'), (0x10C8F, 'M', u'𐳏'), (0x10C90, 'M', u'𐳐'), (0x10C91, 'M', u'𐳑'), (0x10C92, 'M', u'𐳒'), (0x10C93, 'M', u'𐳓'), (0x10C94, 'M', u'𐳔'), (0x10C95, 'M', u'𐳕'), (0x10C96, 'M', u'𐳖'), (0x10C97, 'M', u'𐳗'), (0x10C98, 'M', u'𐳘'), (0x10C99, 'M', u'𐳙'), (0x10C9A, 'M', u'𐳚'), (0x10C9B, 'M', u'𐳛'), (0x10C9C, 'M', u'𐳜'), (0x10C9D, 'M', u'𐳝'), (0x10C9E, 'M', u'𐳞'), (0x10C9F, 'M', u'𐳟'), (0x10CA0, 'M', u'𐳠'), (0x10CA1, 'M', u'𐳡'), (0x10CA2, 'M', u'𐳢'), (0x10CA3, 'M', u'𐳣'), (0x10CA4, 'M', u'𐳤'), (0x10CA5, 'M', u'𐳥'), (0x10CA6, 'M', u'𐳦'), (0x10CA7, 'M', u'𐳧'), (0x10CA8, 'M', u'𐳨'), ] def _seg_55(): return [ (0x10CA9, 'M', u'𐳩'), (0x10CAA, 'M', u'𐳪'), (0x10CAB, 'M', u'𐳫'), (0x10CAC, 'M', u'𐳬'), (0x10CAD, 'M', u'𐳭'), (0x10CAE, 'M', u'𐳮'), (0x10CAF, 'M', u'𐳯'), (0x10CB0, 'M', u'𐳰'), (0x10CB1, 'M', u'𐳱'), (0x10CB2, 'M', u'𐳲'), (0x10CB3, 'X'), (0x10CC0, 'V'), (0x10CF3, 'X'), (0x10CFA, 'V'), (0x10D28, 'X'), (0x10D30, 'V'), (0x10D3A, 'X'), (0x10E60, 'V'), (0x10E7F, 'X'), (0x10F00, 'V'), (0x10F28, 'X'), (0x10F30, 'V'), (0x10F5A, 'X'), (0x11000, 'V'), (0x1104E, 'X'), (0x11052, 'V'), (0x11070, 'X'), (0x1107F, 'V'), (0x110BD, 'X'), (0x110BE, 'V'), (0x110C2, 'X'), (0x110D0, 'V'), (0x110E9, 'X'), (0x110F0, 'V'), (0x110FA, 'X'), (0x11100, 'V'), (0x11135, 'X'), (0x11136, 'V'), (0x11147, 'X'), (0x11150, 'V'), (0x11177, 'X'), (0x11180, 'V'), (0x111CE, 'X'), (0x111D0, 'V'), (0x111E0, 'X'), (0x111E1, 'V'), (0x111F5, 'X'), (0x11200, 'V'), (0x11212, 'X'), (0x11213, 'V'), (0x1123F, 'X'), (0x11280, 'V'), (0x11287, 'X'), (0x11288, 'V'), (0x11289, 'X'), (0x1128A, 'V'), (0x1128E, 'X'), (0x1128F, 'V'), (0x1129E, 'X'), (0x1129F, 'V'), (0x112AA, 'X'), (0x112B0, 'V'), (0x112EB, 'X'), (0x112F0, 'V'), (0x112FA, 'X'), (0x11300, 'V'), (0x11304, 'X'), (0x11305, 'V'), (0x1130D, 'X'), (0x1130F, 'V'), (0x11311, 'X'), (0x11313, 'V'), (0x11329, 'X'), (0x1132A, 'V'), (0x11331, 'X'), (0x11332, 'V'), (0x11334, 'X'), (0x11335, 'V'), (0x1133A, 'X'), (0x1133B, 'V'), (0x11345, 'X'), (0x11347, 'V'), (0x11349, 'X'), (0x1134B, 'V'), (0x1134E, 'X'), (0x11350, 'V'), (0x11351, 'X'), (0x11357, 'V'), (0x11358, 'X'), (0x1135D, 'V'), (0x11364, 'X'), (0x11366, 'V'), (0x1136D, 'X'), (0x11370, 'V'), (0x11375, 'X'), (0x11400, 'V'), (0x1145A, 'X'), (0x1145B, 'V'), (0x1145C, 'X'), (0x1145D, 'V'), ] def _seg_56(): return [ (0x1145F, 'X'), (0x11480, 'V'), (0x114C8, 'X'), (0x114D0, 'V'), (0x114DA, 'X'), (0x11580, 'V'), (0x115B6, 'X'), (0x115B8, 'V'), (0x115DE, 'X'), (0x11600, 'V'), (0x11645, 'X'), (0x11650, 'V'), (0x1165A, 'X'), (0x11660, 'V'), (0x1166D, 'X'), (0x11680, 'V'), (0x116B8, 'X'), (0x116C0, 'V'), (0x116CA, 'X'), (0x11700, 'V'), (0x1171B, 'X'), (0x1171D, 'V'), (0x1172C, 'X'), (0x11730, 'V'), (0x11740, 'X'), (0x11800, 'V'), (0x1183C, 'X'), (0x118A0, 'M', u'𑣀'), (0x118A1, 'M', u'𑣁'), (0x118A2, 'M', u'𑣂'), (0x118A3, 'M', u'𑣃'), (0x118A4, 'M', u'𑣄'), (0x118A5, 'M', u'𑣅'), (0x118A6, 'M', u'𑣆'), (0x118A7, 'M', u'𑣇'), (0x118A8, 'M', u'𑣈'), (0x118A9, 'M', u'𑣉'), (0x118AA, 'M', u'𑣊'), (0x118AB, 'M', u'𑣋'), (0x118AC, 'M', u'𑣌'), (0x118AD, 'M', u'𑣍'), (0x118AE, 'M', u'𑣎'), (0x118AF, 'M', u'𑣏'), (0x118B0, 'M', u'𑣐'), (0x118B1, 'M', u'𑣑'), (0x118B2, 'M', u'𑣒'), (0x118B3, 'M', u'𑣓'), (0x118B4, 'M', u'𑣔'), (0x118B5, 'M', u'𑣕'), (0x118B6, 'M', u'𑣖'), (0x118B7, 'M', u'𑣗'), (0x118B8, 'M', u'𑣘'), (0x118B9, 'M', u'𑣙'), (0x118BA, 'M', u'𑣚'), (0x118BB, 'M', u'𑣛'), (0x118BC, 'M', u'𑣜'), (0x118BD, 'M', u'𑣝'), (0x118BE, 'M', u'𑣞'), (0x118BF, 'M', u'𑣟'), (0x118C0, 'V'), (0x118F3, 'X'), (0x118FF, 'V'), (0x11900, 'X'), (0x11A00, 'V'), (0x11A48, 'X'), (0x11A50, 'V'), (0x11A84, 'X'), (0x11A86, 'V'), (0x11AA3, 'X'), (0x11AC0, 'V'), (0x11AF9, 'X'), (0x11C00, 'V'), (0x11C09, 'X'), (0x11C0A, 'V'), (0x11C37, 'X'), (0x11C38, 'V'), (0x11C46, 'X'), (0x11C50, 'V'), (0x11C6D, 'X'), (0x11C70, 'V'), (0x11C90, 'X'), (0x11C92, 'V'), (0x11CA8, 'X'), (0x11CA9, 'V'), (0x11CB7, 'X'), (0x11D00, 'V'), (0x11D07, 'X'), (0x11D08, 'V'), (0x11D0A, 'X'), (0x11D0B, 'V'), (0x11D37, 'X'), (0x11D3A, 'V'), (0x11D3B, 'X'), (0x11D3C, 'V'), (0x11D3E, 'X'), (0x11D3F, 'V'), (0x11D48, 'X'), (0x11D50, 'V'), (0x11D5A, 'X'), (0x11D60, 'V'), ] def _seg_57(): return [ (0x11D66, 'X'), (0x11D67, 'V'), (0x11D69, 'X'), (0x11D6A, 'V'), (0x11D8F, 'X'), (0x11D90, 'V'), (0x11D92, 'X'), (0x11D93, 'V'), (0x11D99, 'X'), (0x11DA0, 'V'), (0x11DAA, 'X'), (0x11EE0, 'V'), (0x11EF9, 'X'), (0x12000, 'V'), (0x1239A, 'X'), (0x12400, 'V'), (0x1246F, 'X'), (0x12470, 'V'), (0x12475, 'X'), (0x12480, 'V'), (0x12544, 'X'), (0x13000, 'V'), (0x1342F, 'X'), (0x14400, 'V'), (0x14647, 'X'), (0x16800, 'V'), (0x16A39, 'X'), (0x16A40, 'V'), (0x16A5F, 'X'), (0x16A60, 'V'), (0x16A6A, 'X'), (0x16A6E, 'V'), (0x16A70, 'X'), (0x16AD0, 'V'), (0x16AEE, 'X'), (0x16AF0, 'V'), (0x16AF6, 'X'), (0x16B00, 'V'), (0x16B46, 'X'), (0x16B50, 'V'), (0x16B5A, 'X'), (0x16B5B, 'V'), (0x16B62, 'X'), (0x16B63, 'V'), (0x16B78, 'X'), (0x16B7D, 'V'), (0x16B90, 'X'), (0x16E60, 'V'), (0x16E9B, 'X'), (0x16F00, 'V'), (0x16F45, 'X'), (0x16F50, 'V'), (0x16F7F, 'X'), (0x16F8F, 'V'), (0x16FA0, 'X'), (0x16FE0, 'V'), (0x16FE2, 'X'), (0x17000, 'V'), (0x187F2, 'X'), (0x18800, 'V'), (0x18AF3, 'X'), (0x1B000, 'V'), (0x1B11F, 'X'), (0x1B170, 'V'), (0x1B2FC, 'X'), (0x1BC00, 'V'), (0x1BC6B, 'X'), (0x1BC70, 'V'), (0x1BC7D, 'X'), (0x1BC80, 'V'), (0x1BC89, 'X'), (0x1BC90, 'V'), (0x1BC9A, 'X'), (0x1BC9C, 'V'), (0x1BCA0, 'I'), (0x1BCA4, 'X'), (0x1D000, 'V'), (0x1D0F6, 'X'), (0x1D100, 'V'), (0x1D127, 'X'), (0x1D129, 'V'), (0x1D15E, 'M', u'𝅗𝅥'), (0x1D15F, 'M', u'𝅘𝅥'), (0x1D160, 'M', u'𝅘𝅥𝅮'), (0x1D161, 'M', u'𝅘𝅥𝅯'), (0x1D162, 'M', u'𝅘𝅥𝅰'), (0x1D163, 'M', u'𝅘𝅥𝅱'), (0x1D164, 'M', u'𝅘𝅥𝅲'), (0x1D165, 'V'), (0x1D173, 'X'), (0x1D17B, 'V'), (0x1D1BB, 'M', u'𝆹𝅥'), (0x1D1BC, 'M', u'𝆺𝅥'), (0x1D1BD, 'M', u'𝆹𝅥𝅮'), (0x1D1BE, 'M', u'𝆺𝅥𝅮'), (0x1D1BF, 'M', u'𝆹𝅥𝅯'), (0x1D1C0, 'M', u'𝆺𝅥𝅯'), (0x1D1C1, 'V'), (0x1D1E9, 'X'), (0x1D200, 'V'), ] def _seg_58(): return [ (0x1D246, 'X'), (0x1D2E0, 'V'), (0x1D2F4, 'X'), (0x1D300, 'V'), (0x1D357, 'X'), (0x1D360, 'V'), (0x1D379, 'X'), (0x1D400, 'M', u'a'), (0x1D401, 'M', u'b'), (0x1D402, 'M', u'c'), (0x1D403, 'M', u'd'), (0x1D404, 'M', u'e'), (0x1D405, 'M', u'f'), (0x1D406, 'M', u'g'), (0x1D407, 'M', u'h'), (0x1D408, 'M', u'i'), (0x1D409, 'M', u'j'), (0x1D40A, 'M', u'k'), (0x1D40B, 'M', u'l'), (0x1D40C, 'M', u'm'), (0x1D40D, 'M', u'n'), (0x1D40E, 'M', u'o'), (0x1D40F, 'M', u'p'), (0x1D410, 'M', u'q'), (0x1D411, 'M', u'r'), (0x1D412, 'M', u's'), (0x1D413, 'M', u't'), (0x1D414, 'M', u'u'), (0x1D415, 'M', u'v'), (0x1D416, 'M', u'w'), (0x1D417, 'M', u'x'), (0x1D418, 'M', u'y'), (0x1D419, 'M', u'z'), (0x1D41A, 'M', u'a'), (0x1D41B, 'M', u'b'), (0x1D41C, 'M', u'c'), (0x1D41D, 'M', u'd'), (0x1D41E, 'M', u'e'), (0x1D41F, 'M', u'f'), (0x1D420, 'M', u'g'), (0x1D421, 'M', u'h'), (0x1D422, 'M', u'i'), (0x1D423, 'M', u'j'), (0x1D424, 'M', u'k'), (0x1D425, 'M', u'l'), (0x1D426, 'M', u'm'), (0x1D427, 'M', u'n'), (0x1D428, 'M', u'o'), (0x1D429, 'M', u'p'), (0x1D42A, 'M', u'q'), (0x1D42B, 'M', u'r'), (0x1D42C, 'M', u's'), (0x1D42D, 'M', u't'), (0x1D42E, 'M', u'u'), (0x1D42F, 'M', u'v'), (0x1D430, 'M', u'w'), (0x1D431, 'M', u'x'), (0x1D432, 'M', u'y'), (0x1D433, 'M', u'z'), (0x1D434, 'M', u'a'), (0x1D435, 'M', u'b'), (0x1D436, 'M', u'c'), (0x1D437, 'M', u'd'), (0x1D438, 'M', u'e'), (0x1D439, 'M', u'f'), (0x1D43A, 'M', u'g'), (0x1D43B, 'M', u'h'), (0x1D43C, 'M', u'i'), (0x1D43D, 'M', u'j'), (0x1D43E, 'M', u'k'), (0x1D43F, 'M', u'l'), (0x1D440, 'M', u'm'), (0x1D441, 'M', u'n'), (0x1D442, 'M', u'o'), (0x1D443, 'M', u'p'), (0x1D444, 'M', u'q'), (0x1D445, 'M', u'r'), (0x1D446, 'M', u's'), (0x1D447, 'M', u't'), (0x1D448, 'M', u'u'), (0x1D449, 'M', u'v'), (0x1D44A, 'M', u'w'), (0x1D44B, 'M', u'x'), (0x1D44C, 'M', u'y'), (0x1D44D, 'M', u'z'), (0x1D44E, 'M', u'a'), (0x1D44F, 'M', u'b'), (0x1D450, 'M', u'c'), (0x1D451, 'M', u'd'), (0x1D452, 'M', u'e'), (0x1D453, 'M', u'f'), (0x1D454, 'M', u'g'), (0x1D455, 'X'), (0x1D456, 'M', u'i'), (0x1D457, 'M', u'j'), (0x1D458, 'M', u'k'), (0x1D459, 'M', u'l'), (0x1D45A, 'M', u'm'), (0x1D45B, 'M', u'n'), (0x1D45C, 'M', u'o'), ] def _seg_59(): return [ (0x1D45D, 'M', u'p'), (0x1D45E, 'M', u'q'), (0x1D45F, 'M', u'r'), (0x1D460, 'M', u's'), (0x1D461, 'M', u't'), (0x1D462, 'M', u'u'), (0x1D463, 'M', u'v'), (0x1D464, 'M', u'w'), (0x1D465, 'M', u'x'), (0x1D466, 'M', u'y'), (0x1D467, 'M', u'z'), (0x1D468, 'M', u'a'), (0x1D469, 'M', u'b'), (0x1D46A, 'M', u'c'), (0x1D46B, 'M', u'd'), (0x1D46C, 'M', u'e'), (0x1D46D, 'M', u'f'), (0x1D46E, 'M', u'g'), (0x1D46F, 'M', u'h'), (0x1D470, 'M', u'i'), (0x1D471, 'M', u'j'), (0x1D472, 'M', u'k'), (0x1D473, 'M', u'l'), (0x1D474, 'M', u'm'), (0x1D475, 'M', u'n'), (0x1D476, 'M', u'o'), (0x1D477, 'M', u'p'), (0x1D478, 'M', u'q'), (0x1D479, 'M', u'r'), (0x1D47A, 'M', u's'), (0x1D47B, 'M', u't'), (0x1D47C, 'M', u'u'), (0x1D47D, 'M', u'v'), (0x1D47E, 'M', u'w'), (0x1D47F, 'M', u'x'), (0x1D480, 'M', u'y'), (0x1D481, 'M', u'z'), (0x1D482, 'M', u'a'), (0x1D483, 'M', u'b'), (0x1D484, 'M', u'c'), (0x1D485, 'M', u'd'), (0x1D486, 'M', u'e'), (0x1D487, 'M', u'f'), (0x1D488, 'M', u'g'), (0x1D489, 'M', u'h'), (0x1D48A, 'M', u'i'), (0x1D48B, 'M', u'j'), (0x1D48C, 'M', u'k'), (0x1D48D, 'M', u'l'), (0x1D48E, 'M', u'm'), (0x1D48F, 'M', u'n'), (0x1D490, 'M', u'o'), (0x1D491, 'M', u'p'), (0x1D492, 'M', u'q'), (0x1D493, 'M', u'r'), (0x1D494, 'M', u's'), (0x1D495, 'M', u't'), (0x1D496, 'M', u'u'), (0x1D497, 'M', u'v'), (0x1D498, 'M', u'w'), (0x1D499, 'M', u'x'), (0x1D49A, 'M', u'y'), (0x1D49B, 'M', u'z'), (0x1D49C, 'M', u'a'), (0x1D49D, 'X'), (0x1D49E, 'M', u'c'), (0x1D49F, 'M', u'd'), (0x1D4A0, 'X'), (0x1D4A2, 'M', u'g'), (0x1D4A3, 'X'), (0x1D4A5, 'M', u'j'), (0x1D4A6, 'M', u'k'), (0x1D4A7, 'X'), (0x1D4A9, 'M', u'n'), (0x1D4AA, 'M', u'o'), (0x1D4AB, 'M', u'p'), (0x1D4AC, 'M', u'q'), (0x1D4AD, 'X'), (0x1D4AE, 'M', u's'), (0x1D4AF, 'M', u't'), (0x1D4B0, 'M', u'u'), (0x1D4B1, 'M', u'v'), (0x1D4B2, 'M', u'w'), (0x1D4B3, 'M', u'x'), (0x1D4B4, 'M', u'y'), (0x1D4B5, 'M', u'z'), (0x1D4B6, 'M', u'a'), (0x1D4B7, 'M', u'b'), (0x1D4B8, 'M', u'c'), (0x1D4B9, 'M', u'd'), (0x1D4BA, 'X'), (0x1D4BB, 'M', u'f'), (0x1D4BC, 'X'), (0x1D4BD, 'M', u'h'), (0x1D4BE, 'M', u'i'), (0x1D4BF, 'M', u'j'), (0x1D4C0, 'M', u'k'), (0x1D4C1, 'M', u'l'), (0x1D4C2, 'M', u'm'), (0x1D4C3, 'M', u'n'), ] def _seg_60(): return [ (0x1D4C4, 'X'), (0x1D4C5, 'M', u'p'), (0x1D4C6, 'M', u'q'), (0x1D4C7, 'M', u'r'), (0x1D4C8, 'M', u's'), (0x1D4C9, 'M', u't'), (0x1D4CA, 'M', u'u'), (0x1D4CB, 'M', u'v'), (0x1D4CC, 'M', u'w'), (0x1D4CD, 'M', u'x'), (0x1D4CE, 'M', u'y'), (0x1D4CF, 'M', u'z'), (0x1D4D0, 'M', u'a'), (0x1D4D1, 'M', u'b'), (0x1D4D2, 'M', u'c'), (0x1D4D3, 'M', u'd'), (0x1D4D4, 'M', u'e'), (0x1D4D5, 'M', u'f'), (0x1D4D6, 'M', u'g'), (0x1D4D7, 'M', u'h'), (0x1D4D8, 'M', u'i'), (0x1D4D9, 'M', u'j'), (0x1D4DA, 'M', u'k'), (0x1D4DB, 'M', u'l'), (0x1D4DC, 'M', u'm'), (0x1D4DD, 'M', u'n'), (0x1D4DE, 'M', u'o'), (0x1D4DF, 'M', u'p'), (0x1D4E0, 'M', u'q'), (0x1D4E1, 'M', u'r'), (0x1D4E2, 'M', u's'), (0x1D4E3, 'M', u't'), (0x1D4E4, 'M', u'u'), (0x1D4E5, 'M', u'v'), (0x1D4E6, 'M', u'w'), (0x1D4E7, 'M', u'x'), (0x1D4E8, 'M', u'y'), (0x1D4E9, 'M', u'z'), (0x1D4EA, 'M', u'a'), (0x1D4EB, 'M', u'b'), (0x1D4EC, 'M', u'c'), (0x1D4ED, 'M', u'd'), (0x1D4EE, 'M', u'e'), (0x1D4EF, 'M', u'f'), (0x1D4F0, 'M', u'g'), (0x1D4F1, 'M', u'h'), (0x1D4F2, 'M', u'i'), (0x1D4F3, 'M', u'j'), (0x1D4F4, 'M', u'k'), (0x1D4F5, 'M', u'l'), (0x1D4F6, 'M', u'm'), (0x1D4F7, 'M', u'n'), (0x1D4F8, 'M', u'o'), (0x1D4F9, 'M', u'p'), (0x1D4FA, 'M', u'q'), (0x1D4FB, 'M', u'r'), (0x1D4FC, 'M', u's'), (0x1D4FD, 'M', u't'), (0x1D4FE, 'M', u'u'), (0x1D4FF, 'M', u'v'), (0x1D500, 'M', u'w'), (0x1D501, 'M', u'x'), (0x1D502, 'M', u'y'), (0x1D503, 'M', u'z'), (0x1D504, 'M', u'a'), (0x1D505, 'M', u'b'), (0x1D506, 'X'), (0x1D507, 'M', u'd'), (0x1D508, 'M', u'e'), (0x1D509, 'M', u'f'), (0x1D50A, 'M', u'g'), (0x1D50B, 'X'), (0x1D50D, 'M', u'j'), (0x1D50E, 'M', u'k'), (0x1D50F, 'M', u'l'), (0x1D510, 'M', u'm'), (0x1D511, 'M', u'n'), (0x1D512, 'M', u'o'), (0x1D513, 'M', u'p'), (0x1D514, 'M', u'q'), (0x1D515, 'X'), (0x1D516, 'M', u's'), (0x1D517, 'M', u't'), (0x1D518, 'M', u'u'), (0x1D519, 'M', u'v'), (0x1D51A, 'M', u'w'), (0x1D51B, 'M', u'x'), (0x1D51C, 'M', u'y'), (0x1D51D, 'X'), (0x1D51E, 'M', u'a'), (0x1D51F, 'M', u'b'), (0x1D520, 'M', u'c'), (0x1D521, 'M', u'd'), (0x1D522, 'M', u'e'), (0x1D523, 'M', u'f'), (0x1D524, 'M', u'g'), (0x1D525, 'M', u'h'), (0x1D526, 'M', u'i'), (0x1D527, 'M', u'j'), (0x1D528, 'M', u'k'), ] def _seg_61(): return [ (0x1D529, 'M', u'l'), (0x1D52A, 'M', u'm'), (0x1D52B, 'M', u'n'), (0x1D52C, 'M', u'o'), (0x1D52D, 'M', u'p'), (0x1D52E, 'M', u'q'), (0x1D52F, 'M', u'r'), (0x1D530, 'M', u's'), (0x1D531, 'M', u't'), (0x1D532, 'M', u'u'), (0x1D533, 'M', u'v'), (0x1D534, 'M', u'w'), (0x1D535, 'M', u'x'), (0x1D536, 'M', u'y'), (0x1D537, 'M', u'z'), (0x1D538, 'M', u'a'), (0x1D539, 'M', u'b'), (0x1D53A, 'X'), (0x1D53B, 'M', u'd'), (0x1D53C, 'M', u'e'), (0x1D53D, 'M', u'f'), (0x1D53E, 'M', u'g'), (0x1D53F, 'X'), (0x1D540, 'M', u'i'), (0x1D541, 'M', u'j'), (0x1D542, 'M', u'k'), (0x1D543, 'M', u'l'), (0x1D544, 'M', u'm'), (0x1D545, 'X'), (0x1D546, 'M', u'o'), (0x1D547, 'X'), (0x1D54A, 'M', u's'), (0x1D54B, 'M', u't'), (0x1D54C, 'M', u'u'), (0x1D54D, 'M', u'v'), (0x1D54E, 'M', u'w'), (0x1D54F, 'M', u'x'), (0x1D550, 'M', u'y'), (0x1D551, 'X'), (0x1D552, 'M', u'a'), (0x1D553, 'M', u'b'), (0x1D554, 'M', u'c'), (0x1D555, 'M', u'd'), (0x1D556, 'M', u'e'), (0x1D557, 'M', u'f'), (0x1D558, 'M', u'g'), (0x1D559, 'M', u'h'), (0x1D55A, 'M', u'i'), (0x1D55B, 'M', u'j'), (0x1D55C, 'M', u'k'), (0x1D55D, 'M', u'l'), (0x1D55E, 'M', u'm'), (0x1D55F, 'M', u'n'), (0x1D560, 'M', u'o'), (0x1D561, 'M', u'p'), (0x1D562, 'M', u'q'), (0x1D563, 'M', u'r'), (0x1D564, 'M', u's'), (0x1D565, 'M', u't'), (0x1D566, 'M', u'u'), (0x1D567, 'M', u'v'), (0x1D568, 'M', u'w'), (0x1D569, 'M', u'x'), (0x1D56A, 'M', u'y'), (0x1D56B, 'M', u'z'), (0x1D56C, 'M', u'a'), (0x1D56D, 'M', u'b'), (0x1D56E, 'M', u'c'), (0x1D56F, 'M', u'd'), (0x1D570, 'M', u'e'), (0x1D571, 'M', u'f'), (0x1D572, 'M', u'g'), (0x1D573, 'M', u'h'), (0x1D574, 'M', u'i'), (0x1D575, 'M', u'j'), (0x1D576, 'M', u'k'), (0x1D577, 'M', u'l'), (0x1D578, 'M', u'm'), (0x1D579, 'M', u'n'), (0x1D57A, 'M', u'o'), (0x1D57B, 'M', u'p'), (0x1D57C, 'M', u'q'), (0x1D57D, 'M', u'r'), (0x1D57E, 'M', u's'), (0x1D57F, 'M', u't'), (0x1D580, 'M', u'u'), (0x1D581, 'M', u'v'), (0x1D582, 'M', u'w'), (0x1D583, 'M', u'x'), (0x1D584, 'M', u'y'), (0x1D585, 'M', u'z'), (0x1D586, 'M', u'a'), (0x1D587, 'M', u'b'), (0x1D588, 'M', u'c'), (0x1D589, 'M', u'd'), (0x1D58A, 'M', u'e'), (0x1D58B, 'M', u'f'), (0x1D58C, 'M', u'g'), (0x1D58D, 'M', u'h'), (0x1D58E, 'M', u'i'), ] def _seg_62(): return [ (0x1D58F, 'M', u'j'), (0x1D590, 'M', u'k'), (0x1D591, 'M', u'l'), (0x1D592, 'M', u'm'), (0x1D593, 'M', u'n'), (0x1D594, 'M', u'o'), (0x1D595, 'M', u'p'), (0x1D596, 'M', u'q'), (0x1D597, 'M', u'r'), (0x1D598, 'M', u's'), (0x1D599, 'M', u't'), (0x1D59A, 'M', u'u'), (0x1D59B, 'M', u'v'), (0x1D59C, 'M', u'w'), (0x1D59D, 'M', u'x'), (0x1D59E, 'M', u'y'), (0x1D59F, 'M', u'z'), (0x1D5A0, 'M', u'a'), (0x1D5A1, 'M', u'b'), (0x1D5A2, 'M', u'c'), (0x1D5A3, 'M', u'd'), (0x1D5A4, 'M', u'e'), (0x1D5A5, 'M', u'f'), (0x1D5A6, 'M', u'g'), (0x1D5A7, 'M', u'h'), (0x1D5A8, 'M', u'i'), (0x1D5A9, 'M', u'j'), (0x1D5AA, 'M', u'k'), (0x1D5AB, 'M', u'l'), (0x1D5AC, 'M', u'm'), (0x1D5AD, 'M', u'n'), (0x1D5AE, 'M', u'o'), (0x1D5AF, 'M', u'p'), (0x1D5B0, 'M', u'q'), (0x1D5B1, 'M', u'r'), (0x1D5B2, 'M', u's'), (0x1D5B3, 'M', u't'), (0x1D5B4, 'M', u'u'), (0x1D5B5, 'M', u'v'), (0x1D5B6, 'M', u'w'), (0x1D5B7, 'M', u'x'), (0x1D5B8, 'M', u'y'), (0x1D5B9, 'M', u'z'), (0x1D5BA, 'M', u'a'), (0x1D5BB, 'M', u'b'), (0x1D5BC, 'M', u'c'), (0x1D5BD, 'M', u'd'), (0x1D5BE, 'M', u'e'), (0x1D5BF, 'M', u'f'), (0x1D5C0, 'M', u'g'), (0x1D5C1, 'M', u'h'), (0x1D5C2, 'M', u'i'), (0x1D5C3, 'M', u'j'), (0x1D5C4, 'M', u'k'), (0x1D5C5, 'M', u'l'), (0x1D5C6, 'M', u'm'), (0x1D5C7, 'M', u'n'), (0x1D5C8, 'M', u'o'), (0x1D5C9, 'M', u'p'), (0x1D5CA, 'M', u'q'), (0x1D5CB, 'M', u'r'), (0x1D5CC, 'M', u's'), (0x1D5CD, 'M', u't'), (0x1D5CE, 'M', u'u'), (0x1D5CF, 'M', u'v'), (0x1D5D0, 'M', u'w'), (0x1D5D1, 'M', u'x'), (0x1D5D2, 'M', u'y'), (0x1D5D3, 'M', u'z'), (0x1D5D4, 'M', u'a'), (0x1D5D5, 'M', u'b'), (0x1D5D6, 'M', u'c'), (0x1D5D7, 'M', u'd'), (0x1D5D8, 'M', u'e'), (0x1D5D9, 'M', u'f'), (0x1D5DA, 'M', u'g'), (0x1D5DB, 'M', u'h'), (0x1D5DC, 'M', u'i'), (0x1D5DD, 'M', u'j'), (0x1D5DE, 'M', u'k'), (0x1D5DF, 'M', u'l'), (0x1D5E0, 'M', u'm'), (0x1D5E1, 'M', u'n'), (0x1D5E2, 'M', u'o'), (0x1D5E3, 'M', u'p'), (0x1D5E4, 'M', u'q'), (0x1D5E5, 'M', u'r'), (0x1D5E6, 'M', u's'), (0x1D5E7, 'M', u't'), (0x1D5E8, 'M', u'u'), (0x1D5E9, 'M', u'v'), (0x1D5EA, 'M', u'w'), (0x1D5EB, 'M', u'x'), (0x1D5EC, 'M', u'y'), (0x1D5ED, 'M', u'z'), (0x1D5EE, 'M', u'a'), (0x1D5EF, 'M', u'b'), (0x1D5F0, 'M', u'c'), (0x1D5F1, 'M', u'd'), (0x1D5F2, 'M', u'e'), ] def _seg_63(): return [ (0x1D5F3, 'M', u'f'), (0x1D5F4, 'M', u'g'), (0x1D5F5, 'M', u'h'), (0x1D5F6, 'M', u'i'), (0x1D5F7, 'M', u'j'), (0x1D5F8, 'M', u'k'), (0x1D5F9, 'M', u'l'), (0x1D5FA, 'M', u'm'), (0x1D5FB, 'M', u'n'), (0x1D5FC, 'M', u'o'), (0x1D5FD, 'M', u'p'), (0x1D5FE, 'M', u'q'), (0x1D5FF, 'M', u'r'), (0x1D600, 'M', u's'), (0x1D601, 'M', u't'), (0x1D602, 'M', u'u'), (0x1D603, 'M', u'v'), (0x1D604, 'M', u'w'), (0x1D605, 'M', u'x'), (0x1D606, 'M', u'y'), (0x1D607, 'M', u'z'), (0x1D608, 'M', u'a'), (0x1D609, 'M', u'b'), (0x1D60A, 'M', u'c'), (0x1D60B, 'M', u'd'), (0x1D60C, 'M', u'e'), (0x1D60D, 'M', u'f'), (0x1D60E, 'M', u'g'), (0x1D60F, 'M', u'h'), (0x1D610, 'M', u'i'), (0x1D611, 'M', u'j'), (0x1D612, 'M', u'k'), (0x1D613, 'M', u'l'), (0x1D614, 'M', u'm'), (0x1D615, 'M', u'n'), (0x1D616, 'M', u'o'), (0x1D617, 'M', u'p'), (0x1D618, 'M', u'q'), (0x1D619, 'M', u'r'), (0x1D61A, 'M', u's'), (0x1D61B, 'M', u't'), (0x1D61C, 'M', u'u'), (0x1D61D, 'M', u'v'), (0x1D61E, 'M', u'w'), (0x1D61F, 'M', u'x'), (0x1D620, 'M', u'y'), (0x1D621, 'M', u'z'), (0x1D622, 'M', u'a'), (0x1D623, 'M', u'b'), (0x1D624, 'M', u'c'), (0x1D625, 'M', u'd'), (0x1D626, 'M', u'e'), (0x1D627, 'M', u'f'), (0x1D628, 'M', u'g'), (0x1D629, 'M', u'h'), (0x1D62A, 'M', u'i'), (0x1D62B, 'M', u'j'), (0x1D62C, 'M', u'k'), (0x1D62D, 'M', u'l'), (0x1D62E, 'M', u'm'), (0x1D62F, 'M', u'n'), (0x1D630, 'M', u'o'), (0x1D631, 'M', u'p'), (0x1D632, 'M', u'q'), (0x1D633, 'M', u'r'), (0x1D634, 'M', u's'), (0x1D635, 'M', u't'), (0x1D636, 'M', u'u'), (0x1D637, 'M', u'v'), (0x1D638, 'M', u'w'), (0x1D639, 'M', u'x'), (0x1D63A, 'M', u'y'), (0x1D63B, 'M', u'z'), (0x1D63C, 'M', u'a'), (0x1D63D, 'M', u'b'), (0x1D63E, 'M', u'c'), (0x1D63F, 'M', u'd'), (0x1D640, 'M', u'e'), (0x1D641, 'M', u'f'), (0x1D642, 'M', u'g'), (0x1D643, 'M', u'h'), (0x1D644, 'M', u'i'), (0x1D645, 'M', u'j'), (0x1D646, 'M', u'k'), (0x1D647, 'M', u'l'), (0x1D648, 'M', u'm'), (0x1D649, 'M', u'n'), (0x1D64A, 'M', u'o'), (0x1D64B, 'M', u'p'), (0x1D64C, 'M', u'q'), (0x1D64D, 'M', u'r'), (0x1D64E, 'M', u's'), (0x1D64F, 'M', u't'), (0x1D650, 'M', u'u'), (0x1D651, 'M', u'v'), (0x1D652, 'M', u'w'), (0x1D653, 'M', u'x'), (0x1D654, 'M', u'y'), (0x1D655, 'M', u'z'), (0x1D656, 'M', u'a'), ] def _seg_64(): return [ (0x1D657, 'M', u'b'), (0x1D658, 'M', u'c'), (0x1D659, 'M', u'd'), (0x1D65A, 'M', u'e'), (0x1D65B, 'M', u'f'), (0x1D65C, 'M', u'g'), (0x1D65D, 'M', u'h'), (0x1D65E, 'M', u'i'), (0x1D65F, 'M', u'j'), (0x1D660, 'M', u'k'), (0x1D661, 'M', u'l'), (0x1D662, 'M', u'm'), (0x1D663, 'M', u'n'), (0x1D664, 'M', u'o'), (0x1D665, 'M', u'p'), (0x1D666, 'M', u'q'), (0x1D667, 'M', u'r'), (0x1D668, 'M', u's'), (0x1D669, 'M', u't'), (0x1D66A, 'M', u'u'), (0x1D66B, 'M', u'v'), (0x1D66C, 'M', u'w'), (0x1D66D, 'M', u'x'), (0x1D66E, 'M', u'y'), (0x1D66F, 'M', u'z'), (0x1D670, 'M', u'a'), (0x1D671, 'M', u'b'), (0x1D672, 'M', u'c'), (0x1D673, 'M', u'd'), (0x1D674, 'M', u'e'), (0x1D675, 'M', u'f'), (0x1D676, 'M', u'g'), (0x1D677, 'M', u'h'), (0x1D678, 'M', u'i'), (0x1D679, 'M', u'j'), (0x1D67A, 'M', u'k'), (0x1D67B, 'M', u'l'), (0x1D67C, 'M', u'm'), (0x1D67D, 'M', u'n'), (0x1D67E, 'M', u'o'), (0x1D67F, 'M', u'p'), (0x1D680, 'M', u'q'), (0x1D681, 'M', u'r'), (0x1D682, 'M', u's'), (0x1D683, 'M', u't'), (0x1D684, 'M', u'u'), (0x1D685, 'M', u'v'), (0x1D686, 'M', u'w'), (0x1D687, 'M', u'x'), (0x1D688, 'M', u'y'), (0x1D689, 'M', u'z'), (0x1D68A, 'M', u'a'), (0x1D68B, 'M', u'b'), (0x1D68C, 'M', u'c'), (0x1D68D, 'M', u'd'), (0x1D68E, 'M', u'e'), (0x1D68F, 'M', u'f'), (0x1D690, 'M', u'g'), (0x1D691, 'M', u'h'), (0x1D692, 'M', u'i'), (0x1D693, 'M', u'j'), (0x1D694, 'M', u'k'), (0x1D695, 'M', u'l'), (0x1D696, 'M', u'm'), (0x1D697, 'M', u'n'), (0x1D698, 'M', u'o'), (0x1D699, 'M', u'p'), (0x1D69A, 'M', u'q'), (0x1D69B, 'M', u'r'), (0x1D69C, 'M', u's'), (0x1D69D, 'M', u't'), (0x1D69E, 'M', u'u'), (0x1D69F, 'M', u'v'), (0x1D6A0, 'M', u'w'), (0x1D6A1, 'M', u'x'), (0x1D6A2, 'M', u'y'), (0x1D6A3, 'M', u'z'), (0x1D6A4, 'M', u'ı'), (0x1D6A5, 'M', u'ȷ'), (0x1D6A6, 'X'), (0x1D6A8, 'M', u'α'), (0x1D6A9, 'M', u'β'), (0x1D6AA, 'M', u'γ'), (0x1D6AB, 'M', u'δ'), (0x1D6AC, 'M', u'ε'), (0x1D6AD, 'M', u'ζ'), (0x1D6AE, 'M', u'η'), (0x1D6AF, 'M', u'θ'), (0x1D6B0, 'M', u'ι'), (0x1D6B1, 'M', u'κ'), (0x1D6B2, 'M', u'λ'), (0x1D6B3, 'M', u'μ'), (0x1D6B4, 'M', u'ν'), (0x1D6B5, 'M', u'ξ'), (0x1D6B6, 'M', u'ο'), (0x1D6B7, 'M', u'π'), (0x1D6B8, 'M', u'ρ'), (0x1D6B9, 'M', u'θ'), (0x1D6BA, 'M', u'σ'), (0x1D6BB, 'M', u'τ'), ] def _seg_65(): return [ (0x1D6BC, 'M', u'υ'), (0x1D6BD, 'M', u'φ'), (0x1D6BE, 'M', u'χ'), (0x1D6BF, 'M', u'ψ'), (0x1D6C0, 'M', u'ω'), (0x1D6C1, 'M', u'∇'), (0x1D6C2, 'M', u'α'), (0x1D6C3, 'M', u'β'), (0x1D6C4, 'M', u'γ'), (0x1D6C5, 'M', u'δ'), (0x1D6C6, 'M', u'ε'), (0x1D6C7, 'M', u'ζ'), (0x1D6C8, 'M', u'η'), (0x1D6C9, 'M', u'θ'), (0x1D6CA, 'M', u'ι'), (0x1D6CB, 'M', u'κ'), (0x1D6CC, 'M', u'λ'), (0x1D6CD, 'M', u'μ'), (0x1D6CE, 'M', u'ν'), (0x1D6CF, 'M', u'ξ'), (0x1D6D0, 'M', u'ο'), (0x1D6D1, 'M', u'π'), (0x1D6D2, 'M', u'ρ'), (0x1D6D3, 'M', u'σ'), (0x1D6D5, 'M', u'τ'), (0x1D6D6, 'M', u'υ'), (0x1D6D7, 'M', u'φ'), (0x1D6D8, 'M', u'χ'), (0x1D6D9, 'M', u'ψ'), (0x1D6DA, 'M', u'ω'), (0x1D6DB, 'M', u'∂'), (0x1D6DC, 'M', u'ε'), (0x1D6DD, 'M', u'θ'), (0x1D6DE, 'M', u'κ'), (0x1D6DF, 'M', u'φ'), (0x1D6E0, 'M', u'ρ'), (0x1D6E1, 'M', u'π'), (0x1D6E2, 'M', u'α'), (0x1D6E3, 'M', u'β'), (0x1D6E4, 'M', u'γ'), (0x1D6E5, 'M', u'δ'), (0x1D6E6, 'M', u'ε'), (0x1D6E7, 'M', u'ζ'), (0x1D6E8, 'M', u'η'), (0x1D6E9, 'M', u'θ'), (0x1D6EA, 'M', u'ι'), (0x1D6EB, 'M', u'κ'), (0x1D6EC, 'M', u'λ'), (0x1D6ED, 'M', u'μ'), (0x1D6EE, 'M', u'ν'), (0x1D6EF, 'M', u'ξ'), (0x1D6F0, 'M', u'ο'), (0x1D6F1, 'M', u'π'), (0x1D6F2, 'M', u'ρ'), (0x1D6F3, 'M', u'θ'), (0x1D6F4, 'M', u'σ'), (0x1D6F5, 'M', u'τ'), (0x1D6F6, 'M', u'υ'), (0x1D6F7, 'M', u'φ'), (0x1D6F8, 'M', u'χ'), (0x1D6F9, 'M', u'ψ'), (0x1D6FA, 'M', u'ω'), (0x1D6FB, 'M', u'∇'), (0x1D6FC, 'M', u'α'), (0x1D6FD, 'M', u'β'), (0x1D6FE, 'M', u'γ'), (0x1D6FF, 'M', u'δ'), (0x1D700, 'M', u'ε'), (0x1D701, 'M', u'ζ'), (0x1D702, 'M', u'η'), (0x1D703, 'M', u'θ'), (0x1D704, 'M', u'ι'), (0x1D705, 'M', u'κ'), (0x1D706, 'M', u'λ'), (0x1D707, 'M', u'μ'), (0x1D708, 'M', u'ν'), (0x1D709, 'M', u'ξ'), (0x1D70A, 'M', u'ο'), (0x1D70B, 'M', u'π'), (0x1D70C, 'M', u'ρ'), (0x1D70D, 'M', u'σ'), (0x1D70F, 'M', u'τ'), (0x1D710, 'M', u'υ'), (0x1D711, 'M', u'φ'), (0x1D712, 'M', u'χ'), (0x1D713, 'M', u'ψ'), (0x1D714, 'M', u'ω'), (0x1D715, 'M', u'∂'), (0x1D716, 'M', u'ε'), (0x1D717, 'M', u'θ'), (0x1D718, 'M', u'κ'), (0x1D719, 'M', u'φ'), (0x1D71A, 'M', u'ρ'), (0x1D71B, 'M', u'π'), (0x1D71C, 'M', u'α'), (0x1D71D, 'M', u'β'), (0x1D71E, 'M', u'γ'), (0x1D71F, 'M', u'δ'), (0x1D720, 'M', u'ε'), (0x1D721, 'M', u'ζ'), ] def _seg_66(): return [ (0x1D722, 'M', u'η'), (0x1D723, 'M', u'θ'), (0x1D724, 'M', u'ι'), (0x1D725, 'M', u'κ'), (0x1D726, 'M', u'λ'), (0x1D727, 'M', u'μ'), (0x1D728, 'M', u'ν'), (0x1D729, 'M', u'ξ'), (0x1D72A, 'M', u'ο'), (0x1D72B, 'M', u'π'), (0x1D72C, 'M', u'ρ'), (0x1D72D, 'M', u'θ'), (0x1D72E, 'M', u'σ'), (0x1D72F, 'M', u'τ'), (0x1D730, 'M', u'υ'), (0x1D731, 'M', u'φ'), (0x1D732, 'M', u'χ'), (0x1D733, 'M', u'ψ'), (0x1D734, 'M', u'ω'), (0x1D735, 'M', u'∇'), (0x1D736, 'M', u'α'), (0x1D737, 'M', u'β'), (0x1D738, 'M', u'γ'), (0x1D739, 'M', u'δ'), (0x1D73A, 'M', u'ε'), (0x1D73B, 'M', u'ζ'), (0x1D73C, 'M', u'η'), (0x1D73D, 'M', u'θ'), (0x1D73E, 'M', u'ι'), (0x1D73F, 'M', u'κ'), (0x1D740, 'M', u'λ'), (0x1D741, 'M', u'μ'), (0x1D742, 'M', u'ν'), (0x1D743, 'M', u'ξ'), (0x1D744, 'M', u'ο'), (0x1D745, 'M', u'π'), (0x1D746, 'M', u'ρ'), (0x1D747, 'M', u'σ'), (0x1D749, 'M', u'τ'), (0x1D74A, 'M', u'υ'), (0x1D74B, 'M', u'φ'), (0x1D74C, 'M', u'χ'), (0x1D74D, 'M', u'ψ'), (0x1D74E, 'M', u'ω'), (0x1D74F, 'M', u'∂'), (0x1D750, 'M', u'ε'), (0x1D751, 'M', u'θ'), (0x1D752, 'M', u'κ'), (0x1D753, 'M', u'φ'), (0x1D754, 'M', u'ρ'), (0x1D755, 'M', u'π'), (0x1D756, 'M', u'α'), (0x1D757, 'M', u'β'), (0x1D758, 'M', u'γ'), (0x1D759, 'M', u'δ'), (0x1D75A, 'M', u'ε'), (0x1D75B, 'M', u'ζ'), (0x1D75C, 'M', u'η'), (0x1D75D, 'M', u'θ'), (0x1D75E, 'M', u'ι'), (0x1D75F, 'M', u'κ'), (0x1D760, 'M', u'λ'), (0x1D761, 'M', u'μ'), (0x1D762, 'M', u'ν'), (0x1D763, 'M', u'ξ'), (0x1D764, 'M', u'ο'), (0x1D765, 'M', u'π'), (0x1D766, 'M', u'ρ'), (0x1D767, 'M', u'θ'), (0x1D768, 'M', u'σ'), (0x1D769, 'M', u'τ'), (0x1D76A, 'M', u'υ'), (0x1D76B, 'M', u'φ'), (0x1D76C, 'M', u'χ'), (0x1D76D, 'M', u'ψ'), (0x1D76E, 'M', u'ω'), (0x1D76F, 'M', u'∇'), (0x1D770, 'M', u'α'), (0x1D771, 'M', u'β'), (0x1D772, 'M', u'γ'), (0x1D773, 'M', u'δ'), (0x1D774, 'M', u'ε'), (0x1D775, 'M', u'ζ'), (0x1D776, 'M', u'η'), (0x1D777, 'M', u'θ'), (0x1D778, 'M', u'ι'), (0x1D779, 'M', u'κ'), (0x1D77A, 'M', u'λ'), (0x1D77B, 'M', u'μ'), (0x1D77C, 'M', u'ν'), (0x1D77D, 'M', u'ξ'), (0x1D77E, 'M', u'ο'), (0x1D77F, 'M', u'π'), (0x1D780, 'M', u'ρ'), (0x1D781, 'M', u'σ'), (0x1D783, 'M', u'τ'), (0x1D784, 'M', u'υ'), (0x1D785, 'M', u'φ'), (0x1D786, 'M', u'χ'), (0x1D787, 'M', u'ψ'), ] def _seg_67(): return [ (0x1D788, 'M', u'ω'), (0x1D789, 'M', u'∂'), (0x1D78A, 'M', u'ε'), (0x1D78B, 'M', u'θ'), (0x1D78C, 'M', u'κ'), (0x1D78D, 'M', u'φ'), (0x1D78E, 'M', u'ρ'), (0x1D78F, 'M', u'π'), (0x1D790, 'M', u'α'), (0x1D791, 'M', u'β'), (0x1D792, 'M', u'γ'), (0x1D793, 'M', u'δ'), (0x1D794, 'M', u'ε'), (0x1D795, 'M', u'ζ'), (0x1D796, 'M', u'η'), (0x1D797, 'M', u'θ'), (0x1D798, 'M', u'ι'), (0x1D799, 'M', u'κ'), (0x1D79A, 'M', u'λ'), (0x1D79B, 'M', u'μ'), (0x1D79C, 'M', u'ν'), (0x1D79D, 'M', u'ξ'), (0x1D79E, 'M', u'ο'), (0x1D79F, 'M', u'π'), (0x1D7A0, 'M', u'ρ'), (0x1D7A1, 'M', u'θ'), (0x1D7A2, 'M', u'σ'), (0x1D7A3, 'M', u'τ'), (0x1D7A4, 'M', u'υ'), (0x1D7A5, 'M', u'φ'), (0x1D7A6, 'M', u'χ'), (0x1D7A7, 'M', u'ψ'), (0x1D7A8, 'M', u'ω'), (0x1D7A9, 'M', u'∇'), (0x1D7AA, 'M', u'α'), (0x1D7AB, 'M', u'β'), (0x1D7AC, 'M', u'γ'), (0x1D7AD, 'M', u'δ'), (0x1D7AE, 'M', u'ε'), (0x1D7AF, 'M', u'ζ'), (0x1D7B0, 'M', u'η'), (0x1D7B1, 'M', u'θ'), (0x1D7B2, 'M', u'ι'), (0x1D7B3, 'M', u'κ'), (0x1D7B4, 'M', u'λ'), (0x1D7B5, 'M', u'μ'), (0x1D7B6, 'M', u'ν'), (0x1D7B7, 'M', u'ξ'), (0x1D7B8, 'M', u'ο'), (0x1D7B9, 'M', u'π'), (0x1D7BA, 'M', u'ρ'), (0x1D7BB, 'M', u'σ'), (0x1D7BD, 'M', u'τ'), (0x1D7BE, 'M', u'υ'), (0x1D7BF, 'M', u'φ'), (0x1D7C0, 'M', u'χ'), (0x1D7C1, 'M', u'ψ'), (0x1D7C2, 'M', u'ω'), (0x1D7C3, 'M', u'∂'), (0x1D7C4, 'M', u'ε'), (0x1D7C5, 'M', u'θ'), (0x1D7C6, 'M', u'κ'), (0x1D7C7, 'M', u'φ'), (0x1D7C8, 'M', u'ρ'), (0x1D7C9, 'M', u'π'), (0x1D7CA, 'M', u'ϝ'), (0x1D7CC, 'X'), (0x1D7CE, 'M', u'0'), (0x1D7CF, 'M', u'1'), (0x1D7D0, 'M', u'2'), (0x1D7D1, 'M', u'3'), (0x1D7D2, 'M', u'4'), (0x1D7D3, 'M', u'5'), (0x1D7D4, 'M', u'6'), (0x1D7D5, 'M', u'7'), (0x1D7D6, 'M', u'8'), (0x1D7D7, 'M', u'9'), (0x1D7D8, 'M', u'0'), (0x1D7D9, 'M', u'1'), (0x1D7DA, 'M', u'2'), (0x1D7DB, 'M', u'3'), (0x1D7DC, 'M', u'4'), (0x1D7DD, 'M', u'5'), (0x1D7DE, 'M', u'6'), (0x1D7DF, 'M', u'7'), (0x1D7E0, 'M', u'8'), (0x1D7E1, 'M', u'9'), (0x1D7E2, 'M', u'0'), (0x1D7E3, 'M', u'1'), (0x1D7E4, 'M', u'2'), (0x1D7E5, 'M', u'3'), (0x1D7E6, 'M', u'4'), (0x1D7E7, 'M', u'5'), (0x1D7E8, 'M', u'6'), (0x1D7E9, 'M', u'7'), (0x1D7EA, 'M', u'8'), (0x1D7EB, 'M', u'9'), (0x1D7EC, 'M', u'0'), (0x1D7ED, 'M', u'1'), (0x1D7EE, 'M', u'2'), ] def _seg_68(): return [ (0x1D7EF, 'M', u'3'), (0x1D7F0, 'M', u'4'), (0x1D7F1, 'M', u'5'), (0x1D7F2, 'M', u'6'), (0x1D7F3, 'M', u'7'), (0x1D7F4, 'M', u'8'), (0x1D7F5, 'M', u'9'), (0x1D7F6, 'M', u'0'), (0x1D7F7, 'M', u'1'), (0x1D7F8, 'M', u'2'), (0x1D7F9, 'M', u'3'), (0x1D7FA, 'M', u'4'), (0x1D7FB, 'M', u'5'), (0x1D7FC, 'M', u'6'), (0x1D7FD, 'M', u'7'), (0x1D7FE, 'M', u'8'), (0x1D7FF, 'M', u'9'), (0x1D800, 'V'), (0x1DA8C, 'X'), (0x1DA9B, 'V'), (0x1DAA0, 'X'), (0x1DAA1, 'V'), (0x1DAB0, 'X'), (0x1E000, 'V'), (0x1E007, 'X'), (0x1E008, 'V'), (0x1E019, 'X'), (0x1E01B, 'V'), (0x1E022, 'X'), (0x1E023, 'V'), (0x1E025, 'X'), (0x1E026, 'V'), (0x1E02B, 'X'), (0x1E800, 'V'), (0x1E8C5, 'X'), (0x1E8C7, 'V'), (0x1E8D7, 'X'), (0x1E900, 'M', u'𞤢'), (0x1E901, 'M', u'𞤣'), (0x1E902, 'M', u'𞤤'), (0x1E903, 'M', u'𞤥'), (0x1E904, 'M', u'𞤦'), (0x1E905, 'M', u'𞤧'), (0x1E906, 'M', u'𞤨'), (0x1E907, 'M', u'𞤩'), (0x1E908, 'M', u'𞤪'), (0x1E909, 'M', u'𞤫'), (0x1E90A, 'M', u'𞤬'), (0x1E90B, 'M', u'𞤭'), (0x1E90C, 'M', u'𞤮'), (0x1E90D, 'M', u'𞤯'), (0x1E90E, 'M', u'𞤰'), (0x1E90F, 'M', u'𞤱'), (0x1E910, 'M', u'𞤲'), (0x1E911, 'M', u'𞤳'), (0x1E912, 'M', u'𞤴'), (0x1E913, 'M', u'𞤵'), (0x1E914, 'M', u'𞤶'), (0x1E915, 'M', u'𞤷'), (0x1E916, 'M', u'𞤸'), (0x1E917, 'M', u'𞤹'), (0x1E918, 'M', u'𞤺'), (0x1E919, 'M', u'𞤻'), (0x1E91A, 'M', u'𞤼'), (0x1E91B, 'M', u'𞤽'), (0x1E91C, 'M', u'𞤾'), (0x1E91D, 'M', u'𞤿'), (0x1E91E, 'M', u'𞥀'), (0x1E91F, 'M', u'𞥁'), (0x1E920, 'M', u'𞥂'), (0x1E921, 'M', u'𞥃'), (0x1E922, 'V'), (0x1E94B, 'X'), (0x1E950, 'V'), (0x1E95A, 'X'), (0x1E95E, 'V'), (0x1E960, 'X'), (0x1EC71, 'V'), (0x1ECB5, 'X'), (0x1EE00, 'M', u'ا'), (0x1EE01, 'M', u'ب'), (0x1EE02, 'M', u'ج'), (0x1EE03, 'M', u'د'), (0x1EE04, 'X'), (0x1EE05, 'M', u'و'), (0x1EE06, 'M', u'ز'), (0x1EE07, 'M', u'ح'), (0x1EE08, 'M', u'ط'), (0x1EE09, 'M', u'ي'), (0x1EE0A, 'M', u'ك'), (0x1EE0B, 'M', u'ل'), (0x1EE0C, 'M', u'م'), (0x1EE0D, 'M', u'ن'), (0x1EE0E, 'M', u'س'), (0x1EE0F, 'M', u'ع'), (0x1EE10, 'M', u'ف'), (0x1EE11, 'M', u'ص'), (0x1EE12, 'M', u'ق'), (0x1EE13, 'M', u'ر'), (0x1EE14, 'M', u'ش'), ] def _seg_69(): return [ (0x1EE15, 'M', u'ت'), (0x1EE16, 'M', u'ث'), (0x1EE17, 'M', u'خ'), (0x1EE18, 'M', u'ذ'), (0x1EE19, 'M', u'ض'), (0x1EE1A, 'M', u'ظ'), (0x1EE1B, 'M', u'غ'), (0x1EE1C, 'M', u'ٮ'), (0x1EE1D, 'M', u'ں'), (0x1EE1E, 'M', u'ڡ'), (0x1EE1F, 'M', u'ٯ'), (0x1EE20, 'X'), (0x1EE21, 'M', u'ب'), (0x1EE22, 'M', u'ج'), (0x1EE23, 'X'), (0x1EE24, 'M', u'ه'), (0x1EE25, 'X'), (0x1EE27, 'M', u'ح'), (0x1EE28, 'X'), (0x1EE29, 'M', u'ي'), (0x1EE2A, 'M', u'ك'), (0x1EE2B, 'M', u'ل'), (0x1EE2C, 'M', u'م'), (0x1EE2D, 'M', u'ن'), (0x1EE2E, 'M', u'س'), (0x1EE2F, 'M', u'ع'), (0x1EE30, 'M', u'ف'), (0x1EE31, 'M', u'ص'), (0x1EE32, 'M', u'ق'), (0x1EE33, 'X'), (0x1EE34, 'M', u'ش'), (0x1EE35, 'M', u'ت'), (0x1EE36, 'M', u'ث'), (0x1EE37, 'M', u'خ'), (0x1EE38, 'X'), (0x1EE39, 'M', u'ض'), (0x1EE3A, 'X'), (0x1EE3B, 'M', u'غ'), (0x1EE3C, 'X'), (0x1EE42, 'M', u'ج'), (0x1EE43, 'X'), (0x1EE47, 'M', u'ح'), (0x1EE48, 'X'), (0x1EE49, 'M', u'ي'), (0x1EE4A, 'X'), (0x1EE4B, 'M', u'ل'), (0x1EE4C, 'X'), (0x1EE4D, 'M', u'ن'), (0x1EE4E, 'M', u'س'), (0x1EE4F, 'M', u'ع'), (0x1EE50, 'X'), (0x1EE51, 'M', u'ص'), (0x1EE52, 'M', u'ق'), (0x1EE53, 'X'), (0x1EE54, 'M', u'ش'), (0x1EE55, 'X'), (0x1EE57, 'M', u'خ'), (0x1EE58, 'X'), (0x1EE59, 'M', u'ض'), (0x1EE5A, 'X'), (0x1EE5B, 'M', u'غ'), (0x1EE5C, 'X'), (0x1EE5D, 'M', u'ں'), (0x1EE5E, 'X'), (0x1EE5F, 'M', u'ٯ'), (0x1EE60, 'X'), (0x1EE61, 'M', u'ب'), (0x1EE62, 'M', u'ج'), (0x1EE63, 'X'), (0x1EE64, 'M', u'ه'), (0x1EE65, 'X'), (0x1EE67, 'M', u'ح'), (0x1EE68, 'M', u'ط'), (0x1EE69, 'M', u'ي'), (0x1EE6A, 'M', u'ك'), (0x1EE6B, 'X'), (0x1EE6C, 'M', u'م'), (0x1EE6D, 'M', u'ن'), (0x1EE6E, 'M', u'س'), (0x1EE6F, 'M', u'ع'), (0x1EE70, 'M', u'ف'), (0x1EE71, 'M', u'ص'), (0x1EE72, 'M', u'ق'), (0x1EE73, 'X'), (0x1EE74, 'M', u'ش'), (0x1EE75, 'M', u'ت'), (0x1EE76, 'M', u'ث'), (0x1EE77, 'M', u'خ'), (0x1EE78, 'X'), (0x1EE79, 'M', u'ض'), (0x1EE7A, 'M', u'ظ'), (0x1EE7B, 'M', u'غ'), (0x1EE7C, 'M', u'ٮ'), (0x1EE7D, 'X'), (0x1EE7E, 'M', u'ڡ'), (0x1EE7F, 'X'), (0x1EE80, 'M', u'ا'), (0x1EE81, 'M', u'ب'), (0x1EE82, 'M', u'ج'), (0x1EE83, 'M', u'د'), ] def _seg_70(): return [ (0x1EE84, 'M', u'ه'), (0x1EE85, 'M', u'و'), (0x1EE86, 'M', u'ز'), (0x1EE87, 'M', u'ح'), (0x1EE88, 'M', u'ط'), (0x1EE89, 'M', u'ي'), (0x1EE8A, 'X'), (0x1EE8B, 'M', u'ل'), (0x1EE8C, 'M', u'م'), (0x1EE8D, 'M', u'ن'), (0x1EE8E, 'M', u'س'), (0x1EE8F, 'M', u'ع'), (0x1EE90, 'M', u'ف'), (0x1EE91, 'M', u'ص'), (0x1EE92, 'M', u'ق'), (0x1EE93, 'M', u'ر'), (0x1EE94, 'M', u'ش'), (0x1EE95, 'M', u'ت'), (0x1EE96, 'M', u'ث'), (0x1EE97, 'M', u'خ'), (0x1EE98, 'M', u'ذ'), (0x1EE99, 'M', u'ض'), (0x1EE9A, 'M', u'ظ'), (0x1EE9B, 'M', u'غ'), (0x1EE9C, 'X'), (0x1EEA1, 'M', u'ب'), (0x1EEA2, 'M', u'ج'), (0x1EEA3, 'M', u'د'), (0x1EEA4, 'X'), (0x1EEA5, 'M', u'و'), (0x1EEA6, 'M', u'ز'), (0x1EEA7, 'M', u'ح'), (0x1EEA8, 'M', u'ط'), (0x1EEA9, 'M', u'ي'), (0x1EEAA, 'X'), (0x1EEAB, 'M', u'ل'), (0x1EEAC, 'M', u'م'), (0x1EEAD, 'M', u'ن'), (0x1EEAE, 'M', u'س'), (0x1EEAF, 'M', u'ع'), (0x1EEB0, 'M', u'ف'), (0x1EEB1, 'M', u'ص'), (0x1EEB2, 'M', u'ق'), (0x1EEB3, 'M', u'ر'), (0x1EEB4, 'M', u'ش'), (0x1EEB5, 'M', u'ت'), (0x1EEB6, 'M', u'ث'), (0x1EEB7, 'M', u'خ'), (0x1EEB8, 'M', u'ذ'), (0x1EEB9, 'M', u'ض'), (0x1EEBA, 'M', u'ظ'), (0x1EEBB, 'M', u'غ'), (0x1EEBC, 'X'), (0x1EEF0, 'V'), (0x1EEF2, 'X'), (0x1F000, 'V'), (0x1F02C, 'X'), (0x1F030, 'V'), (0x1F094, 'X'), (0x1F0A0, 'V'), (0x1F0AF, 'X'), (0x1F0B1, 'V'), (0x1F0C0, 'X'), (0x1F0C1, 'V'), (0x1F0D0, 'X'), (0x1F0D1, 'V'), (0x1F0F6, 'X'), (0x1F101, '3', u'0,'), (0x1F102, '3', u'1,'), (0x1F103, '3', u'2,'), (0x1F104, '3', u'3,'), (0x1F105, '3', u'4,'), (0x1F106, '3', u'5,'), (0x1F107, '3', u'6,'), (0x1F108, '3', u'7,'), (0x1F109, '3', u'8,'), (0x1F10A, '3', u'9,'), (0x1F10B, 'V'), (0x1F10D, 'X'), (0x1F110, '3', u'(a)'), (0x1F111, '3', u'(b)'), (0x1F112, '3', u'(c)'), (0x1F113, '3', u'(d)'), (0x1F114, '3', u'(e)'), (0x1F115, '3', u'(f)'), (0x1F116, '3', u'(g)'), (0x1F117, '3', u'(h)'), (0x1F118, '3', u'(i)'), (0x1F119, '3', u'(j)'), (0x1F11A, '3', u'(k)'), (0x1F11B, '3', u'(l)'), (0x1F11C, '3', u'(m)'), (0x1F11D, '3', u'(n)'), (0x1F11E, '3', u'(o)'), (0x1F11F, '3', u'(p)'), (0x1F120, '3', u'(q)'), (0x1F121, '3', u'(r)'), (0x1F122, '3', u'(s)'), (0x1F123, '3', u'(t)'), (0x1F124, '3', u'(u)'), ] def _seg_71(): return [ (0x1F125, '3', u'(v)'), (0x1F126, '3', u'(w)'), (0x1F127, '3', u'(x)'), (0x1F128, '3', u'(y)'), (0x1F129, '3', u'(z)'), (0x1F12A, 'M', u'〔s〕'), (0x1F12B, 'M', u'c'), (0x1F12C, 'M', u'r'), (0x1F12D, 'M', u'cd'), (0x1F12E, 'M', u'wz'), (0x1F12F, 'V'), (0x1F130, 'M', u'a'), (0x1F131, 'M', u'b'), (0x1F132, 'M', u'c'), (0x1F133, 'M', u'd'), (0x1F134, 'M', u'e'), (0x1F135, 'M', u'f'), (0x1F136, 'M', u'g'), (0x1F137, 'M', u'h'), (0x1F138, 'M', u'i'), (0x1F139, 'M', u'j'), (0x1F13A, 'M', u'k'), (0x1F13B, 'M', u'l'), (0x1F13C, 'M', u'm'), (0x1F13D, 'M', u'n'), (0x1F13E, 'M', u'o'), (0x1F13F, 'M', u'p'), (0x1F140, 'M', u'q'), (0x1F141, 'M', u'r'), (0x1F142, 'M', u's'), (0x1F143, 'M', u't'), (0x1F144, 'M', u'u'), (0x1F145, 'M', u'v'), (0x1F146, 'M', u'w'), (0x1F147, 'M', u'x'), (0x1F148, 'M', u'y'), (0x1F149, 'M', u'z'), (0x1F14A, 'M', u'hv'), (0x1F14B, 'M', u'mv'), (0x1F14C, 'M', u'sd'), (0x1F14D, 'M', u'ss'), (0x1F14E, 'M', u'ppv'), (0x1F14F, 'M', u'wc'), (0x1F150, 'V'), (0x1F16A, 'M', u'mc'), (0x1F16B, 'M', u'md'), (0x1F16C, 'X'), (0x1F170, 'V'), (0x1F190, 'M', u'dj'), (0x1F191, 'V'), (0x1F1AD, 'X'), (0x1F1E6, 'V'), (0x1F200, 'M', u'ほか'), (0x1F201, 'M', u'ココ'), (0x1F202, 'M', u'サ'), (0x1F203, 'X'), (0x1F210, 'M', u'手'), (0x1F211, 'M', u'字'), (0x1F212, 'M', u'双'), (0x1F213, 'M', u'デ'), (0x1F214, 'M', u'二'), (0x1F215, 'M', u'多'), (0x1F216, 'M', u'解'), (0x1F217, 'M', u'天'), (0x1F218, 'M', u'交'), (0x1F219, 'M', u'映'), (0x1F21A, 'M', u'無'), (0x1F21B, 'M', u'料'), (0x1F21C, 'M', u'前'), (0x1F21D, 'M', u'後'), (0x1F21E, 'M', u'再'), (0x1F21F, 'M', u'新'), (0x1F220, 'M', u'初'), (0x1F221, 'M', u'終'), (0x1F222, 'M', u'生'), (0x1F223, 'M', u'販'), (0x1F224, 'M', u'声'), (0x1F225, 'M', u'吹'), (0x1F226, 'M', u'演'), (0x1F227, 'M', u'投'), (0x1F228, 'M', u'捕'), (0x1F229, 'M', u'一'), (0x1F22A, 'M', u'三'), (0x1F22B, 'M', u'遊'), (0x1F22C, 'M', u'左'), (0x1F22D, 'M', u'中'), (0x1F22E, 'M', u'右'), (0x1F22F, 'M', u'指'), (0x1F230, 'M', u'走'), (0x1F231, 'M', u'打'), (0x1F232, 'M', u'禁'), (0x1F233, 'M', u'空'), (0x1F234, 'M', u'合'), (0x1F235, 'M', u'満'), (0x1F236, 'M', u'有'), (0x1F237, 'M', u'月'), (0x1F238, 'M', u'申'), (0x1F239, 'M', u'割'), (0x1F23A, 'M', u'営'), (0x1F23B, 'M', u'配'), ] def _seg_72(): return [ (0x1F23C, 'X'), (0x1F240, 'M', u'〔本〕'), (0x1F241, 'M', u'〔三〕'), (0x1F242, 'M', u'〔二〕'), (0x1F243, 'M', u'〔安〕'), (0x1F244, 'M', u'〔点〕'), (0x1F245, 'M', u'〔打〕'), (0x1F246, 'M', u'〔盗〕'), (0x1F247, 'M', u'〔勝〕'), (0x1F248, 'M', u'〔敗〕'), (0x1F249, 'X'), (0x1F250, 'M', u'得'), (0x1F251, 'M', u'可'), (0x1F252, 'X'), (0x1F260, 'V'), (0x1F266, 'X'), (0x1F300, 'V'), (0x1F6D5, 'X'), (0x1F6E0, 'V'), (0x1F6ED, 'X'), (0x1F6F0, 'V'), (0x1F6FA, 'X'), (0x1F700, 'V'), (0x1F774, 'X'), (0x1F780, 'V'), (0x1F7D9, 'X'), (0x1F800, 'V'), (0x1F80C, 'X'), (0x1F810, 'V'), (0x1F848, 'X'), (0x1F850, 'V'), (0x1F85A, 'X'), (0x1F860, 'V'), (0x1F888, 'X'), (0x1F890, 'V'), (0x1F8AE, 'X'), (0x1F900, 'V'), (0x1F90C, 'X'), (0x1F910, 'V'), (0x1F93F, 'X'), (0x1F940, 'V'), (0x1F971, 'X'), (0x1F973, 'V'), (0x1F977, 'X'), (0x1F97A, 'V'), (0x1F97B, 'X'), (0x1F97C, 'V'), (0x1F9A3, 'X'), (0x1F9B0, 'V'), (0x1F9BA, 'X'), (0x1F9C0, 'V'), (0x1F9C3, 'X'), (0x1F9D0, 'V'), (0x1FA00, 'X'), (0x1FA60, 'V'), (0x1FA6E, 'X'), (0x20000, 'V'), (0x2A6D7, 'X'), (0x2A700, 'V'), (0x2B735, 'X'), (0x2B740, 'V'), (0x2B81E, 'X'), (0x2B820, 'V'), (0x2CEA2, 'X'), (0x2CEB0, 'V'), (0x2EBE1, 'X'), (0x2F800, 'M', u'丽'), (0x2F801, 'M', u'丸'), (0x2F802, 'M', u'乁'), (0x2F803, 'M', u'𠄢'), (0x2F804, 'M', u'你'), (0x2F805, 'M', u'侮'), (0x2F806, 'M', u'侻'), (0x2F807, 'M', u'倂'), (0x2F808, 'M', u'偺'), (0x2F809, 'M', u'備'), (0x2F80A, 'M', u'僧'), (0x2F80B, 'M', u'像'), (0x2F80C, 'M', u'㒞'), (0x2F80D, 'M', u'𠘺'), (0x2F80E, 'M', u'免'), (0x2F80F, 'M', u'兔'), (0x2F810, 'M', u'兤'), (0x2F811, 'M', u'具'), (0x2F812, 'M', u'𠔜'), (0x2F813, 'M', u'㒹'), (0x2F814, 'M', u'內'), (0x2F815, 'M', u'再'), (0x2F816, 'M', u'𠕋'), (0x2F817, 'M', u'冗'), (0x2F818, 'M', u'冤'), (0x2F819, 'M', u'仌'), (0x2F81A, 'M', u'冬'), (0x2F81B, 'M', u'况'), (0x2F81C, 'M', u'𩇟'), (0x2F81D, 'M', u'凵'), (0x2F81E, 'M', u'刃'), (0x2F81F, 'M', u'㓟'), (0x2F820, 'M', u'刻'), (0x2F821, 'M', u'剆'), ] def _seg_73(): return [ (0x2F822, 'M', u'割'), (0x2F823, 'M', u'剷'), (0x2F824, 'M', u'㔕'), (0x2F825, 'M', u'勇'), (0x2F826, 'M', u'勉'), (0x2F827, 'M', u'勤'), (0x2F828, 'M', u'勺'), (0x2F829, 'M', u'包'), (0x2F82A, 'M', u'匆'), (0x2F82B, 'M', u'北'), (0x2F82C, 'M', u'卉'), (0x2F82D, 'M', u'卑'), (0x2F82E, 'M', u'博'), (0x2F82F, 'M', u'即'), (0x2F830, 'M', u'卽'), (0x2F831, 'M', u'卿'), (0x2F834, 'M', u'𠨬'), (0x2F835, 'M', u'灰'), (0x2F836, 'M', u'及'), (0x2F837, 'M', u'叟'), (0x2F838, 'M', u'𠭣'), (0x2F839, 'M', u'叫'), (0x2F83A, 'M', u'叱'), (0x2F83B, 'M', u'吆'), (0x2F83C, 'M', u'咞'), (0x2F83D, 'M', u'吸'), (0x2F83E, 'M', u'呈'), (0x2F83F, 'M', u'周'), (0x2F840, 'M', u'咢'), (0x2F841, 'M', u'哶'), (0x2F842, 'M', u'唐'), (0x2F843, 'M', u'啓'), (0x2F844, 'M', u'啣'), (0x2F845, 'M', u'善'), (0x2F847, 'M', u'喙'), (0x2F848, 'M', u'喫'), (0x2F849, 'M', u'喳'), (0x2F84A, 'M', u'嗂'), (0x2F84B, 'M', u'圖'), (0x2F84C, 'M', u'嘆'), (0x2F84D, 'M', u'圗'), (0x2F84E, 'M', u'噑'), (0x2F84F, 'M', u'噴'), (0x2F850, 'M', u'切'), (0x2F851, 'M', u'壮'), (0x2F852, 'M', u'城'), (0x2F853, 'M', u'埴'), (0x2F854, 'M', u'堍'), (0x2F855, 'M', u'型'), (0x2F856, 'M', u'堲'), (0x2F857, 'M', u'報'), (0x2F858, 'M', u'墬'), (0x2F859, 'M', u'𡓤'), (0x2F85A, 'M', u'売'), (0x2F85B, 'M', u'壷'), (0x2F85C, 'M', u'夆'), (0x2F85D, 'M', u'多'), (0x2F85E, 'M', u'夢'), (0x2F85F, 'M', u'奢'), (0x2F860, 'M', u'𡚨'), (0x2F861, 'M', u'𡛪'), (0x2F862, 'M', u'姬'), (0x2F863, 'M', u'娛'), (0x2F864, 'M', u'娧'), (0x2F865, 'M', u'姘'), (0x2F866, 'M', u'婦'), (0x2F867, 'M', u'㛮'), (0x2F868, 'X'), (0x2F869, 'M', u'嬈'), (0x2F86A, 'M', u'嬾'), (0x2F86C, 'M', u'𡧈'), (0x2F86D, 'M', u'寃'), (0x2F86E, 'M', u'寘'), (0x2F86F, 'M', u'寧'), (0x2F870, 'M', u'寳'), (0x2F871, 'M', u'𡬘'), (0x2F872, 'M', u'寿'), (0x2F873, 'M', u'将'), (0x2F874, 'X'), (0x2F875, 'M', u'尢'), (0x2F876, 'M', u'㞁'), (0x2F877, 'M', u'屠'), (0x2F878, 'M', u'屮'), (0x2F879, 'M', u'峀'), (0x2F87A, 'M', u'岍'), (0x2F87B, 'M', u'𡷤'), (0x2F87C, 'M', u'嵃'), (0x2F87D, 'M', u'𡷦'), (0x2F87E, 'M', u'嵮'), (0x2F87F, 'M', u'嵫'), (0x2F880, 'M', u'嵼'), (0x2F881, 'M', u'巡'), (0x2F882, 'M', u'巢'), (0x2F883, 'M', u'㠯'), (0x2F884, 'M', u'巽'), (0x2F885, 'M', u'帨'), (0x2F886, 'M', u'帽'), (0x2F887, 'M', u'幩'), (0x2F888, 'M', u'㡢'), (0x2F889, 'M', u'𢆃'), ] def _seg_74(): return [ (0x2F88A, 'M', u'㡼'), (0x2F88B, 'M', u'庰'), (0x2F88C, 'M', u'庳'), (0x2F88D, 'M', u'庶'), (0x2F88E, 'M', u'廊'), (0x2F88F, 'M', u'𪎒'), (0x2F890, 'M', u'廾'), (0x2F891, 'M', u'𢌱'), (0x2F893, 'M', u'舁'), (0x2F894, 'M', u'弢'), (0x2F896, 'M', u'㣇'), (0x2F897, 'M', u'𣊸'), (0x2F898, 'M', u'𦇚'), (0x2F899, 'M', u'形'), (0x2F89A, 'M', u'彫'), (0x2F89B, 'M', u'㣣'), (0x2F89C, 'M', u'徚'), (0x2F89D, 'M', u'忍'), (0x2F89E, 'M', u'志'), (0x2F89F, 'M', u'忹'), (0x2F8A0, 'M', u'悁'), (0x2F8A1, 'M', u'㤺'), (0x2F8A2, 'M', u'㤜'), (0x2F8A3, 'M', u'悔'), (0x2F8A4, 'M', u'𢛔'), (0x2F8A5, 'M', u'惇'), (0x2F8A6, 'M', u'慈'), (0x2F8A7, 'M', u'慌'), (0x2F8A8, 'M', u'慎'), (0x2F8A9, 'M', u'慌'), (0x2F8AA, 'M', u'慺'), (0x2F8AB, 'M', u'憎'), (0x2F8AC, 'M', u'憲'), (0x2F8AD, 'M', u'憤'), (0x2F8AE, 'M', u'憯'), (0x2F8AF, 'M', u'懞'), (0x2F8B0, 'M', u'懲'), (0x2F8B1, 'M', u'懶'), (0x2F8B2, 'M', u'成'), (0x2F8B3, 'M', u'戛'), (0x2F8B4, 'M', u'扝'), (0x2F8B5, 'M', u'抱'), (0x2F8B6, 'M', u'拔'), (0x2F8B7, 'M', u'捐'), (0x2F8B8, 'M', u'𢬌'), (0x2F8B9, 'M', u'挽'), (0x2F8BA, 'M', u'拼'), (0x2F8BB, 'M', u'捨'), (0x2F8BC, 'M', u'掃'), (0x2F8BD, 'M', u'揤'), (0x2F8BE, 'M', u'𢯱'), (0x2F8BF, 'M', u'搢'), (0x2F8C0, 'M', u'揅'), (0x2F8C1, 'M', u'掩'), (0x2F8C2, 'M', u'㨮'), (0x2F8C3, 'M', u'摩'), (0x2F8C4, 'M', u'摾'), (0x2F8C5, 'M', u'撝'), (0x2F8C6, 'M', u'摷'), (0x2F8C7, 'M', u'㩬'), (0x2F8C8, 'M', u'敏'), (0x2F8C9, 'M', u'敬'), (0x2F8CA, 'M', u'𣀊'), (0x2F8CB, 'M', u'旣'), (0x2F8CC, 'M', u'書'), (0x2F8CD, 'M', u'晉'), (0x2F8CE, 'M', u'㬙'), (0x2F8CF, 'M', u'暑'), (0x2F8D0, 'M', u'㬈'), (0x2F8D1, 'M', u'㫤'), (0x2F8D2, 'M', u'冒'), (0x2F8D3, 'M', u'冕'), (0x2F8D4, 'M', u'最'), (0x2F8D5, 'M', u'暜'), (0x2F8D6, 'M', u'肭'), (0x2F8D7, 'M', u'䏙'), (0x2F8D8, 'M', u'朗'), (0x2F8D9, 'M', u'望'), (0x2F8DA, 'M', u'朡'), (0x2F8DB, 'M', u'杞'), (0x2F8DC, 'M', u'杓'), (0x2F8DD, 'M', u'𣏃'), (0x2F8DE, 'M', u'㭉'), (0x2F8DF, 'M', u'柺'), (0x2F8E0, 'M', u'枅'), (0x2F8E1, 'M', u'桒'), (0x2F8E2, 'M', u'梅'), (0x2F8E3, 'M', u'𣑭'), (0x2F8E4, 'M', u'梎'), (0x2F8E5, 'M', u'栟'), (0x2F8E6, 'M', u'椔'), (0x2F8E7, 'M', u'㮝'), (0x2F8E8, 'M', u'楂'), (0x2F8E9, 'M', u'榣'), (0x2F8EA, 'M', u'槪'), (0x2F8EB, 'M', u'檨'), (0x2F8EC, 'M', u'𣚣'), (0x2F8ED, 'M', u'櫛'), (0x2F8EE, 'M', u'㰘'), (0x2F8EF, 'M', u'次'), ] def _seg_75(): return [ (0x2F8F0, 'M', u'𣢧'), (0x2F8F1, 'M', u'歔'), (0x2F8F2, 'M', u'㱎'), (0x2F8F3, 'M', u'歲'), (0x2F8F4, 'M', u'殟'), (0x2F8F5, 'M', u'殺'), (0x2F8F6, 'M', u'殻'), (0x2F8F7, 'M', u'𣪍'), (0x2F8F8, 'M', u'𡴋'), (0x2F8F9, 'M', u'𣫺'), (0x2F8FA, 'M', u'汎'), (0x2F8FB, 'M', u'𣲼'), (0x2F8FC, 'M', u'沿'), (0x2F8FD, 'M', u'泍'), (0x2F8FE, 'M', u'汧'), (0x2F8FF, 'M', u'洖'), (0x2F900, 'M', u'派'), (0x2F901, 'M', u'海'), (0x2F902, 'M', u'流'), (0x2F903, 'M', u'浩'), (0x2F904, 'M', u'浸'), (0x2F905, 'M', u'涅'), (0x2F906, 'M', u'𣴞'), (0x2F907, 'M', u'洴'), (0x2F908, 'M', u'港'), (0x2F909, 'M', u'湮'), (0x2F90A, 'M', u'㴳'), (0x2F90B, 'M', u'滋'), (0x2F90C, 'M', u'滇'), (0x2F90D, 'M', u'𣻑'), (0x2F90E, 'M', u'淹'), (0x2F90F, 'M', u'潮'), (0x2F910, 'M', u'𣽞'), (0x2F911, 'M', u'𣾎'), (0x2F912, 'M', u'濆'), (0x2F913, 'M', u'瀹'), (0x2F914, 'M', u'瀞'), (0x2F915, 'M', u'瀛'), (0x2F916, 'M', u'㶖'), (0x2F917, 'M', u'灊'), (0x2F918, 'M', u'災'), (0x2F919, 'M', u'灷'), (0x2F91A, 'M', u'炭'), (0x2F91B, 'M', u'𠔥'), (0x2F91C, 'M', u'煅'), (0x2F91D, 'M', u'𤉣'), (0x2F91E, 'M', u'熜'), (0x2F91F, 'X'), (0x2F920, 'M', u'爨'), (0x2F921, 'M', u'爵'), (0x2F922, 'M', u'牐'), (0x2F923, 'M', u'𤘈'), (0x2F924, 'M', u'犀'), (0x2F925, 'M', u'犕'), (0x2F926, 'M', u'𤜵'), (0x2F927, 'M', u'𤠔'), (0x2F928, 'M', u'獺'), (0x2F929, 'M', u'王'), (0x2F92A, 'M', u'㺬'), (0x2F92B, 'M', u'玥'), (0x2F92C, 'M', u'㺸'), (0x2F92E, 'M', u'瑇'), (0x2F92F, 'M', u'瑜'), (0x2F930, 'M', u'瑱'), (0x2F931, 'M', u'璅'), (0x2F932, 'M', u'瓊'), (0x2F933, 'M', u'㼛'), (0x2F934, 'M', u'甤'), (0x2F935, 'M', u'𤰶'), (0x2F936, 'M', u'甾'), (0x2F937, 'M', u'𤲒'), (0x2F938, 'M', u'異'), (0x2F939, 'M', u'𢆟'), (0x2F93A, 'M', u'瘐'), (0x2F93B, 'M', u'𤾡'), (0x2F93C, 'M', u'𤾸'), (0x2F93D, 'M', u'𥁄'), (0x2F93E, 'M', u'㿼'), (0x2F93F, 'M', u'䀈'), (0x2F940, 'M', u'直'), (0x2F941, 'M', u'𥃳'), (0x2F942, 'M', u'𥃲'), (0x2F943, 'M', u'𥄙'), (0x2F944, 'M', u'𥄳'), (0x2F945, 'M', u'眞'), (0x2F946, 'M', u'真'), (0x2F948, 'M', u'睊'), (0x2F949, 'M', u'䀹'), (0x2F94A, 'M', u'瞋'), (0x2F94B, 'M', u'䁆'), (0x2F94C, 'M', u'䂖'), (0x2F94D, 'M', u'𥐝'), (0x2F94E, 'M', u'硎'), (0x2F94F, 'M', u'碌'), (0x2F950, 'M', u'磌'), (0x2F951, 'M', u'䃣'), (0x2F952, 'M', u'𥘦'), (0x2F953, 'M', u'祖'), (0x2F954, 'M', u'𥚚'), (0x2F955, 'M', u'𥛅'), ] def _seg_76(): return [ (0x2F956, 'M', u'福'), (0x2F957, 'M', u'秫'), (0x2F958, 'M', u'䄯'), (0x2F959, 'M', u'穀'), (0x2F95A, 'M', u'穊'), (0x2F95B, 'M', u'穏'), (0x2F95C, 'M', u'𥥼'), (0x2F95D, 'M', u'𥪧'), (0x2F95F, 'X'), (0x2F960, 'M', u'䈂'), (0x2F961, 'M', u'𥮫'), (0x2F962, 'M', u'篆'), (0x2F963, 'M', u'築'), (0x2F964, 'M', u'䈧'), (0x2F965, 'M', u'𥲀'), (0x2F966, 'M', u'糒'), (0x2F967, 'M', u'䊠'), (0x2F968, 'M', u'糨'), (0x2F969, 'M', u'糣'), (0x2F96A, 'M', u'紀'), (0x2F96B, 'M', u'𥾆'), (0x2F96C, 'M', u'絣'), (0x2F96D, 'M', u'䌁'), (0x2F96E, 'M', u'緇'), (0x2F96F, 'M', u'縂'), (0x2F970, 'M', u'繅'), (0x2F971, 'M', u'䌴'), (0x2F972, 'M', u'𦈨'), (0x2F973, 'M', u'𦉇'), (0x2F974, 'M', u'䍙'), (0x2F975, 'M', u'𦋙'), (0x2F976, 'M', u'罺'), (0x2F977, 'M', u'𦌾'), (0x2F978, 'M', u'羕'), (0x2F979, 'M', u'翺'), (0x2F97A, 'M', u'者'), (0x2F97B, 'M', u'𦓚'), (0x2F97C, 'M', u'𦔣'), (0x2F97D, 'M', u'聠'), (0x2F97E, 'M', u'𦖨'), (0x2F97F, 'M', u'聰'), (0x2F980, 'M', u'𣍟'), (0x2F981, 'M', u'䏕'), (0x2F982, 'M', u'育'), (0x2F983, 'M', u'脃'), (0x2F984, 'M', u'䐋'), (0x2F985, 'M', u'脾'), (0x2F986, 'M', u'媵'), (0x2F987, 'M', u'𦞧'), (0x2F988, 'M', u'𦞵'), (0x2F989, 'M', u'𣎓'), (0x2F98A, 'M', u'𣎜'), (0x2F98B, 'M', u'舁'), (0x2F98C, 'M', u'舄'), (0x2F98D, 'M', u'辞'), (0x2F98E, 'M', u'䑫'), (0x2F98F, 'M', u'芑'), (0x2F990, 'M', u'芋'), (0x2F991, 'M', u'芝'), (0x2F992, 'M', u'劳'), (0x2F993, 'M', u'花'), (0x2F994, 'M', u'芳'), (0x2F995, 'M', u'芽'), (0x2F996, 'M', u'苦'), (0x2F997, 'M', u'𦬼'), (0x2F998, 'M', u'若'), (0x2F999, 'M', u'茝'), (0x2F99A, 'M', u'荣'), (0x2F99B, 'M', u'莭'), (0x2F99C, 'M', u'茣'), (0x2F99D, 'M', u'莽'), (0x2F99E, 'M', u'菧'), (0x2F99F, 'M', u'著'), (0x2F9A0, 'M', u'荓'), (0x2F9A1, 'M', u'菊'), (0x2F9A2, 'M', u'菌'), (0x2F9A3, 'M', u'菜'), (0x2F9A4, 'M', u'𦰶'), (0x2F9A5, 'M', u'𦵫'), (0x2F9A6, 'M', u'𦳕'), (0x2F9A7, 'M', u'䔫'), (0x2F9A8, 'M', u'蓱'), (0x2F9A9, 'M', u'蓳'), (0x2F9AA, 'M', u'蔖'), (0x2F9AB, 'M', u'𧏊'), (0x2F9AC, 'M', u'蕤'), (0x2F9AD, 'M', u'𦼬'), (0x2F9AE, 'M', u'䕝'), (0x2F9AF, 'M', u'䕡'), (0x2F9B0, 'M', u'𦾱'), (0x2F9B1, 'M', u'𧃒'), (0x2F9B2, 'M', u'䕫'), (0x2F9B3, 'M', u'虐'), (0x2F9B4, 'M', u'虜'), (0x2F9B5, 'M', u'虧'), (0x2F9B6, 'M', u'虩'), (0x2F9B7, 'M', u'蚩'), (0x2F9B8, 'M', u'蚈'), (0x2F9B9, 'M', u'蜎'), (0x2F9BA, 'M', u'蛢'), ] def _seg_77(): return [ (0x2F9BB, 'M', u'蝹'), (0x2F9BC, 'M', u'蜨'), (0x2F9BD, 'M', u'蝫'), (0x2F9BE, 'M', u'螆'), (0x2F9BF, 'X'), (0x2F9C0, 'M', u'蟡'), (0x2F9C1, 'M', u'蠁'), (0x2F9C2, 'M', u'䗹'), (0x2F9C3, 'M', u'衠'), (0x2F9C4, 'M', u'衣'), (0x2F9C5, 'M', u'𧙧'), (0x2F9C6, 'M', u'裗'), (0x2F9C7, 'M', u'裞'), (0x2F9C8, 'M', u'䘵'), (0x2F9C9, 'M', u'裺'), (0x2F9CA, 'M', u'㒻'), (0x2F9CB, 'M', u'𧢮'), (0x2F9CC, 'M', u'𧥦'), (0x2F9CD, 'M', u'䚾'), (0x2F9CE, 'M', u'䛇'), (0x2F9CF, 'M', u'誠'), (0x2F9D0, 'M', u'諭'), (0x2F9D1, 'M', u'變'), (0x2F9D2, 'M', u'豕'), (0x2F9D3, 'M', u'𧲨'), (0x2F9D4, 'M', u'貫'), (0x2F9D5, 'M', u'賁'), (0x2F9D6, 'M', u'贛'), (0x2F9D7, 'M', u'起'), (0x2F9D8, 'M', u'𧼯'), (0x2F9D9, 'M', u'𠠄'), (0x2F9DA, 'M', u'跋'), (0x2F9DB, 'M', u'趼'), (0x2F9DC, 'M', u'跰'), (0x2F9DD, 'M', u'𠣞'), (0x2F9DE, 'M', u'軔'), (0x2F9DF, 'M', u'輸'), (0x2F9E0, 'M', u'𨗒'), (0x2F9E1, 'M', u'𨗭'), (0x2F9E2, 'M', u'邔'), (0x2F9E3, 'M', u'郱'), (0x2F9E4, 'M', u'鄑'), (0x2F9E5, 'M', u'𨜮'), (0x2F9E6, 'M', u'鄛'), (0x2F9E7, 'M', u'鈸'), (0x2F9E8, 'M', u'鋗'), (0x2F9E9, 'M', u'鋘'), (0x2F9EA, 'M', u'鉼'), (0x2F9EB, 'M', u'鏹'), (0x2F9EC, 'M', u'鐕'), (0x2F9ED, 'M', u'𨯺'), (0x2F9EE, 'M', u'開'), (0x2F9EF, 'M', u'䦕'), (0x2F9F0, 'M', u'閷'), (0x2F9F1, 'M', u'𨵷'), (0x2F9F2, 'M', u'䧦'), (0x2F9F3, 'M', u'雃'), (0x2F9F4, 'M', u'嶲'), (0x2F9F5, 'M', u'霣'), (0x2F9F6, 'M', u'𩅅'), (0x2F9F7, 'M', u'𩈚'), (0x2F9F8, 'M', u'䩮'), (0x2F9F9, 'M', u'䩶'), (0x2F9FA, 'M', u'韠'), (0x2F9FB, 'M', u'𩐊'), (0x2F9FC, 'M', u'䪲'), (0x2F9FD, 'M', u'𩒖'), (0x2F9FE, 'M', u'頋'), (0x2FA00, 'M', u'頩'), (0x2FA01, 'M', u'𩖶'), (0x2FA02, 'M', u'飢'), (0x2FA03, 'M', u'䬳'), (0x2FA04, 'M', u'餩'), (0x2FA05, 'M', u'馧'), (0x2FA06, 'M', u'駂'), (0x2FA07, 'M', u'駾'), (0x2FA08, 'M', u'䯎'), (0x2FA09, 'M', u'𩬰'), (0x2FA0A, 'M', u'鬒'), (0x2FA0B, 'M', u'鱀'), (0x2FA0C, 'M', u'鳽'), (0x2FA0D, 'M', u'䳎'), (0x2FA0E, 'M', u'䳭'), (0x2FA0F, 'M', u'鵧'), (0x2FA10, 'M', u'𪃎'), (0x2FA11, 'M', u'䳸'), (0x2FA12, 'M', u'𪄅'), (0x2FA13, 'M', u'𪈎'), (0x2FA14, 'M', u'𪊑'), (0x2FA15, 'M', u'麻'), (0x2FA16, 'M', u'䵖'), (0x2FA17, 'M', u'黹'), (0x2FA18, 'M', u'黾'), (0x2FA19, 'M', u'鼅'), (0x2FA1A, 'M', u'鼏'), (0x2FA1B, 'M', u'鼖'), (0x2FA1C, 'M', u'鼻'), (0x2FA1D, 'M', u'𪘀'), (0x2FA1E, 'X'), (0xE0100, 'I'), ] def _seg_78(): return [ (0xE01F0, 'X'), ] uts46data = tuple( _seg_0() + _seg_1() + _seg_2() + _seg_3() + _seg_4() + _seg_5() + _seg_6() + _seg_7() + _seg_8() + _seg_9() + _seg_10() + _seg_11() + _seg_12() + _seg_13() + _seg_14() + _seg_15() + _seg_16() + _seg_17() + _seg_18() + _seg_19() + _seg_20() + _seg_21() + _seg_22() + _seg_23() + _seg_24() + _seg_25() + _seg_26() + _seg_27() + _seg_28() + _seg_29() + _seg_30() + _seg_31() + _seg_32() + _seg_33() + _seg_34() + _seg_35() + _seg_36() + _seg_37() + _seg_38() + _seg_39() + _seg_40() + _seg_41() + _seg_42() + _seg_43() + _seg_44() + _seg_45() + _seg_46() + _seg_47() + _seg_48() + _seg_49() + _seg_50() + _seg_51() + _seg_52() + _seg_53() + _seg_54() + _seg_55() + _seg_56() + _seg_57() + _seg_58() + _seg_59() + _seg_60() + _seg_61() + _seg_62() + _seg_63() + _seg_64() + _seg_65() + _seg_66() + _seg_67() + _seg_68() + _seg_69() + _seg_70() + _seg_71() + _seg_72() + _seg_73() + _seg_74() + _seg_75() + _seg_76() + _seg_77() + _seg_78() ) ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/idna-2.8.dist-info/INSTALLER ================================================ pip ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/idna-2.8.dist-info/LICENSE.rst ================================================ License ------- Copyright (c) 2013-2018, Kim Davies. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: #. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. #. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. #. Neither the name of the copyright holder nor the names of the contributors may be used to endorse or promote products derived from this software without specific prior written permission. #. THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Portions of the codec implementation and unit tests are derived from the Python standard library, which carries the `Python Software Foundation License `_: Copyright (c) 2001-2014 Python Software Foundation; All Rights Reserved Portions of the unit tests are derived from the Unicode standard, which is subject to the Unicode, Inc. License Agreement: Copyright (c) 1991-2014 Unicode, Inc. All rights reserved. Distributed under the Terms of Use in . Permission is hereby granted, free of charge, to any person obtaining a copy of the Unicode data files and any associated documentation (the "Data Files") or Unicode software and any associated documentation (the "Software") to deal in the Data Files or Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, and/or sell copies of the Data Files or Software, and to permit persons to whom the Data Files or Software are furnished to do so, provided that (a) this copyright and permission notice appear with all copies of the Data Files or Software, (b) this copyright and permission notice appear in associated documentation, and (c) there is clear notice in each modified Data File or in the Software as well as in the documentation associated with the Data File(s) or Software that the data or software has been modified. THE DATA FILES AND SOFTWARE ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THE DATA FILES OR SOFTWARE. Except as contained in this notice, the name of a copyright holder shall not be used in advertising or otherwise to promote the sale, use or other dealings in these Data Files or Software without prior written authorization of the copyright holder. ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/idna-2.8.dist-info/METADATA ================================================ Metadata-Version: 2.1 Name: idna Version: 2.8 Summary: Internationalized Domain Names in Applications (IDNA) Home-page: https://github.com/kjd/idna Author: Kim Davies Author-email: kim@cynosure.com.au License: BSD-like Platform: UNKNOWN Classifier: Development Status :: 5 - Production/Stable Classifier: Intended Audience :: Developers Classifier: Intended Audience :: System Administrators Classifier: License :: OSI Approved :: BSD License Classifier: Operating System :: OS Independent Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 2 Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: 3.4 Classifier: Programming Language :: Python :: 3.5 Classifier: Programming Language :: Python :: 3.6 Classifier: Topic :: Internet :: Name Service (DNS) Classifier: Topic :: Software Development :: Libraries :: Python Modules Classifier: Topic :: Utilities Requires-Python: >=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.* Internationalized Domain Names in Applications (IDNA) ===================================================== Support for the Internationalised Domain Names in Applications (IDNA) protocol as specified in `RFC 5891 `_. This is the latest version of the protocol and is sometimes referred to as “IDNA 2008”. This library also provides support for Unicode Technical Standard 46, `Unicode IDNA Compatibility Processing `_. This acts as a suitable replacement for the “encodings.idna” module that comes with the Python standard library, but only supports the old, deprecated IDNA specification (`RFC 3490 `_). Basic functions are simply executed: .. code-block:: pycon # Python 3 >>> import idna >>> idna.encode('ドメイン.テスト') b'xn--eckwd4c7c.xn--zckzah' >>> print(idna.decode('xn--eckwd4c7c.xn--zckzah')) ドメイン.テスト # Python 2 >>> import idna >>> idna.encode(u'ドメイン.テスト') 'xn--eckwd4c7c.xn--zckzah' >>> print idna.decode('xn--eckwd4c7c.xn--zckzah') ドメイン.テスト Packages -------- The latest tagged release version is published in the PyPI repository: .. image:: https://badge.fury.io/py/idna.svg :target: http://badge.fury.io/py/idna Installation ------------ To install this library, you can use pip: .. code-block:: bash $ pip install idna Alternatively, you can install the package using the bundled setup script: .. code-block:: bash $ python setup.py install This library works with Python 2.7 and Python 3.4 or later. Usage ----- For typical usage, the ``encode`` and ``decode`` functions will take a domain name argument and perform a conversion to A-labels or U-labels respectively. .. code-block:: pycon # Python 3 >>> import idna >>> idna.encode('ドメイン.テスト') b'xn--eckwd4c7c.xn--zckzah' >>> print(idna.decode('xn--eckwd4c7c.xn--zckzah')) ドメイン.テスト You may use the codec encoding and decoding methods using the ``idna.codec`` module: .. code-block:: pycon # Python 2 >>> import idna.codec >>> print u'домена.испытание'.encode('idna') xn--80ahd1agd.xn--80akhbyknj4f >>> print 'xn--80ahd1agd.xn--80akhbyknj4f'.decode('idna') домена.испытание Conversions can be applied at a per-label basis using the ``ulabel`` or ``alabel`` functions if necessary: .. code-block:: pycon # Python 2 >>> idna.alabel(u'测试') 'xn--0zwm56d' Compatibility Mapping (UTS #46) +++++++++++++++++++++++++++++++ As described in `RFC 5895 `_, the IDNA specification no longer normalizes input from different potential ways a user may input a domain name. This functionality, known as a “mapping”, is now considered by the specification to be a local user-interface issue distinct from IDNA conversion functionality. This library provides one such mapping, that was developed by the Unicode Consortium. Known as `Unicode IDNA Compatibility Processing `_, it provides for both a regular mapping for typical applications, as well as a transitional mapping to help migrate from older IDNA 2003 applications. For example, “Königsgäßchen” is not a permissible label as *LATIN CAPITAL LETTER K* is not allowed (nor are capital letters in general). UTS 46 will convert this into lower case prior to applying the IDNA conversion. .. code-block:: pycon # Python 3 >>> import idna >>> idna.encode(u'Königsgäßchen') ... idna.core.InvalidCodepoint: Codepoint U+004B at position 1 of 'Königsgäßchen' not allowed >>> idna.encode('Königsgäßchen', uts46=True) b'xn--knigsgchen-b4a3dun' >>> print(idna.decode('xn--knigsgchen-b4a3dun')) königsgäßchen Transitional processing provides conversions to help transition from the older 2003 standard to the current standard. For example, in the original IDNA specification, the *LATIN SMALL LETTER SHARP S* (ß) was converted into two *LATIN SMALL LETTER S* (ss), whereas in the current IDNA specification this conversion is not performed. .. code-block:: pycon # Python 2 >>> idna.encode(u'Königsgäßchen', uts46=True, transitional=True) 'xn--knigsgsschen-lcb0w' Implementors should use transitional processing with caution, only in rare cases where conversion from legacy labels to current labels must be performed (i.e. IDNA implementations that pre-date 2008). For typical applications that just need to convert labels, transitional processing is unlikely to be beneficial and could produce unexpected incompatible results. ``encodings.idna`` Compatibility ++++++++++++++++++++++++++++++++ Function calls from the Python built-in ``encodings.idna`` module are mapped to their IDNA 2008 equivalents using the ``idna.compat`` module. Simply substitute the ``import`` clause in your code to refer to the new module name. Exceptions ---------- All errors raised during the conversion following the specification should raise an exception derived from the ``idna.IDNAError`` base class. More specific exceptions that may be generated as ``idna.IDNABidiError`` when the error reflects an illegal combination of left-to-right and right-to-left characters in a label; ``idna.InvalidCodepoint`` when a specific codepoint is an illegal character in an IDN label (i.e. INVALID); and ``idna.InvalidCodepointContext`` when the codepoint is illegal based on its positional context (i.e. it is CONTEXTO or CONTEXTJ but the contextual requirements are not satisfied.) Building and Diagnostics ------------------------ The IDNA and UTS 46 functionality relies upon pre-calculated lookup tables for performance. These tables are derived from computing against eligibility criteria in the respective standards. These tables are computed using the command-line script ``tools/idna-data``. This tool will fetch relevant tables from the Unicode Consortium and perform the required calculations to identify eligibility. It has three main modes: * ``idna-data make-libdata``. Generates ``idnadata.py`` and ``uts46data.py``, the pre-calculated lookup tables using for IDNA and UTS 46 conversions. Implementors who wish to track this library against a different Unicode version may use this tool to manually generate a different version of the ``idnadata.py`` and ``uts46data.py`` files. * ``idna-data make-table``. Generate a table of the IDNA disposition (e.g. PVALID, CONTEXTJ, CONTEXTO) in the format found in Appendix B.1 of RFC 5892 and the pre-computed tables published by `IANA `_. * ``idna-data U+0061``. Prints debugging output on the various properties associated with an individual Unicode codepoint (in this case, U+0061), that are used to assess the IDNA and UTS 46 status of a codepoint. This is helpful in debugging or analysis. The tool accepts a number of arguments, described using ``idna-data -h``. Most notably, the ``--version`` argument allows the specification of the version of Unicode to use in computing the table data. For example, ``idna-data --version 9.0.0 make-libdata`` will generate library data against Unicode 9.0.0. Note that this script requires Python 3, but all generated library data will work in Python 2.7. Testing ------- The library has a test suite based on each rule of the IDNA specification, as well as tests that are provided as part of the Unicode Technical Standard 46, `Unicode IDNA Compatibility Processing `_. The tests are run automatically on each commit at Travis CI: .. image:: https://travis-ci.org/kjd/idna.svg?branch=master :target: https://travis-ci.org/kjd/idna ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/idna-2.8.dist-info/RECORD ================================================ idna-2.8.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 idna-2.8.dist-info/LICENSE.rst,sha256=DUvHq9SNz7FOJCVO5AQGZzf_AWcUTiIpFKIRO4eUaD4,3947 idna-2.8.dist-info/METADATA,sha256=X4QsM_BLMPhl4gC8SEnXjvl5-gj7hvwAl7UCyR418so,8862 idna-2.8.dist-info/RECORD,, idna-2.8.dist-info/WHEEL,sha256=CihQvCnsGZQBGAHLEUMf0IdA4fRduS_NBUTMgCTtvPM,110 idna-2.8.dist-info/top_level.txt,sha256=jSag9sEDqvSPftxOQy-ABfGV_RSy7oFh4zZJpODV8k0,5 idna/__init__.py,sha256=9Nt7xpyet3DmOrPUGooDdAwmHZZu1qUAy2EaJ93kGiQ,58 idna/__pycache__/__init__.cpython-36.pyc,, idna/__pycache__/codec.cpython-36.pyc,, idna/__pycache__/compat.cpython-36.pyc,, idna/__pycache__/core.cpython-36.pyc,, idna/__pycache__/idnadata.cpython-36.pyc,, idna/__pycache__/intranges.cpython-36.pyc,, idna/__pycache__/package_data.cpython-36.pyc,, idna/__pycache__/uts46data.cpython-36.pyc,, idna/codec.py,sha256=lvYb7yu7PhAqFaAIAdWcwgaWI2UmgseUua-1c0AsG0A,3299 idna/compat.py,sha256=R-h29D-6mrnJzbXxymrWUW7iZUvy-26TQwZ0ij57i4U,232 idna/core.py,sha256=JDCZZ_PLESqIgEbU8mPyoEufWwoOiIqygA17-QZIe3s,11733 idna/idnadata.py,sha256=HXaPFw6_YAJ0qppACPu0YLAULtRs3QovRM_CCZHGdY0,40899 idna/intranges.py,sha256=TY1lpxZIQWEP6tNqjZkFA5hgoMWOj1OBmnUG8ihT87E,1749 idna/package_data.py,sha256=kIzeKKXEouXLR4srqwf9Q3zv-NffKSOz5aSDOJARPB0,21 idna/uts46data.py,sha256=oLyNZ1pBaiBlj9zFzLFRd_P7J8MkRcgDisjExZR_4MY,198292 ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/idna-2.8.dist-info/WHEEL ================================================ Wheel-Version: 1.0 Generator: bdist_wheel (0.32.2) Root-Is-Purelib: true Tag: py2-none-any Tag: py3-none-any ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/idna-2.8.dist-info/top_level.txt ================================================ idna ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/incremental/__init__.py ================================================ # Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. """ Versions for Python packages. See L{Version}. """ from __future__ import division, absolute_import import sys import warnings # # Compat functions # if sys.version_info < (3, 0): _PY3 = False else: _PY3 = True try: _cmp = cmp except NameError: def _cmp(a, b): """ Compare two objects. Returns a negative number if C{a < b}, zero if they are equal, and a positive number if C{a > b}. """ if a < b: return -1 elif a == b: return 0 else: return 1 def _comparable(klass): """ Class decorator that ensures support for the special C{__cmp__} method. On Python 2 this does nothing. On Python 3, C{__eq__}, C{__lt__}, etc. methods are added to the class, relying on C{__cmp__} to implement their comparisons. """ # On Python 2, __cmp__ will just work, so no need to add extra methods: if not _PY3: return klass def __eq__(self, other): c = self.__cmp__(other) if c is NotImplemented: return c return c == 0 def __ne__(self, other): c = self.__cmp__(other) if c is NotImplemented: return c return c != 0 def __lt__(self, other): c = self.__cmp__(other) if c is NotImplemented: return c return c < 0 def __le__(self, other): c = self.__cmp__(other) if c is NotImplemented: return c return c <= 0 def __gt__(self, other): c = self.__cmp__(other) if c is NotImplemented: return c return c > 0 def __ge__(self, other): c = self.__cmp__(other) if c is NotImplemented: return c return c >= 0 klass.__lt__ = __lt__ klass.__gt__ = __gt__ klass.__le__ = __le__ klass.__ge__ = __ge__ klass.__eq__ = __eq__ klass.__ne__ = __ne__ return klass # # Versioning # @_comparable class _inf(object): """ An object that is bigger than all other objects. """ def __cmp__(self, other): """ @param other: Another object. @type other: any @return: 0 if other is inf, 1 otherwise. @rtype: C{int} """ if other is _inf: return 0 return 1 _inf = _inf() class IncomparableVersions(TypeError): """ Two versions could not be compared. """ @_comparable class Version(object): """ An encapsulation of a version for a project, with support for outputting PEP-440 compatible version strings. This class supports the standard major.minor.micro[rcN] scheme of versioning. """ def __init__(self, package, major, minor, micro, release_candidate=None, prerelease=None, dev=None): """ @param package: Name of the package that this is a version of. @type package: C{str} @param major: The major version number. @type major: C{int} or C{str} (for the "NEXT" symbol) @param minor: The minor version number. @type minor: C{int} @param micro: The micro version number. @type micro: C{int} @param release_candidate: The release candidate number. @type release_candidate: C{int} @param prerelease: The prerelease number. (Deprecated) @type prerelease: C{int} @param dev: The development release number. @type dev: C{int} """ if release_candidate and prerelease: raise ValueError("Please only return one of these.") elif prerelease and not release_candidate: release_candidate = prerelease warnings.warn(("Passing prerelease to incremental.Version was " "deprecated in Incremental 16.9.0. Please pass " "release_candidate instead."), DeprecationWarning, stacklevel=2) if major == "NEXT": if minor or micro or release_candidate or dev: raise ValueError(("When using NEXT, all other values except " "Package must be 0.")) self.package = package self.major = major self.minor = minor self.micro = micro self.release_candidate = release_candidate self.dev = dev @property def prerelease(self): warnings.warn(("Accessing incremental.Version.prerelease was " "deprecated in Incremental 16.9.0. Use " "Version.release_candidate instead."), DeprecationWarning, stacklevel=2), return self.release_candidate def public(self): """ Return a PEP440-compatible "public" representation of this L{Version}. Examples: - 14.4.0 - 1.2.3rc1 - 14.2.1rc1dev9 - 16.04.0dev0 """ if self.major == "NEXT": return self.major if self.release_candidate is None: rc = "" else: rc = "rc%s" % (self.release_candidate,) if self.dev is None: dev = "" else: dev = "dev%s" % (self.dev,) return '%r.%d.%d%s%s' % (self.major, self.minor, self.micro, rc, dev) base = public short = public local = public def __repr__(self): if self.release_candidate is None: release_candidate = "" else: release_candidate = ", release_candidate=%r" % ( self.release_candidate,) if self.dev is None: dev = "" else: dev = ", dev=%r" % (self.dev,) return '%s(%r, %r, %d, %d%s%s)' % ( self.__class__.__name__, self.package, self.major, self.minor, self.micro, release_candidate, dev) def __str__(self): return '[%s, version %s]' % ( self.package, self.short()) def __cmp__(self, other): """ Compare two versions, considering major versions, minor versions, micro versions, then release candidates. Package names are case insensitive. A version with a release candidate is always less than a version without a release candidate. If both versions have release candidates, they will be included in the comparison. @param other: Another version. @type other: L{Version} @return: NotImplemented when the other object is not a Version, or one of -1, 0, or 1. @raise IncomparableVersions: when the package names of the versions differ. """ if not isinstance(other, self.__class__): return NotImplemented if self.package.lower() != other.package.lower(): raise IncomparableVersions("%r != %r" % (self.package, other.package)) if self.major == "NEXT": major = _inf else: major = self.major if self.release_candidate is None: release_candidate = _inf else: release_candidate = self.release_candidate if self.dev is None: dev = _inf else: dev = self.dev if other.major == "NEXT": othermajor = _inf else: othermajor = other.major if other.release_candidate is None: otherrc = _inf else: otherrc = other.release_candidate if other.dev is None: otherdev = _inf else: otherdev = other.dev x = _cmp((major, self.minor, self.micro, release_candidate, dev), (othermajor, other.minor, other.micro, otherrc, otherdev)) return x def getVersionString(version): """ Get a friendly string for the given version object. @param version: A L{Version} object. @return: A string containing the package and short version number. """ result = '%s %s' % (version.package, version.short()) return result def _get_version(dist, keyword, value): """ Get the version from the package listed in the Distribution. """ if not value: return from distutils.command import build_py sp_command = build_py.build_py(dist) sp_command.finalize_options() for item in sp_command.find_all_modules(): if item[1] == "_version": version_file = {} with open(item[2]) as f: exec(f.read(), version_file) dist.metadata.version = version_file["__version__"].public() return None raise Exception("No _version.py found.") from ._version import __version__ # noqa __all__ = ["__version__", "Version", "getVersionString"] ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/incremental/_version.py ================================================ """ Provides Incremental version information. """ # This file is auto-generated! Do not edit! # Use `python -m incremental.update Incremental` to change this file. from incremental import Version __version__ = Version('Incremental', 17, 5, 0) __all__ = ["__version__"] ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/incremental/tests/__init__.py ================================================ ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/incremental/tests/test_update.py ================================================ # Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. """ Tests for L{incremental.update}. """ from __future__ import division, absolute_import import sys import os import datetime from twisted.python.filepath import FilePath from twisted.python.compat import NativeStringIO from twisted.trial.unittest import TestCase from incremental.update import _run, run class NonCreatedUpdateTests(TestCase): def setUp(self): self.srcdir = FilePath(self.mktemp()) self.srcdir.makedirs() packagedir = self.srcdir.child('inctestpkg') packagedir.makedirs() packagedir.child('__init__.py').setContent(b""" from incremental import Version introduced_in = Version('inctestpkg', 'NEXT', 0, 0).short() next_released_version = "inctestpkg NEXT" """) self.getcwd = lambda: self.srcdir.path self.packagedir = packagedir class Date(object): year = 2016 month = 8 self.date = Date() def test_create(self): """ `incremental.update package --create` initialises the version. """ self.assertFalse(self.packagedir.child("_version.py").exists()) out = [] _run('inctestpkg', path=None, newversion=None, patch=False, rc=False, dev=False, create=True, _date=self.date, _getcwd=self.getcwd, _print=out.append) self.assertTrue(self.packagedir.child("_version.py").exists()) self.assertEqual(self.packagedir.child("_version.py").getContent(), b'''""" Provides inctestpkg version information. """ # This file is auto-generated! Do not edit! # Use `python -m incremental.update inctestpkg` to change this file. from incremental import Version __version__ = Version('inctestpkg', 16, 8, 0) __all__ = ["__version__"] ''') class MissingTests(TestCase): def setUp(self): self.srcdir = FilePath(self.mktemp()) self.srcdir.makedirs() self.srcdir.child('srca').makedirs() packagedir = self.srcdir.child('srca').child('inctestpkg') packagedir.makedirs() packagedir.child('__init__.py').setContent(b""" from incremental import Version introduced_in = Version('inctestpkg', 'NEXT', 0, 0).short() next_released_version = "inctestpkg NEXT" """) packagedir.child('_version.py').setContent(b""" from incremental import Version __version__ = Version('inctestpkg', 1, 2, 3) __all__ = ["__version__"] """) self.getcwd = lambda: self.srcdir.path self.packagedir = packagedir class Date(object): year = 2016 month = 8 self.date = Date() def test_path(self): """ `incremental.update package --dev` raises and quits if it can't find the package. """ out = [] with self.assertRaises(ValueError): _run(u'inctestpkg', path=None, newversion=None, patch=False, rc=False, dev=True, create=False, _date=self.date, _getcwd=self.getcwd, _print=out.append) class CreatedUpdateInSrcTests(TestCase): def setUp(self): self.srcdir = FilePath(self.mktemp()) self.srcdir.makedirs() self.srcdir.child('src').makedirs() packagedir = self.srcdir.child('src').child('inctestpkg') packagedir.makedirs() packagedir.child('__init__.py').setContent(b""" from incremental import Version introduced_in = Version('inctestpkg', 'NEXT', 0, 0).short() next_released_version = "inctestpkg NEXT" """) packagedir.child('_version.py').setContent(b""" from incremental import Version __version__ = Version('inctestpkg', 1, 2, 3) __all__ = ["__version__"] """) self.getcwd = lambda: self.srcdir.path self.packagedir = packagedir class Date(object): year = 2016 month = 8 self.date = Date() def test_path(self): """ `incremental.update package --path= --dev` increments the dev version of the package on the given path """ out = [] _run(u'inctestpkg', path=None, newversion=None, patch=False, rc=False, dev=True, create=False, _date=self.date, _getcwd=self.getcwd, _print=out.append) self.assertTrue(self.packagedir.child("_version.py").exists()) self.assertEqual(self.packagedir.child("_version.py").getContent(), b'''""" Provides inctestpkg version information. """ # This file is auto-generated! Do not edit! # Use `python -m incremental.update inctestpkg` to change this file. from incremental import Version __version__ = Version('inctestpkg', 1, 2, 3, dev=0) __all__ = ["__version__"] ''') _run(u'inctestpkg', path=None, newversion=None, patch=False, rc=False, dev=True, create=False, _date=self.date, _getcwd=self.getcwd, _print=out.append) self.assertTrue(self.packagedir.child("_version.py").exists()) self.assertEqual(self.packagedir.child("_version.py").getContent(), b'''""" Provides inctestpkg version information. """ # This file is auto-generated! Do not edit! # Use `python -m incremental.update inctestpkg` to change this file. from incremental import Version __version__ = Version('inctestpkg', 1, 2, 3, dev=1) __all__ = ["__version__"] ''') class CreatedUpdateTests(TestCase): maxDiff = None def setUp(self): self.srcdir = FilePath(self.mktemp()) self.srcdir.makedirs() packagedir = self.srcdir.child('inctestpkg') packagedir.makedirs() packagedir.child('__init__.py').setContent(b""" from incremental import Version introduced_in = Version('inctestpkg', 'NEXT', 0, 0).short() next_released_version = "inctestpkg NEXT" """) packagedir.child('_version.py').setContent(b""" from incremental import Version __version__ = Version('inctestpkg', 1, 2, 3) __all__ = ["__version__"] """) self.getcwd = lambda: self.srcdir.path self.packagedir = packagedir class Date(object): year = 2016 month = 8 self.date = Date() def test_path(self): """ `incremental.update package --path= --dev` increments the dev version of the package on the given path """ out = [] _run(u'inctestpkg', path=self.packagedir.path, newversion=None, patch=False, rc=False, dev=True, create=False, _date=self.date, _print=out.append) self.assertTrue(self.packagedir.child("_version.py").exists()) self.assertEqual(self.packagedir.child("_version.py").getContent(), b'''""" Provides inctestpkg version information. """ # This file is auto-generated! Do not edit! # Use `python -m incremental.update inctestpkg` to change this file. from incremental import Version __version__ = Version('inctestpkg', 1, 2, 3, dev=0) __all__ = ["__version__"] ''') def test_dev(self): """ `incremental.update package --dev` increments the dev version. """ out = [] _run(u'inctestpkg', path=None, newversion=None, patch=False, rc=False, dev=True, create=False, _date=self.date, _getcwd=self.getcwd, _print=out.append) self.assertTrue(self.packagedir.child("_version.py").exists()) self.assertEqual(self.packagedir.child("_version.py").getContent(), b'''""" Provides inctestpkg version information. """ # This file is auto-generated! Do not edit! # Use `python -m incremental.update inctestpkg` to change this file. from incremental import Version __version__ = Version('inctestpkg', 1, 2, 3, dev=0) __all__ = ["__version__"] ''') def test_patch(self): """ `incremental.update package --patch` increments the patch version. """ out = [] _run(u'inctestpkg', path=None, newversion=None, patch=True, rc=False, dev=False, create=False, _date=self.date, _getcwd=self.getcwd, _print=out.append) self.assertEqual(self.packagedir.child("_version.py").getContent(), b'''""" Provides inctestpkg version information. """ # This file is auto-generated! Do not edit! # Use `python -m incremental.update inctestpkg` to change this file. from incremental import Version __version__ = Version('inctestpkg', 1, 2, 4) __all__ = ["__version__"] ''') self.assertEqual(self.packagedir.child("__init__.py").getContent(), b""" from incremental import Version introduced_in = Version('inctestpkg', 1, 2, 4).short() next_released_version = "inctestpkg 1.2.4" """) def test_patch_with_prerelease_and_dev(self): """ `incremental.update package --patch` increments the patch version, and disregards any old prerelease/dev versions. """ self.packagedir.child('_version.py').setContent(b""" from incremental import Version __version__ = Version('inctestpkg', 1, 2, 3, release_candidate=1, dev=2) __all__ = ["__version__"] """) out = [] _run(u'inctestpkg', path=None, newversion=None, patch=True, rc=False, dev=False, create=False, _date=self.date, _getcwd=self.getcwd, _print=out.append) self.assertEqual(self.packagedir.child("_version.py").getContent(), b'''""" Provides inctestpkg version information. """ # This file is auto-generated! Do not edit! # Use `python -m incremental.update inctestpkg` to change this file. from incremental import Version __version__ = Version('inctestpkg', 1, 2, 4) __all__ = ["__version__"] ''') def test_rc_patch(self): """ `incremental.update package --patch --rc` increments the patch version and makes it a release candidate. """ out = [] _run(u'inctestpkg', path=None, newversion=None, patch=True, rc=True, dev=False, create=False, _date=self.date, _getcwd=self.getcwd, _print=out.append) self.assertEqual(self.packagedir.child("_version.py").getContent(), b'''""" Provides inctestpkg version information. """ # This file is auto-generated! Do not edit! # Use `python -m incremental.update inctestpkg` to change this file. from incremental import Version __version__ = Version('inctestpkg', 1, 2, 4, release_candidate=1) __all__ = ["__version__"] ''') self.assertEqual(self.packagedir.child("__init__.py").getContent(), b""" from incremental import Version introduced_in = Version('inctestpkg', 1, 2, 4, release_candidate=1).short() next_released_version = "inctestpkg 1.2.4rc1" """) def test_rc_with_existing_rc(self): """ `incremental.update package --rc` increments the rc version if the existing version is an rc, and discards any dev version. """ self.packagedir.child('_version.py').setContent(b""" from incremental import Version __version__ = Version('inctestpkg', 1, 2, 3, release_candidate=1, dev=2) __all__ = ["__version__"] """) out = [] _run(u'inctestpkg', path=None, newversion=None, patch=False, rc=True, dev=False, create=False, _date=self.date, _getcwd=self.getcwd, _print=out.append) self.assertEqual(self.packagedir.child("_version.py").getContent(), b'''""" Provides inctestpkg version information. """ # This file is auto-generated! Do not edit! # Use `python -m incremental.update inctestpkg` to change this file. from incremental import Version __version__ = Version('inctestpkg', 1, 2, 3, release_candidate=2) __all__ = ["__version__"] ''') self.assertEqual(self.packagedir.child("__init__.py").getContent(), b""" from incremental import Version introduced_in = Version('inctestpkg', 1, 2, 3, release_candidate=2).short() next_released_version = "inctestpkg 1.2.3rc2" """) def test_rc_with_no_rc(self): """ `incremental.update package --rc`, when the package is not a release candidate, will issue a new major/minor rc, and disregards the micro and dev. """ self.packagedir.child('_version.py').setContent(b""" from incremental import Version __version__ = Version('inctestpkg', 1, 2, 3, dev=2) __all__ = ["__version__"] """) out = [] _run(u'inctestpkg', path=None, newversion=None, patch=False, rc=True, dev=False, create=False, _date=self.date, _getcwd=self.getcwd, _print=out.append) self.assertEqual(self.packagedir.child("_version.py").getContent(), b'''""" Provides inctestpkg version information. """ # This file is auto-generated! Do not edit! # Use `python -m incremental.update inctestpkg` to change this file. from incremental import Version __version__ = Version('inctestpkg', 16, 8, 0, release_candidate=1) __all__ = ["__version__"] ''') self.assertEqual(self.packagedir.child("__init__.py").getContent(), b""" from incremental import Version introduced_in = Version('inctestpkg', 16, 8, 0, release_candidate=1).short() next_released_version = "inctestpkg 16.8.0rc1" """) def test_full_with_rc(self): """ `incremental.update package`, when the package is a release candidate, will issue the major/minor, sans release candidate or dev. """ out = [] _run(u'inctestpkg', path=None, newversion=None, patch=False, rc=True, dev=False, create=False, _date=self.date, _getcwd=self.getcwd, _print=out.append) self.assertEqual(self.packagedir.child("_version.py").getContent(), b'''""" Provides inctestpkg version information. """ # This file is auto-generated! Do not edit! # Use `python -m incremental.update inctestpkg` to change this file. from incremental import Version __version__ = Version('inctestpkg', 16, 8, 0, release_candidate=1) __all__ = ["__version__"] ''') self.assertEqual(self.packagedir.child("__init__.py").getContent(), b""" from incremental import Version introduced_in = Version('inctestpkg', 16, 8, 0, release_candidate=1).short() next_released_version = "inctestpkg 16.8.0rc1" """) _run(u'inctestpkg', path=None, newversion=None, patch=False, rc=False, dev=False, create=False, _date=self.date, _getcwd=self.getcwd, _print=out.append) self.assertEqual(self.packagedir.child("_version.py").getContent(), b'''""" Provides inctestpkg version information. """ # This file is auto-generated! Do not edit! # Use `python -m incremental.update inctestpkg` to change this file. from incremental import Version __version__ = Version('inctestpkg', 16, 8, 0) __all__ = ["__version__"] ''') self.assertEqual(self.packagedir.child("__init__.py").getContent(), b""" from incremental import Version introduced_in = Version('inctestpkg', 16, 8, 0).short() next_released_version = "inctestpkg 16.8.0" """) def test_full_without_rc(self): """ `incremental.update package`, when the package is NOT a release candidate, will raise an error. """ out = [] with self.assertRaises(ValueError) as e: _run(u'inctestpkg', path=None, newversion=None, patch=False, rc=False, dev=False, create=False, _date=self.date, _getcwd=self.getcwd, _print=out.append) self.assertEqual( e.exception.args[0], "You need to issue a rc before updating the major/minor") def test_no_mix_newversion(self): """ The `--newversion` flag can't be mixed with --patch, --rc, or --dev. """ out = [] with self.assertRaises(ValueError) as e: _run(u'inctestpkg', path=None, newversion="1", patch=True, rc=False, dev=False, create=False, _date=self.date, _getcwd=self.getcwd, _print=out.append) self.assertEqual(e.exception.args[0], "Only give --newversion") with self.assertRaises(ValueError) as e: _run(u'inctestpkg', path=None, newversion="1", patch=False, rc=True, dev=False, create=False, _date=self.date, _getcwd=self.getcwd, _print=out.append) self.assertEqual(e.exception.args[0], "Only give --newversion") with self.assertRaises(ValueError) as e: _run(u'inctestpkg', path=None, newversion="1", patch=False, rc=False, dev=True, create=False, _date=self.date, _getcwd=self.getcwd, _print=out.append) self.assertEqual(e.exception.args[0], "Only give --newversion") def test_no_mix_dev(self): """ The `--dev` flag can't be mixed with --patch, or --rc. """ out = [] with self.assertRaises(ValueError) as e: _run(u'inctestpkg', path=None, newversion=None, patch=True, rc=False, dev=True, create=False, _date=self.date, _getcwd=self.getcwd, _print=out.append) self.assertEqual(e.exception.args[0], "Only give --dev") with self.assertRaises(ValueError) as e: _run(u'inctestpkg', path=None, newversion=None, patch=False, rc=True, dev=True, create=False, _date=self.date, _getcwd=self.getcwd, _print=out.append) self.assertEqual(e.exception.args[0], "Only give --dev") def test_no_mix_create(self): """ The `--create` flag can't be mixed with --patch, --rc, --dev, or --newversion. """ out = [] with self.assertRaises(ValueError) as e: _run(u'inctestpkg', path=None, newversion=None, patch=True, rc=False, dev=False, create=True, _date=self.date, _getcwd=self.getcwd, _print=out.append) self.assertEqual(e.exception.args[0], "Only give --create") with self.assertRaises(ValueError) as e: _run(u'inctestpkg', path=None, newversion="1", patch=False, rc=False, dev=False, create=True, _date=self.date, _getcwd=self.getcwd, _print=out.append) self.assertEqual(e.exception.args[0], "Only give --create") with self.assertRaises(ValueError) as e: _run(u'inctestpkg', path=None, newversion=None, patch=False, rc=True, dev=False, create=True, _date=self.date, _getcwd=self.getcwd, _print=out.append) self.assertEqual(e.exception.args[0], "Only give --create") with self.assertRaises(ValueError) as e: _run(u'inctestpkg', path=None, newversion=None, patch=False, rc=False, dev=True, create=True, _date=self.date, _getcwd=self.getcwd, _print=out.append) self.assertEqual(e.exception.args[0], "Only give --create") def test_newversion(self): """ `incremental.update package --newversion=1.2.3rc1dev3`, will set that version in the package. """ out = [] _run(u'inctestpkg', path=None, newversion="1.2.3rc1dev3", patch=False, rc=False, dev=False, create=False, _date=self.date, _getcwd=self.getcwd, _print=out.append) self.assertEqual(self.packagedir.child("_version.py").getContent(), b'''""" Provides inctestpkg version information. """ # This file is auto-generated! Do not edit! # Use `python -m incremental.update inctestpkg` to change this file. from incremental import Version __version__ = Version('inctestpkg', 1, 2, 3, release_candidate=1, dev=3) __all__ = ["__version__"] ''') self.assertEqual(self.packagedir.child("__init__.py").getContent(), (b""" from incremental import Version introduced_in = Version('inctestpkg', 1, 2, 3, """ b"""release_candidate=1, dev=3).short() next_released_version = "inctestpkg 1.2.3rc1dev3" """)) def test_newversion_bare(self): """ `incremental.update package --newversion=1`, will set that version in the package. """ out = [] _run(u'inctestpkg', path=None, newversion="1", patch=False, rc=False, dev=False, create=False, _date=self.date, _getcwd=self.getcwd, _print=out.append) self.assertEqual(self.packagedir.child("_version.py").getContent(), b'''""" Provides inctestpkg version information. """ # This file is auto-generated! Do not edit! # Use `python -m incremental.update inctestpkg` to change this file. from incremental import Version __version__ = Version('inctestpkg', 1, 0, 0) __all__ = ["__version__"] ''') self.assertEqual(self.packagedir.child("__init__.py").getContent(), b""" from incremental import Version introduced_in = Version('inctestpkg', 1, 0, 0).short() next_released_version = "inctestpkg 1.0.0" """) class ScriptTests(TestCase): def setUp(self): self.srcdir = FilePath(self.mktemp()) self.srcdir.makedirs() self.srcdir.child('src').makedirs() packagedir = self.srcdir.child('src').child('inctestpkg') packagedir.makedirs() packagedir.child('__init__.py').setContent(b""" from incremental import Version introduced_in = Version('inctestpkg', 'NEXT', 0, 0).short() next_released_version = "inctestpkg NEXT" """) packagedir.child('_version.py').setContent(b""" from incremental import Version __version__ = Version('inctestpkg', 1, 2, 3) __all__ = ["__version__"] """) self.getcwd = lambda: self.srcdir.path self.packagedir = packagedir class Date(object): year = 2016 month = 8 class DateModule(object): def today(self): return Date() self.date = DateModule() def test_run(self): """ Calling run() with no args will cause it to print help. """ stringio = NativeStringIO() self.patch(sys, 'stdout', stringio) with self.assertRaises(SystemExit) as e: run(["--help"]) self.assertEqual(e.exception.args[0], 0) self.assertIn("Show this message and exit", stringio.getvalue()) def test_insufficient_args(self): """ Calling run() with no args will cause it to print help. """ stringio = NativeStringIO() self.patch(sys, 'stdout', stringio) self.patch(os, 'getcwd', self.getcwd) self.patch(datetime, 'date', self.date) with self.assertRaises(SystemExit) as e: run(["inctestpkg", "--rc"]) self.assertEqual(e.exception.args[0], 0) self.assertIn("Updating codebase", stringio.getvalue()) self.assertEqual(self.packagedir.child("_version.py").getContent(), b'''""" Provides inctestpkg version information. """ # This file is auto-generated! Do not edit! # Use `python -m incremental.update inctestpkg` to change this file. from incremental import Version __version__ = Version('inctestpkg', 16, 8, 0, release_candidate=1) __all__ = ["__version__"] ''') self.assertEqual(self.packagedir.child("__init__.py").getContent(), b""" from incremental import Version introduced_in = Version('inctestpkg', 16, 8, 0, release_candidate=1).short() next_released_version = "inctestpkg 16.8.0rc1" """) ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/incremental/tests/test_version.py ================================================ # Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. """ Tests for L{incremental}. """ from __future__ import division, absolute_import import operator from incremental import getVersionString, IncomparableVersions from incremental import Version, _inf from twisted.trial.unittest import TestCase class VersionsTests(TestCase): def test_localIsShort(self): """ The local version is the same as the short version. """ va = Version("dummy", 1, 0, 0, release_candidate=1, dev=3) self.assertEqual(va.local(), va.short()) def test_versionComparison(self): """ Versions can be compared for equality and order. """ va = Version("dummy", 1, 0, 0) vb = Version("dummy", 0, 1, 0) self.assertTrue(va > vb) self.assertTrue(vb < va) self.assertTrue(va >= vb) self.assertTrue(vb <= va) self.assertTrue(va != vb) self.assertTrue(vb == Version("dummy", 0, 1, 0)) self.assertTrue(vb == vb) def test_versionComparisonCaseInsensitive(self): """ Version package names are case insensitive. """ va = Version("dummy", 1, 0, 0) vb = Version("DuMmY", 0, 1, 0) self.assertTrue(va > vb) self.assertTrue(vb < va) self.assertTrue(va >= vb) self.assertTrue(vb <= va) self.assertTrue(va != vb) self.assertTrue(vb == Version("dummy", 0, 1, 0)) self.assertTrue(vb == vb) def test_comparingNEXTReleases(self): """ NEXT releases are always larger than numbered releases. """ va = Version("whatever", "NEXT", 0, 0) vb = Version("whatever", 1, 0, 0) self.assertTrue(va > vb) self.assertFalse(va < vb) self.assertNotEquals(vb, va) def test_NEXTMustBeAlone(self): """ NEXT releases must always have the rest of the numbers set to 0. """ with self.assertRaises(ValueError): Version("whatever", "NEXT", 1, 0, release_candidate=0, dev=0) with self.assertRaises(ValueError): Version("whatever", "NEXT", 0, 1, release_candidate=0, dev=0) with self.assertRaises(ValueError): Version("whatever", "NEXT", 0, 0, release_candidate=1, dev=0) with self.assertRaises(ValueError): Version("whatever", "NEXT", 0, 0, release_candidate=0, dev=1) def test_comparingNEXTReleasesEqual(self): """ NEXT releases are equal to each other. """ va = Version("whatever", "NEXT", 0, 0) vb = Version("whatever", "NEXT", 0, 0) self.assertEquals(vb, va) def test_comparingPrereleasesWithReleases(self): """ Prereleases are always less than versions without prereleases. """ va = Version("whatever", 1, 0, 0, prerelease=1) vb = Version("whatever", 1, 0, 0) self.assertTrue(va < vb) self.assertFalse(va > vb) self.assertNotEquals(vb, va) def test_prereleaseDeprecated(self): """ Passing 'prerelease' to Version is deprecated. """ Version("whatever", 1, 0, 0, prerelease=1) warnings = self.flushWarnings([self.test_prereleaseDeprecated]) self.assertEqual(len(warnings), 1) self.assertEqual( warnings[0]['message'], ("Passing prerelease to incremental.Version was deprecated in " "Incremental 16.9.0. Please pass release_candidate instead.")) def test_prereleaseAttributeDeprecated(self): """ Accessing 'prerelease' on a Version is deprecated. """ va = Version("whatever", 1, 0, 0, release_candidate=1) va.prerelease warnings = self.flushWarnings( [self.test_prereleaseAttributeDeprecated]) self.assertEqual(len(warnings), 1) self.assertEqual( warnings[0]['message'], ("Accessing incremental.Version.prerelease was deprecated in " "Incremental 16.9.0. Use Version.release_candidate instead.")) def test_comparingReleaseCandidatesWithReleases(self): """ Release Candidates are always less than versions without release candidates. """ va = Version("whatever", 1, 0, 0, release_candidate=1) vb = Version("whatever", 1, 0, 0) self.assertTrue(va < vb) self.assertFalse(va > vb) self.assertNotEquals(vb, va) def test_comparingDevReleasesWithReleases(self): """ Dev releases are always less than versions without dev releases. """ va = Version("whatever", 1, 0, 0, dev=1) vb = Version("whatever", 1, 0, 0) self.assertTrue(va < vb) self.assertFalse(va > vb) self.assertNotEquals(vb, va) def test_rcEqualspre(self): """ Release Candidates are equal to prereleases. """ va = Version("whatever", 1, 0, 0, release_candidate=1) vb = Version("whatever", 1, 0, 0, prerelease=1) self.assertTrue(va == vb) self.assertFalse(va != vb) def test_rcOrpreButNotBoth(self): """ Release Candidate and prerelease can't both be given. """ with self.assertRaises(ValueError): Version("whatever", 1, 0, 0, prerelease=1, release_candidate=1) def test_comparingReleaseCandidates(self): """ The value specified as the release candidate is used in version comparisons. """ va = Version("whatever", 1, 0, 0, release_candidate=1) vb = Version("whatever", 1, 0, 0, release_candidate=2) self.assertTrue(va < vb) self.assertTrue(vb > va) self.assertTrue(va <= vb) self.assertTrue(vb >= va) self.assertTrue(va != vb) self.assertTrue(vb == Version("whatever", 1, 0, 0, release_candidate=2)) self.assertTrue(va == va) def test_comparingDev(self): """ The value specified as the dev release is used in version comparisons. """ va = Version("whatever", 1, 0, 0, dev=1) vb = Version("whatever", 1, 0, 0, dev=2) self.assertTrue(va < vb) self.assertTrue(vb > va) self.assertTrue(va <= vb) self.assertTrue(vb >= va) self.assertTrue(va != vb) self.assertTrue(vb == Version("whatever", 1, 0, 0, dev=2)) self.assertTrue(va == va) def test_comparingDevAndRC(self): """ The value specified as the dev release and release candidate is used in version comparisons. """ va = Version("whatever", 1, 0, 0, release_candidate=1, dev=1) vb = Version("whatever", 1, 0, 0, release_candidate=1, dev=2) self.assertTrue(va < vb) self.assertTrue(vb > va) self.assertTrue(va <= vb) self.assertTrue(vb >= va) self.assertTrue(va != vb) self.assertTrue(vb == Version("whatever", 1, 0, 0, release_candidate=1, dev=2)) self.assertTrue(va == va) def test_comparingDevAndRCDifferent(self): """ The value specified as the dev release and release candidate is used in version comparisons. """ va = Version("whatever", 1, 0, 0, release_candidate=1, dev=1) vb = Version("whatever", 1, 0, 0, release_candidate=2, dev=1) self.assertTrue(va < vb) self.assertTrue(vb > va) self.assertTrue(va <= vb) self.assertTrue(vb >= va) self.assertTrue(va != vb) self.assertTrue(vb == Version("whatever", 1, 0, 0, release_candidate=2, dev=1)) self.assertTrue(va == va) def test_infComparison(self): """ L{_inf} is equal to L{_inf}. This is a regression test. """ self.assertEqual(_inf, _inf) def test_disallowBuggyComparisons(self): """ The package names of the Version objects need to be the same. """ self.assertRaises(IncomparableVersions, operator.eq, Version("dummy", 1, 0, 0), Version("dumym", 1, 0, 0)) def test_notImplementedComparisons(self): """ Comparing a L{Version} to some other object type results in C{NotImplemented}. """ va = Version("dummy", 1, 0, 0) vb = ("dummy", 1, 0, 0) # a tuple is not a Version object self.assertEqual(va.__cmp__(vb), NotImplemented) def test_repr(self): """ Calling C{repr} on a version returns a human-readable string representation of the version. """ self.assertEqual(repr(Version("dummy", 1, 2, 3)), "Version('dummy', 1, 2, 3)") def test_reprWithPrerelease(self): """ Calling C{repr} on a version with a prerelease returns a human-readable string representation of the version including the prerelease as a release candidate.. """ self.assertEqual(repr(Version("dummy", 1, 2, 3, prerelease=4)), "Version('dummy', 1, 2, 3, release_candidate=4)") def test_reprWithReleaseCandidate(self): """ Calling C{repr} on a version with a release candidate returns a human-readable string representation of the version including the rc. """ self.assertEqual(repr(Version("dummy", 1, 2, 3, release_candidate=4)), "Version('dummy', 1, 2, 3, release_candidate=4)") def test_devWithReleaseCandidate(self): """ Calling C{repr} on a version with a dev release returns a human-readable string representation of the version including the dev release. """ self.assertEqual(repr(Version("dummy", 1, 2, 3, dev=4)), "Version('dummy', 1, 2, 3, dev=4)") def test_str(self): """ Calling C{str} on a version returns a human-readable string representation of the version. """ self.assertEqual(str(Version("dummy", 1, 2, 3)), "[dummy, version 1.2.3]") def test_strWithPrerelease(self): """ Calling C{str} on a version with a prerelease includes the prerelease as a release candidate. """ self.assertEqual(str(Version("dummy", 1, 0, 0, prerelease=1)), "[dummy, version 1.0.0rc1]") def test_strWithReleaseCandidate(self): """ Calling C{str} on a version with a release candidate includes the release candidate. """ self.assertEqual(str(Version("dummy", 1, 0, 0, release_candidate=1)), "[dummy, version 1.0.0rc1]") def test_strWithDevAndReleaseCandidate(self): """ Calling C{str} on a version with a release candidate and dev release includes the release candidate and the dev release. """ self.assertEqual(str(Version("dummy", 1, 0, 0, release_candidate=1, dev=2)), "[dummy, version 1.0.0rc1dev2]") def test_strWithDev(self): """ Calling C{str} on a version with a dev release includes the dev release. """ self.assertEqual(str(Version("dummy", 1, 0, 0, dev=1)), "[dummy, version 1.0.0dev1]") def testShort(self): self.assertEqual(Version('dummy', 1, 2, 3).short(), '1.2.3') def test_getVersionString(self): """ L{getVersionString} returns a string with the package name and the short version number. """ self.assertEqual( 'Twisted 8.0.0', getVersionString(Version('Twisted', 8, 0, 0))) def test_getVersionStringWithPrerelease(self): """ L{getVersionString} includes the prerelease as a release candidate, if any. """ self.assertEqual( getVersionString(Version("whatever", 8, 0, 0, prerelease=1)), "whatever 8.0.0rc1") def test_getVersionStringWithReleaseCandidate(self): """ L{getVersionString} includes the release candidate, if any. """ self.assertEqual( getVersionString(Version("whatever", 8, 0, 0, release_candidate=1)), "whatever 8.0.0rc1") def test_getVersionStringWithDev(self): """ L{getVersionString} includes the dev release, if any. """ self.assertEqual( getVersionString(Version("whatever", 8, 0, 0, dev=1)), "whatever 8.0.0dev1") def test_getVersionStringWithDevAndRC(self): """ L{getVersionString} includes the dev release and release candidate, if any. """ self.assertEqual( getVersionString(Version("whatever", 8, 0, 0, release_candidate=2, dev=1)), "whatever 8.0.0rc2dev1") def test_baseWithNEXT(self): """ The C{base} method returns just "NEXT" when NEXT is the major version. """ self.assertEqual(Version("foo", "NEXT", 0, 0).base(), "NEXT") def test_base(self): """ The C{base} method returns a very simple representation of the version. """ self.assertEqual(Version("foo", 1, 0, 0).base(), "1.0.0") def test_baseWithPrerelease(self): """ The base version includes 'rcX' for versions with prereleases. """ self.assertEqual(Version("foo", 1, 0, 0, prerelease=8).base(), "1.0.0rc8") def test_baseWithDev(self): """ The base version includes 'devX' for versions with dev releases. """ self.assertEqual(Version("foo", 1, 0, 0, dev=8).base(), "1.0.0dev8") def test_baseWithReleaseCandidate(self): """ The base version includes 'rcX' for versions with prereleases. """ self.assertEqual(Version("foo", 1, 0, 0, release_candidate=8).base(), "1.0.0rc8") def test_baseWithDevAndRC(self): """ The base version includes 'rcXdevX' for versions with dev releases and a release candidate. """ self.assertEqual(Version("foo", 1, 0, 0, release_candidate=2, dev=8).base(), "1.0.0rc2dev8") ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/incremental/update.py ================================================ # Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. from __future__ import absolute_import, division, print_function import click import os import datetime from incremental import Version from twisted.python.filepath import FilePath _VERSIONPY_TEMPLATE = '''""" Provides %s version information. """ # This file is auto-generated! Do not edit! # Use `python -m incremental.update %s` to change this file. from incremental import Version __version__ = %s __all__ = ["__version__"] ''' _YEAR_START = 2000 def _findPath(path, package): cwd = FilePath(path) src_dir = cwd.child("src").child(package.lower()) current_dir = cwd.child(package.lower()) if src_dir.isdir(): return src_dir elif current_dir.isdir(): return current_dir else: raise ValueError(("Can't find under `./src` or `./`. Check the " "package name is right (note that we expect your " "package name to be lower cased), or pass it using " "'--path'.")) def _existing_version(path): version_info = {} with path.child("_version.py").open('r') as f: exec(f.read(), version_info) return version_info["__version__"] def _run(package, path, newversion, patch, rc, dev, create, _date=None, _getcwd=None, _print=print): if not _getcwd: _getcwd = os.getcwd if not _date: _date = datetime.date.today() if type(package) != str: package = package.encode('utf8') if not path: path = _findPath(_getcwd(), package) else: path = FilePath(path) if newversion and patch or newversion and dev or newversion and rc: raise ValueError("Only give --newversion") if dev and patch or dev and rc: raise ValueError("Only give --dev") if create and dev or create and patch or create and rc or \ create and newversion: raise ValueError("Only give --create") if newversion: from pkg_resources import parse_version existing = _existing_version(path) st_version = parse_version(newversion)._version release = list(st_version.release) if len(release) == 1: release.append(0) if len(release) == 2: release.append(0) v = Version( package, *release, release_candidate=st_version.pre[1] if st_version.pre else None, dev=st_version.dev[1] if st_version.dev else None) elif create: v = Version(package, _date.year - _YEAR_START, _date.month, 0) existing = v elif rc and not patch: existing = _existing_version(path) if existing.release_candidate: v = Version(package, existing.major, existing.minor, existing.micro, existing.release_candidate + 1) else: v = Version(package, _date.year - _YEAR_START, _date.month, 0, 1) elif patch: if rc: rc = 1 else: rc = None existing = _existing_version(path) v = Version(package, existing.major, existing.minor, existing.micro + 1, rc) elif dev: existing = _existing_version(path) if existing.dev is None: _dev = 0 else: _dev = existing.dev + 1 v = Version(package, existing.major, existing.minor, existing.micro, existing.release_candidate, dev=_dev) else: existing = _existing_version(path) if existing.release_candidate: v = Version(package, existing.major, existing.minor, existing.micro) else: raise ValueError( "You need to issue a rc before updating the major/minor") NEXT_repr = repr(Version(package, "NEXT", 0, 0)).split("#")[0] NEXT_repr_bytes = NEXT_repr.encode('utf8') version_repr = repr(v).split("#")[0] version_repr_bytes = version_repr.encode('utf8') existing_version_repr = repr(existing).split("#")[0] existing_version_repr_bytes = existing_version_repr.encode('utf8') _print("Updating codebase to %s" % (v.public())) for x in path.walk(): if not x.isfile(): continue original_content = x.getContent() content = original_content # Replace previous release_candidate calls to the new one if existing.release_candidate: content = content.replace(existing_version_repr_bytes, version_repr_bytes) content = content.replace( (package.encode('utf8') + b" " + existing.public().encode('utf8')), (package.encode('utf8') + b" " + v.public().encode('utf8'))) # Replace NEXT Version calls with the new one content = content.replace(NEXT_repr_bytes, version_repr_bytes) content = content.replace(NEXT_repr_bytes.replace(b"'", b'"'), version_repr_bytes) # Replace NEXT with content = content.replace(package.encode('utf8') + b" NEXT", (package.encode('utf8') + b" " + v.public().encode('utf8'))) if content != original_content: _print("Updating %s" % (x.path,)) with x.open('w') as f: f.write(content) _print("Updating %s/_version.py" % (path.path)) with path.child("_version.py").open('w') as f: f.write( (_VERSIONPY_TEMPLATE % ( package, package, version_repr)).encode('utf8')) @click.command() @click.argument('package') @click.option('--path', default=None) @click.option('--newversion', default=None) @click.option('--patch', is_flag=True) @click.option('--rc', is_flag=True) @click.option('--dev', is_flag=True) @click.option('--create', is_flag=True) def run(*args, **kwargs): return _run(*args, **kwargs) if __name__ == '__main__': # pragma: no cover run() ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/incremental-17.5.0.dist-info/DESCRIPTION.rst ================================================ Incremental =========== |travis| |pypi| |coverage| Incremental is a small library that versions your Python projects. API documentation can be found `here `_. Quick Start ----------- Add this to your ``setup.py``\ 's ``setup()`` call, removing any other versioning arguments: .. code:: setup( use_incremental=True, setup_requires=['incremental'], install_requires=['incremental'], # along with any other install dependencies ... } Then run ``python -m incremental.update --create`` (you will need ``click`` installed from PyPI). It will create a file in your package named ``_version.py`` and look like this: .. code:: from incremental import Version __version__ = Version("widgetbox", 17, 1, 0) __all__ = ["__version__"] Then, so users of your project can find your version, in your root package's ``__init__.py`` add: .. code:: from ._version import __version__ Subsequent installations of your project will then use Incremental for versioning. Incremental Versions -------------------- ``incremental.Version`` is a class that represents a version of a given project. It is made up of the following elements (which are given during instantiation): - ``package`` (required), the name of the package this ``Version`` represents. - ``major``, ``minor``, ``micro`` (all required), the X.Y.Z of your project's ``Version``. - ``release_candidate`` (optional), set to 0 or higher to mark this ``Version`` being of a release candidate (also sometimes called a "prerelease"). - ``dev`` (optional), set to 0 or higher to mark this ``Version`` as a development release. You can extract a PEP-440 compatible version string by using the following methods: - ``.local()``, which returns a ``str`` containing the full version plus any Git or SVN information, if available. An example output would be ``"17.1.1rc1+r123"`` or ``"3.7.0+rb2e812003b5d5fcf08efd1dffed6afa98d44ac8c"``. - ``.public()``, which returns a ``str`` containing the full version, without any Git or SVN information. This is the version you should provide to users, or publicly use. An example output would be ``"13.2.0"``, ``"17.1.2dev1"``, or ``"18.8.0rc2"``. Calling ``repr()`` with a ``Version`` will give a Python-source-code representation of it, and calling ``str()`` with a ``Version`` will provide a string similar to ``'[Incremental, version 16.10.1]'``. Updating -------- Incremental includes a tool to automate updating your Incremental-using project's version called ``incremental.update``. It updates the ``_version.py`` file and automatically updates some uses of Incremental versions from an indeterminate version to the current one. It requires ``click`` from PyPI. ``python -m incremental.update `` will perform updates on that package. The commands that can be given after that will determine what the next version is. - ``--newversion=``, to set the project version to a fully-specified version (like 1.2.3, or 17.1.0dev1). - ``--rc``, to set the project version to ``..0rc1`` if the current version is not a release candidate, or bump the release candidate number by 1 if it is. - ``--dev``, to set the project development release number to 0 if it is not a development release, or bump the development release number by 1 if it is. - ``--patch``, to increment the patch number of the release. This will also reset the release candidate number, pass ``--rc`` at the same time to increment the patch number and make it a release candidate. If you give no arguments, it will strip the release candidate number, making it a "full release". Incremental supports "indeterminate" versions, as a stand-in for the next "full" version. This can be used when the version which will be displayed to the end-user is unknown (for example "introduced in" or "deprecated in"). Incremental supports the following indeterminate versions: - ``Version("", "NEXT", 0, 0)`` - `` NEXT`` When you run ``python -m incremental.update --rc``, these will be updated to real versions (assuming the target final version is 17.1.0): - ``Version("", 17, 1, 0, release_candidate=1)`` - `` 17.1.0rc1`` Once the final version is made, it will become: - ``Version("", 17, 1, 0)`` - `` 17.1.0`` .. |coverage| image:: https://codecov.io/github/hawkowl/incremental/coverage.svg?branch=master .. _coverage: https://codecov.io/github/hawkowl/incremental .. |travis| image:: https://travis-ci.org/hawkowl/incremental.svg?branch=master .. _travis: http://travis-ci.org/hawkowl/incremental .. |pypi| image:: http://img.shields.io/pypi/v/incremental.svg .. _pypi: https://pypi.python.org/pypi/incremental ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/incremental-17.5.0.dist-info/INSTALLER ================================================ pip ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/incremental-17.5.0.dist-info/METADATA ================================================ Metadata-Version: 2.0 Name: incremental Version: 17.5.0 Summary: UNKNOWN Home-page: https://github.com/twisted/incremental Author: Amber Brown Author-email: hawkowl@twistedmatrix.com License: MIT Platform: UNKNOWN Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: MIT License Classifier: Programming Language :: Python :: 2 Classifier: Programming Language :: Python :: 2.6 Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: 3.3 Classifier: Programming Language :: Python :: 3.4 Classifier: Programming Language :: Python :: 3.5 Classifier: Programming Language :: Python :: 3.6 Provides-Extra: scripts Requires-Dist: click (>=6.0); extra == 'scripts' Requires-Dist: twisted (>=16.4.0); extra == 'scripts' Incremental =========== |travis| |pypi| |coverage| Incremental is a small library that versions your Python projects. API documentation can be found `here `_. Quick Start ----------- Add this to your ``setup.py``\ 's ``setup()`` call, removing any other versioning arguments: .. code:: setup( use_incremental=True, setup_requires=['incremental'], install_requires=['incremental'], # along with any other install dependencies ... } Then run ``python -m incremental.update --create`` (you will need ``click`` installed from PyPI). It will create a file in your package named ``_version.py`` and look like this: .. code:: from incremental import Version __version__ = Version("widgetbox", 17, 1, 0) __all__ = ["__version__"] Then, so users of your project can find your version, in your root package's ``__init__.py`` add: .. code:: from ._version import __version__ Subsequent installations of your project will then use Incremental for versioning. Incremental Versions -------------------- ``incremental.Version`` is a class that represents a version of a given project. It is made up of the following elements (which are given during instantiation): - ``package`` (required), the name of the package this ``Version`` represents. - ``major``, ``minor``, ``micro`` (all required), the X.Y.Z of your project's ``Version``. - ``release_candidate`` (optional), set to 0 or higher to mark this ``Version`` being of a release candidate (also sometimes called a "prerelease"). - ``dev`` (optional), set to 0 or higher to mark this ``Version`` as a development release. You can extract a PEP-440 compatible version string by using the following methods: - ``.local()``, which returns a ``str`` containing the full version plus any Git or SVN information, if available. An example output would be ``"17.1.1rc1+r123"`` or ``"3.7.0+rb2e812003b5d5fcf08efd1dffed6afa98d44ac8c"``. - ``.public()``, which returns a ``str`` containing the full version, without any Git or SVN information. This is the version you should provide to users, or publicly use. An example output would be ``"13.2.0"``, ``"17.1.2dev1"``, or ``"18.8.0rc2"``. Calling ``repr()`` with a ``Version`` will give a Python-source-code representation of it, and calling ``str()`` with a ``Version`` will provide a string similar to ``'[Incremental, version 16.10.1]'``. Updating -------- Incremental includes a tool to automate updating your Incremental-using project's version called ``incremental.update``. It updates the ``_version.py`` file and automatically updates some uses of Incremental versions from an indeterminate version to the current one. It requires ``click`` from PyPI. ``python -m incremental.update `` will perform updates on that package. The commands that can be given after that will determine what the next version is. - ``--newversion=``, to set the project version to a fully-specified version (like 1.2.3, or 17.1.0dev1). - ``--rc``, to set the project version to ``..0rc1`` if the current version is not a release candidate, or bump the release candidate number by 1 if it is. - ``--dev``, to set the project development release number to 0 if it is not a development release, or bump the development release number by 1 if it is. - ``--patch``, to increment the patch number of the release. This will also reset the release candidate number, pass ``--rc`` at the same time to increment the patch number and make it a release candidate. If you give no arguments, it will strip the release candidate number, making it a "full release". Incremental supports "indeterminate" versions, as a stand-in for the next "full" version. This can be used when the version which will be displayed to the end-user is unknown (for example "introduced in" or "deprecated in"). Incremental supports the following indeterminate versions: - ``Version("", "NEXT", 0, 0)`` - `` NEXT`` When you run ``python -m incremental.update --rc``, these will be updated to real versions (assuming the target final version is 17.1.0): - ``Version("", 17, 1, 0, release_candidate=1)`` - `` 17.1.0rc1`` Once the final version is made, it will become: - ``Version("", 17, 1, 0)`` - `` 17.1.0`` .. |coverage| image:: https://codecov.io/github/hawkowl/incremental/coverage.svg?branch=master .. _coverage: https://codecov.io/github/hawkowl/incremental .. |travis| image:: https://travis-ci.org/hawkowl/incremental.svg?branch=master .. _travis: http://travis-ci.org/hawkowl/incremental .. |pypi| image:: http://img.shields.io/pypi/v/incremental.svg .. _pypi: https://pypi.python.org/pypi/incremental ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/incremental-17.5.0.dist-info/RECORD ================================================ exampleproj/__init__.py,sha256=wVUVOn7507BCBqkRvFS9HK53UcUjXzC5msC6bJRhS6s,229 exampleproj/__pycache__/__init__.cpython-36.pyc,, exampleproj/__pycache__/_version.cpython-36.pyc,, exampleproj/_version.py,sha256=rg3bI25RROVfWYekpRHyamIjC57sP9ccNh-WT810ldo,220 incremental-17.5.0.dist-info/DESCRIPTION.rst,sha256=CEhuO8j_yz24FpoelRI9wsJ--6kUA9hIksHUdhrgqLY,4818 incremental-17.5.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 incremental-17.5.0.dist-info/METADATA,sha256=jxH6e70AY99WYfgmo1BM9ovHcuIv3411Gyw8bqsZKyk,5651 incremental-17.5.0.dist-info/RECORD,, incremental-17.5.0.dist-info/WHEEL,sha256=o2k-Qa-RMNIJmUdIc7KU6VWR_ErNRbWNlxDIpl7lm34,110 incremental-17.5.0.dist-info/entry_points.txt,sha256=8Ap0rJ8G9THgI-ZYxAsGJVIffcEgM5y0GlhwZlLD0zM,83 incremental-17.5.0.dist-info/metadata.json,sha256=kyDlobxp9BacDNwHCDiuuJzgskzntxABnKvt_53VXkQ,1032 incremental-17.5.0.dist-info/top_level.txt,sha256=dVpYwi6ag8TlocBDEAfD7HydlIWoVmh6ESMv04izUdc,12 incremental/__init__.py,sha256=F9sMkt4wNU0o9LilRL_bjh2x2UL3j0o8TQ0Azvt6A2E,9213 incremental/__pycache__/__init__.cpython-36.pyc,, incremental/__pycache__/_version.cpython-36.pyc,, incremental/__pycache__/update.cpython-36.pyc,, incremental/_version.py,sha256=VNbdIBHWnhj2KgEJU1jfCaXE0_TkOofTZlR9Jnnkc7Y,272 incremental/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 incremental/tests/__pycache__/__init__.cpython-36.pyc,, incremental/tests/__pycache__/test_update.cpython-36.pyc,, incremental/tests/__pycache__/test_version.cpython-36.pyc,, incremental/tests/test_update.py,sha256=Blsbg_4Yddbz12GJ7P1aZepXI0lLYC5mpibjkgeIQ0U,23630 incremental/tests/test_version.py,sha256=zf6SO2T4fLOvmjEKIQWwismMDQoCygqoTnb1Iscn18o,14700 incremental/update.py,sha256=XdWEC3ObYusl1XnrQhwsDzxCeQDjHTlnrqYWYpfGn18,6150 ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/incremental-17.5.0.dist-info/WHEEL ================================================ Wheel-Version: 1.0 Generator: bdist_wheel (0.29.0) Root-Is-Purelib: true Tag: py2-none-any Tag: py3-none-any ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/incremental-17.5.0.dist-info/entry_points.txt ================================================ [distutils.setup_keywords] use_incremental = incremental:_get_version ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/incremental-17.5.0.dist-info/metadata.json ================================================ {"classifiers": ["Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Programming Language :: Python :: 2", "Programming Language :: Python :: 2.6", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.3", "Programming Language :: Python :: 3.4", "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6"], "extensions": {"python.details": {"contacts": [{"email": "hawkowl@twistedmatrix.com", "name": "Amber Brown", "role": "author"}], "document_names": {"description": "DESCRIPTION.rst"}, "project_urls": {"Home": "https://github.com/twisted/incremental"}}, "python.exports": {"distutils.setup_keywords": {"use_incremental": "incremental:_get_version"}}}, "extras": ["scripts"], "generator": "bdist_wheel (0.29.0)", "license": "MIT", "metadata_version": "2.0", "name": "incremental", "run_requires": [{"extra": "scripts", "requires": ["click (>=6.0)", "twisted (>=16.4.0)"]}], "summary": "UNKNOWN", "version": "17.5.0"} ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/incremental-17.5.0.dist-info/top_level.txt ================================================ incremental ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/lxml/ElementInclude.py ================================================ # # ElementTree # $Id: ElementInclude.py 1862 2004-06-18 07:31:02Z Fredrik $ # # limited xinclude support for element trees # # history: # 2003-08-15 fl created # 2003-11-14 fl fixed default loader # # Copyright (c) 2003-2004 by Fredrik Lundh. All rights reserved. # # fredrik@pythonware.com # http://www.pythonware.com # # -------------------------------------------------------------------- # The ElementTree toolkit is # # Copyright (c) 1999-2004 by Fredrik Lundh # # By obtaining, using, and/or copying this software and/or its # associated documentation, you agree that you have read, understood, # and will comply with the following terms and conditions: # # Permission to use, copy, modify, and distribute this software and # its associated documentation for any purpose and without fee is # hereby granted, provided that the above copyright notice appears in # all copies, and that both that copyright notice and this permission # notice appear in supporting documentation, and that the name of # Secret Labs AB or the author not be used in advertising or publicity # pertaining to distribution of the software without specific, written # prior permission. # # SECRET LABS AB AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD # TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANT- # ABILITY AND FITNESS. IN NO EVENT SHALL SECRET LABS AB OR THE AUTHOR # BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY # DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, # WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS # ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE # OF THIS SOFTWARE. # -------------------------------------------------------------------- """ Limited XInclude support for the ElementTree package. While lxml.etree has full support for XInclude (see `etree.ElementTree.xinclude()`), this module provides a simpler, pure Python, ElementTree compatible implementation that supports a simple form of custom URL resolvers. """ from lxml import etree try: from urlparse import urljoin from urllib2 import urlopen except ImportError: # Python 3 from urllib.parse import urljoin from urllib.request import urlopen XINCLUDE = "{http://www.w3.org/2001/XInclude}" XINCLUDE_INCLUDE = XINCLUDE + "include" XINCLUDE_FALLBACK = XINCLUDE + "fallback" XINCLUDE_ITER_TAG = XINCLUDE + "*" # For security reasons, the inclusion depth is limited to this read-only value by default. DEFAULT_MAX_INCLUSION_DEPTH = 6 ## # Fatal include error. class FatalIncludeError(etree.LxmlSyntaxError): pass class LimitedRecursiveIncludeError(FatalIncludeError): pass ## # ET compatible default loader. # This loader reads an included resource from disk. # # @param href Resource reference. # @param parse Parse mode. Either "xml" or "text". # @param encoding Optional text encoding. # @return The expanded resource. If the parse mode is "xml", this # is an ElementTree instance. If the parse mode is "text", this # is a Unicode string. If the loader fails, it can return None # or raise an IOError exception. # @throws IOError If the loader fails to load the resource. def default_loader(href, parse, encoding=None): file = open(href, 'rb') if parse == "xml": data = etree.parse(file).getroot() else: data = file.read() if not encoding: encoding = 'utf-8' data = data.decode(encoding) file.close() return data ## # Default loader used by lxml.etree - handles custom resolvers properly # def _lxml_default_loader(href, parse, encoding=None, parser=None): if parse == "xml": data = etree.parse(href, parser).getroot() else: if "://" in href: f = urlopen(href) else: f = open(href, 'rb') data = f.read() f.close() if not encoding: encoding = 'utf-8' data = data.decode(encoding) return data ## # Wrapper for ET compatibility - drops the parser def _wrap_et_loader(loader): def load(href, parse, encoding=None, parser=None): return loader(href, parse, encoding) return load ## # Expand XInclude directives. # # @param elem Root element. # @param loader Optional resource loader. If omitted, it defaults # to {@link default_loader}. If given, it should be a callable # that implements the same interface as default_loader. # @param base_url The base URL of the original file, to resolve # relative include file references. # @param max_depth The maximum number of recursive inclusions. # Limited to reduce the risk of malicious content explosion. # Pass None to disable the limitation. # @throws LimitedRecursiveIncludeError If the {@link max_depth} was exceeded. # @throws FatalIncludeError If the function fails to include a given # resource, or if the tree contains malformed XInclude elements. # @throws IOError If the function fails to load a given resource. # @returns the node or its replacement if it was an XInclude node def include(elem, loader=None, base_url=None, max_depth=DEFAULT_MAX_INCLUSION_DEPTH): if max_depth is None: max_depth = -1 elif max_depth < 0: raise ValueError("expected non-negative depth or None for 'max_depth', got %r" % max_depth) if base_url is None: if hasattr(elem, 'getroot'): tree = elem elem = elem.getroot() else: tree = elem.getroottree() if hasattr(tree, 'docinfo'): base_url = tree.docinfo.URL elif hasattr(elem, 'getroot'): elem = elem.getroot() _include(elem, loader, base_url, max_depth) def _include(elem, loader=None, base_url=None, max_depth=DEFAULT_MAX_INCLUSION_DEPTH, _parent_hrefs=None): if loader is not None: load_include = _wrap_et_loader(loader) else: load_include = _lxml_default_loader if _parent_hrefs is None: _parent_hrefs = set() parser = elem.getroottree().parser include_elements = list( elem.iter(XINCLUDE_ITER_TAG)) for e in include_elements: if e.tag == XINCLUDE_INCLUDE: # process xinclude directive href = urljoin(base_url, e.get("href")) parse = e.get("parse", "xml") parent = e.getparent() if parse == "xml": if href in _parent_hrefs: raise FatalIncludeError( "recursive include of %r detected" % href ) if max_depth == 0: raise LimitedRecursiveIncludeError( "maximum xinclude depth reached when including file %s" % href) _parent_hrefs.add(href) node = load_include(href, parse, parser=parser) if node is None: raise FatalIncludeError( "cannot load %r as %r" % (href, parse) ) node = _include(node, loader, href, max_depth - 1, _parent_hrefs) if e.tail: node.tail = (node.tail or "") + e.tail if parent is None: return node # replaced the root node! parent.replace(e, node) elif parse == "text": text = load_include(href, parse, encoding=e.get("encoding")) if text is None: raise FatalIncludeError( "cannot load %r as %r" % (href, parse) ) predecessor = e.getprevious() if predecessor is not None: predecessor.tail = (predecessor.tail or "") + text elif parent is None: return text # replaced the root node! else: parent.text = (parent.text or "") + text + (e.tail or "") parent.remove(e) else: raise FatalIncludeError( "unknown parse type in xi:include tag (%r)" % parse ) elif e.tag == XINCLUDE_FALLBACK: parent = e.getparent() if parent is not None and parent.tag != XINCLUDE_INCLUDE: raise FatalIncludeError( "xi:fallback tag must be child of xi:include (%r)" % e.tag ) else: raise FatalIncludeError( "Invalid element found in XInclude namespace (%r)" % e.tag ) return elem ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/lxml/__init__.py ================================================ # this is a package def get_include(): """ Returns a list of header include paths (for lxml itself, libxml2 and libxslt) needed to compile C code against lxml if it was built with statically linked libraries. """ import os lxml_path = __path__[0] include_path = os.path.join(lxml_path, 'includes') includes = [include_path, lxml_path] for name in os.listdir(include_path): path = os.path.join(include_path, name) if os.path.isdir(path): includes.append(path) return includes ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/lxml/_elementpath.py ================================================ # cython: language_level=2 # # ElementTree # $Id: ElementPath.py 3375 2008-02-13 08:05:08Z fredrik $ # # limited xpath support for element trees # # history: # 2003-05-23 fl created # 2003-05-28 fl added support for // etc # 2003-08-27 fl fixed parsing of periods in element names # 2007-09-10 fl new selection engine # 2007-09-12 fl fixed parent selector # 2007-09-13 fl added iterfind; changed findall to return a list # 2007-11-30 fl added namespaces support # 2009-10-30 fl added child element value filter # # Copyright (c) 2003-2009 by Fredrik Lundh. All rights reserved. # # fredrik@pythonware.com # http://www.pythonware.com # # -------------------------------------------------------------------- # The ElementTree toolkit is # # Copyright (c) 1999-2009 by Fredrik Lundh # # By obtaining, using, and/or copying this software and/or its # associated documentation, you agree that you have read, understood, # and will comply with the following terms and conditions: # # Permission to use, copy, modify, and distribute this software and # its associated documentation for any purpose and without fee is # hereby granted, provided that the above copyright notice appears in # all copies, and that both that copyright notice and this permission # notice appear in supporting documentation, and that the name of # Secret Labs AB or the author not be used in advertising or publicity # pertaining to distribution of the software without specific, written # prior permission. # # SECRET LABS AB AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD # TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANT- # ABILITY AND FITNESS. IN NO EVENT SHALL SECRET LABS AB OR THE AUTHOR # BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY # DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, # WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS # ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE # OF THIS SOFTWARE. # -------------------------------------------------------------------- ## # Implementation module for XPath support. There's usually no reason # to import this module directly; the ElementTree does this for # you, if needed. ## from __future__ import absolute_import import re xpath_tokenizer_re = re.compile( "(" "'[^']*'|\"[^\"]*\"|" "::|" "//?|" r"\.\.|" r"\(\)|" r"[/.*:\[\]\(\)@=])|" r"((?:\{[^}]+\})?[^/\[\]\(\)@=\s]+)|" r"\s+" ) def xpath_tokenizer(pattern, namespaces=None): # ElementTree uses '', lxml used None originally. default_namespace = (namespaces.get(None) or namespaces.get('')) if namespaces else None parsing_attribute = False for token in xpath_tokenizer_re.findall(pattern): ttype, tag = token if tag and tag[0] != "{": if ":" in tag: prefix, uri = tag.split(":", 1) try: if not namespaces: raise KeyError yield ttype, "{%s}%s" % (namespaces[prefix], uri) except KeyError: raise SyntaxError("prefix %r not found in prefix map" % prefix) elif default_namespace and not parsing_attribute: yield ttype, "{%s}%s" % (default_namespace, tag) else: yield token parsing_attribute = False else: yield token parsing_attribute = ttype == '@' def prepare_child(next, token): tag = token[1] def select(result): for elem in result: for e in elem.iterchildren(tag): yield e return select def prepare_star(next, token): def select(result): for elem in result: for e in elem.iterchildren('*'): yield e return select def prepare_self(next, token): def select(result): return result return select def prepare_descendant(next, token): token = next() if token[0] == "*": tag = "*" elif not token[0]: tag = token[1] else: raise SyntaxError("invalid descendant") def select(result): for elem in result: for e in elem.iterdescendants(tag): yield e return select def prepare_parent(next, token): def select(result): for elem in result: parent = elem.getparent() if parent is not None: yield parent return select def prepare_predicate(next, token): # FIXME: replace with real parser!!! refs: # http://effbot.org/zone/simple-iterator-parser.htm # http://javascript.crockford.com/tdop/tdop.html signature = '' predicate = [] while 1: token = next() if token[0] == "]": break if token == ('', ''): # ignore whitespace continue if token[0] and token[0][:1] in "'\"": token = "'", token[0][1:-1] signature += token[0] or "-" predicate.append(token[1]) # use signature to determine predicate type if signature == "@-": # [@attribute] predicate key = predicate[1] def select(result): for elem in result: if elem.get(key) is not None: yield elem return select if signature == "@-='": # [@attribute='value'] key = predicate[1] value = predicate[-1] def select(result): for elem in result: if elem.get(key) == value: yield elem return select if signature == "-" and not re.match(r"-?\d+$", predicate[0]): # [tag] tag = predicate[0] def select(result): for elem in result: for _ in elem.iterchildren(tag): yield elem break return select if signature == ".='" or (signature == "-='" and not re.match(r"-?\d+$", predicate[0])): # [.='value'] or [tag='value'] tag = predicate[0] value = predicate[-1] if tag: def select(result): for elem in result: for e in elem.iterchildren(tag): if "".join(e.itertext()) == value: yield elem break else: def select(result): for elem in result: if "".join(elem.itertext()) == value: yield elem return select if signature == "-" or signature == "-()" or signature == "-()-": # [index] or [last()] or [last()-index] if signature == "-": # [index] index = int(predicate[0]) - 1 if index < 0: if index == -1: raise SyntaxError( "indices in path predicates are 1-based, not 0-based") else: raise SyntaxError("path index >= 1 expected") else: if predicate[0] != "last": raise SyntaxError("unsupported function") if signature == "-()-": try: index = int(predicate[2]) - 1 except ValueError: raise SyntaxError("unsupported expression") else: index = -1 def select(result): for elem in result: parent = elem.getparent() if parent is None: continue try: # FIXME: what if the selector is "*" ? elems = list(parent.iterchildren(elem.tag)) if elems[index] is elem: yield elem except IndexError: pass return select raise SyntaxError("invalid predicate") ops = { "": prepare_child, "*": prepare_star, ".": prepare_self, "..": prepare_parent, "//": prepare_descendant, "[": prepare_predicate, } # -------------------------------------------------------------------- _cache = {} def _build_path_iterator(path, namespaces): """compile selector pattern""" if path[-1:] == "/": path += "*" # implicit all (FIXME: keep this?) cache_key = (path,) if namespaces: # lxml originally used None for the default namespace but ElementTree uses the # more convenient (all-strings-dict) empty string, so we support both here, # preferring the more convenient '', as long as they aren't ambiguous. if None in namespaces: if '' in namespaces and namespaces[None] != namespaces['']: raise ValueError("Ambiguous default namespace provided: %r versus %r" % ( namespaces[None], namespaces[''])) cache_key += (namespaces[None],) + tuple(sorted( item for item in namespaces.items() if item[0] is not None)) else: cache_key += tuple(sorted(namespaces.items())) try: return _cache[cache_key] except KeyError: pass if len(_cache) > 100: _cache.clear() if path[:1] == "/": raise SyntaxError("cannot use absolute path on element") stream = iter(xpath_tokenizer(path, namespaces)) try: _next = stream.next except AttributeError: # Python 3 _next = stream.__next__ try: token = _next() except StopIteration: raise SyntaxError("empty path expression") selector = [] while 1: try: selector.append(ops[token[0]](_next, token)) except StopIteration: raise SyntaxError("invalid path") try: token = _next() if token[0] == "/": token = _next() except StopIteration: break _cache[cache_key] = selector return selector ## # Iterate over the matching nodes def iterfind(elem, path, namespaces=None): selector = _build_path_iterator(path, namespaces) result = iter((elem,)) for select in selector: result = select(result) return result ## # Find first matching object. def find(elem, path, namespaces=None): it = iterfind(elem, path, namespaces) try: return next(it) except StopIteration: return None ## # Find all matching objects. def findall(elem, path, namespaces=None): return list(iterfind(elem, path, namespaces)) ## # Find text for first matching object. def findtext(elem, path, default=None, namespaces=None): el = find(elem, path, namespaces) if el is None: return default else: return el.text or '' ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/lxml/builder.py ================================================ # cython: language_level=2 # # Element generator factory by Fredrik Lundh. # # Source: # http://online.effbot.org/2006_11_01_archive.htm#et-builder # http://effbot.python-hosting.com/file/stuff/sandbox/elementlib/builder.py # # -------------------------------------------------------------------- # The ElementTree toolkit is # # Copyright (c) 1999-2004 by Fredrik Lundh # # By obtaining, using, and/or copying this software and/or its # associated documentation, you agree that you have read, understood, # and will comply with the following terms and conditions: # # Permission to use, copy, modify, and distribute this software and # its associated documentation for any purpose and without fee is # hereby granted, provided that the above copyright notice appears in # all copies, and that both that copyright notice and this permission # notice appear in supporting documentation, and that the name of # Secret Labs AB or the author not be used in advertising or publicity # pertaining to distribution of the software without specific, written # prior permission. # # SECRET LABS AB AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD # TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANT- # ABILITY AND FITNESS. IN NO EVENT SHALL SECRET LABS AB OR THE AUTHOR # BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY # DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, # WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS # ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE # OF THIS SOFTWARE. # -------------------------------------------------------------------- """ The ``E`` Element factory for generating XML documents. """ from __future__ import absolute_import import lxml.etree as ET from functools import partial try: basestring except NameError: basestring = str try: unicode except NameError: unicode = str class ElementMaker(object): """Element generator factory. Unlike the ordinary Element factory, the E factory allows you to pass in more than just a tag and some optional attributes; you can also pass in text and other elements. The text is added as either text or tail attributes, and elements are inserted at the right spot. Some small examples:: >>> from lxml import etree as ET >>> from lxml.builder import E >>> ET.tostring(E("tag")) '' >>> ET.tostring(E("tag", "text")) 'text' >>> ET.tostring(E("tag", "text", key="value")) 'text' >>> ET.tostring(E("tag", E("subtag", "text"), "tail")) 'texttail' For simple tags, the factory also allows you to write ``E.tag(...)`` instead of ``E('tag', ...)``:: >>> ET.tostring(E.tag()) '' >>> ET.tostring(E.tag("text")) 'text' >>> ET.tostring(E.tag(E.subtag("text"), "tail")) 'texttail' Here's a somewhat larger example; this shows how to generate HTML documents, using a mix of prepared factory functions for inline elements, nested ``E.tag`` calls, and embedded XHTML fragments:: # some common inline elements A = E.a I = E.i B = E.b def CLASS(v): # helper function, 'class' is a reserved word return {'class': v} page = ( E.html( E.head( E.title("This is a sample document") ), E.body( E.h1("Hello!", CLASS("title")), E.p("This is a paragraph with ", B("bold"), " text in it!"), E.p("This is another paragraph, with a ", A("link", href="http://www.python.org"), "."), E.p("Here are some reserved characters: ."), ET.XML("

And finally, here is an embedded XHTML fragment.

"), ) ) ) print ET.tostring(page) Here's a prettyprinted version of the output from the above script:: This is a sample document

Hello!

This is a paragraph with bold text in it!

This is another paragraph, with link.

Here are some reserved characters: <spam&egg>.

And finally, here is an embedded XHTML fragment.

For namespace support, you can pass a namespace map (``nsmap``) and/or a specific target ``namespace`` to the ElementMaker class:: >>> E = ElementMaker(namespace="http://my.ns/") >>> print(ET.tostring( E.test )) >>> E = ElementMaker(namespace="http://my.ns/", nsmap={'p':'http://my.ns/'}) >>> print(ET.tostring( E.test )) """ def __init__(self, typemap=None, namespace=None, nsmap=None, makeelement=None): if namespace is not None: self._namespace = '{' + namespace + '}' else: self._namespace = None if nsmap: self._nsmap = dict(nsmap) else: self._nsmap = None if makeelement is not None: assert callable(makeelement) self._makeelement = makeelement else: self._makeelement = ET.Element # initialize type map for this element factory if typemap: typemap = dict(typemap) else: typemap = {} def add_text(elem, item): try: elem[-1].tail = (elem[-1].tail or "") + item except IndexError: elem.text = (elem.text or "") + item def add_cdata(elem, cdata): if elem.text: raise ValueError("Can't add a CDATA section. Element already has some text: %r" % elem.text) elem.text = cdata if str not in typemap: typemap[str] = add_text if unicode not in typemap: typemap[unicode] = add_text if ET.CDATA not in typemap: typemap[ET.CDATA] = add_cdata def add_dict(elem, item): attrib = elem.attrib for k, v in item.items(): if isinstance(v, basestring): attrib[k] = v else: attrib[k] = typemap[type(v)](None, v) if dict not in typemap: typemap[dict] = add_dict self._typemap = typemap def __call__(self, tag, *children, **attrib): typemap = self._typemap if self._namespace is not None and tag[0] != '{': tag = self._namespace + tag elem = self._makeelement(tag, nsmap=self._nsmap) if attrib: typemap[dict](elem, attrib) for item in children: if callable(item): item = item() t = typemap.get(type(item)) if t is None: if ET.iselement(item): elem.append(item) continue for basetype in type(item).__mro__: # See if the typemap knows of any of this type's bases. t = typemap.get(basetype) if t is not None: break else: raise TypeError("bad argument type: %s(%r)" % (type(item).__name__, item)) v = t(elem, item) if v: typemap.get(type(v))(elem, v) return elem def __getattr__(self, tag): return partial(self, tag) # create factory object E = ElementMaker() ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/lxml/cssselect.py ================================================ """CSS Selectors based on XPath. This module supports selecting XML/HTML tags based on CSS selectors. See the `CSSSelector` class for details. This is a thin wrapper around cssselect 0.7 or later. """ from __future__ import absolute_import from . import etree try: import cssselect as external_cssselect except ImportError: raise ImportError( 'cssselect does not seem to be installed. ' 'See http://packages.python.org/cssselect/') SelectorSyntaxError = external_cssselect.SelectorSyntaxError ExpressionError = external_cssselect.ExpressionError SelectorError = external_cssselect.SelectorError __all__ = ['SelectorSyntaxError', 'ExpressionError', 'SelectorError', 'CSSSelector'] class LxmlTranslator(external_cssselect.GenericTranslator): """ A custom CSS selector to XPath translator with lxml-specific extensions. """ def xpath_contains_function(self, xpath, function): # Defined there, removed in later drafts: # http://www.w3.org/TR/2001/CR-css3-selectors-20011113/#content-selectors if function.argument_types() not in (['STRING'], ['IDENT']): raise ExpressionError( "Expected a single string or ident for :contains(), got %r" % function.arguments) value = function.arguments[0].value return xpath.add_condition( 'contains(__lxml_internal_css:lower-case(string(.)), %s)' % self.xpath_literal(value.lower())) class LxmlHTMLTranslator(LxmlTranslator, external_cssselect.HTMLTranslator): """ lxml extensions + HTML support. """ def _make_lower_case(context, s): return s.lower() ns = etree.FunctionNamespace('http://codespeak.net/lxml/css/') ns.prefix = '__lxml_internal_css' ns['lower-case'] = _make_lower_case class CSSSelector(etree.XPath): """A CSS selector. Usage:: >>> from lxml import etree, cssselect >>> select = cssselect.CSSSelector("a tag > child") >>> root = etree.XML("TEXT") >>> [ el.tag for el in select(root) ] ['child'] To use CSS namespaces, you need to pass a prefix-to-namespace mapping as ``namespaces`` keyword argument:: >>> rdfns = 'http://www.w3.org/1999/02/22-rdf-syntax-ns#' >>> select_ns = cssselect.CSSSelector('root > rdf|Description', ... namespaces={'rdf': rdfns}) >>> rdf = etree.XML(( ... '' ... 'blah' ... '') % rdfns) >>> [(el.tag, el.text) for el in select_ns(rdf)] [('{http://www.w3.org/1999/02/22-rdf-syntax-ns#}Description', 'blah')] """ def __init__(self, css, namespaces=None, translator='xml'): if translator == 'xml': translator = LxmlTranslator() elif translator == 'html': translator = LxmlHTMLTranslator() elif translator == 'xhtml': translator = LxmlHTMLTranslator(xhtml=True) path = translator.css_to_xpath(css) etree.XPath.__init__(self, path, namespaces=namespaces) self.css = css def __repr__(self): return '<%s %s for %r>' % ( self.__class__.__name__, hex(abs(id(self)))[2:], self.css) ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/lxml/doctestcompare.py ================================================ """ lxml-based doctest output comparison. Note: normally, you should just import the `lxml.usedoctest` and `lxml.html.usedoctest` modules from within a doctest, instead of this one:: >>> import lxml.usedoctest # for XML output >>> import lxml.html.usedoctest # for HTML output To use this module directly, you must call ``lxmldoctest.install()``, which will cause doctest to use this in all subsequent calls. This changes the way output is checked and comparisons are made for XML or HTML-like content. XML or HTML content is noticed because the example starts with ``<`` (it's HTML if it starts with ```` or include an ``any`` attribute in the tag. An ``any`` tag matches any tag, while the attribute matches any and all attributes. When a match fails, the reformatted example and gotten text is displayed (indented), and a rough diff-like output is given. Anything marked with ``+`` is in the output but wasn't supposed to be, and similarly ``-`` means its in the example but wasn't in the output. You can disable parsing on one line with ``# doctest:+NOPARSE_MARKUP`` """ from lxml import etree import sys import re import doctest try: from html import escape as html_escape except ImportError: from cgi import escape as html_escape __all__ = ['PARSE_HTML', 'PARSE_XML', 'NOPARSE_MARKUP', 'LXMLOutputChecker', 'LHTMLOutputChecker', 'install', 'temp_install'] try: _basestring = basestring except NameError: _basestring = (str, bytes) _IS_PYTHON_3 = sys.version_info[0] >= 3 PARSE_HTML = doctest.register_optionflag('PARSE_HTML') PARSE_XML = doctest.register_optionflag('PARSE_XML') NOPARSE_MARKUP = doctest.register_optionflag('NOPARSE_MARKUP') OutputChecker = doctest.OutputChecker def strip(v): if v is None: return None else: return v.strip() def norm_whitespace(v): return _norm_whitespace_re.sub(' ', v) _html_parser = etree.HTMLParser(recover=False, remove_blank_text=True) def html_fromstring(html): return etree.fromstring(html, _html_parser) # We use this to distinguish repr()s from elements: _repr_re = re.compile(r'^<[^>]+ (at|object) ') _norm_whitespace_re = re.compile(r'[ \t\n][ \t\n]+') class LXMLOutputChecker(OutputChecker): empty_tags = ( 'param', 'img', 'area', 'br', 'basefont', 'input', 'base', 'meta', 'link', 'col') def get_default_parser(self): return etree.XML def check_output(self, want, got, optionflags): alt_self = getattr(self, '_temp_override_self', None) if alt_self is not None: super_method = self._temp_call_super_check_output self = alt_self else: super_method = OutputChecker.check_output parser = self.get_parser(want, got, optionflags) if not parser: return super_method( self, want, got, optionflags) try: want_doc = parser(want) except etree.XMLSyntaxError: return False try: got_doc = parser(got) except etree.XMLSyntaxError: return False return self.compare_docs(want_doc, got_doc) def get_parser(self, want, got, optionflags): parser = None if NOPARSE_MARKUP & optionflags: return None if PARSE_HTML & optionflags: parser = html_fromstring elif PARSE_XML & optionflags: parser = etree.XML elif (want.strip().lower().startswith('' % el.tag return '<%s %s>' % (el.tag, ' '.join(attrs)) def format_end_tag(self, el): if isinstance(el, etree.CommentBase): # FIXME: probably PIs should be handled specially too? return '-->' return '' % el.tag def collect_diff(self, want, got, html, indent): parts = [] if not len(want) and not len(got): parts.append(' '*indent) parts.append(self.collect_diff_tag(want, got)) if not self.html_empty_tag(got, html): parts.append(self.collect_diff_text(want.text, got.text)) parts.append(self.collect_diff_end_tag(want, got)) parts.append(self.collect_diff_text(want.tail, got.tail)) parts.append('\n') return ''.join(parts) parts.append(' '*indent) parts.append(self.collect_diff_tag(want, got)) parts.append('\n') if strip(want.text) or strip(got.text): parts.append(' '*indent) parts.append(self.collect_diff_text(want.text, got.text)) parts.append('\n') want_children = list(want) got_children = list(got) while want_children or got_children: if not want_children: parts.append(self.format_doc(got_children.pop(0), html, indent+2, '+')) continue if not got_children: parts.append(self.format_doc(want_children.pop(0), html, indent+2, '-')) continue parts.append(self.collect_diff( want_children.pop(0), got_children.pop(0), html, indent+2)) parts.append(' '*indent) parts.append(self.collect_diff_end_tag(want, got)) parts.append('\n') if strip(want.tail) or strip(got.tail): parts.append(' '*indent) parts.append(self.collect_diff_text(want.tail, got.tail)) parts.append('\n') return ''.join(parts) def collect_diff_tag(self, want, got): if not self.tag_compare(want.tag, got.tag): tag = '%s (got: %s)' % (want.tag, got.tag) else: tag = got.tag attrs = [] any = want.tag == 'any' or 'any' in want.attrib for name, value in sorted(got.attrib.items()): if name not in want.attrib and not any: attrs.append('+%s="%s"' % (name, self.format_text(value, False))) else: if name in want.attrib: text = self.collect_diff_text(want.attrib[name], value, False) else: text = self.format_text(value, False) attrs.append('%s="%s"' % (name, text)) if not any: for name, value in sorted(want.attrib.items()): if name in got.attrib: continue attrs.append('-%s="%s"' % (name, self.format_text(value, False))) if attrs: tag = '<%s %s>' % (tag, ' '.join(attrs)) else: tag = '<%s>' % tag return tag def collect_diff_end_tag(self, want, got): if want.tag != got.tag: tag = '%s (got: %s)' % (want.tag, got.tag) else: tag = got.tag return '' % tag def collect_diff_text(self, want, got, strip=True): if self.text_compare(want, got, strip): if not got: return '' return self.format_text(got, strip) text = '%s (got: %s)' % (want, got) return self.format_text(text, strip) class LHTMLOutputChecker(LXMLOutputChecker): def get_default_parser(self): return html_fromstring def install(html=False): """ Install doctestcompare for all future doctests. If html is true, then by default the HTML parser will be used; otherwise the XML parser is used. """ if html: doctest.OutputChecker = LHTMLOutputChecker else: doctest.OutputChecker = LXMLOutputChecker def temp_install(html=False, del_module=None): """ Use this *inside* a doctest to enable this checker for this doctest only. If html is true, then by default the HTML parser will be used; otherwise the XML parser is used. """ if html: Checker = LHTMLOutputChecker else: Checker = LXMLOutputChecker frame = _find_doctest_frame() dt_self = frame.f_locals['self'] checker = Checker() old_checker = dt_self._checker dt_self._checker = checker # The unfortunate thing is that there is a local variable 'check' # in the function that runs the doctests, that is a bound method # into the output checker. We have to update that. We can't # modify the frame, so we have to modify the object in place. The # only way to do this is to actually change the func_code # attribute of the method. We change it, and then wait for # __record_outcome to be run, which signals the end of the __run # method, at which point we restore the previous check_output # implementation. if _IS_PYTHON_3: check_func = frame.f_locals['check'].__func__ checker_check_func = checker.check_output.__func__ else: check_func = frame.f_locals['check'].im_func checker_check_func = checker.check_output.im_func # Because we can't patch up func_globals, this is the only global # in check_output that we care about: doctest.etree = etree _RestoreChecker(dt_self, old_checker, checker, check_func, checker_check_func, del_module) class _RestoreChecker(object): def __init__(self, dt_self, old_checker, new_checker, check_func, clone_func, del_module): self.dt_self = dt_self self.checker = old_checker self.checker._temp_call_super_check_output = self.call_super self.checker._temp_override_self = new_checker self.check_func = check_func self.clone_func = clone_func self.del_module = del_module self.install_clone() self.install_dt_self() def install_clone(self): if _IS_PYTHON_3: self.func_code = self.check_func.__code__ self.func_globals = self.check_func.__globals__ self.check_func.__code__ = self.clone_func.__code__ else: self.func_code = self.check_func.func_code self.func_globals = self.check_func.func_globals self.check_func.func_code = self.clone_func.func_code def uninstall_clone(self): if _IS_PYTHON_3: self.check_func.__code__ = self.func_code else: self.check_func.func_code = self.func_code def install_dt_self(self): self.prev_func = self.dt_self._DocTestRunner__record_outcome self.dt_self._DocTestRunner__record_outcome = self def uninstall_dt_self(self): self.dt_self._DocTestRunner__record_outcome = self.prev_func def uninstall_module(self): if self.del_module: import sys del sys.modules[self.del_module] if '.' in self.del_module: package, module = self.del_module.rsplit('.', 1) package_mod = sys.modules[package] delattr(package_mod, module) def __call__(self, *args, **kw): self.uninstall_clone() self.uninstall_dt_self() del self.checker._temp_override_self del self.checker._temp_call_super_check_output result = self.prev_func(*args, **kw) self.uninstall_module() return result def call_super(self, *args, **kw): self.uninstall_clone() try: return self.check_func(*args, **kw) finally: self.install_clone() def _find_doctest_frame(): import sys frame = sys._getframe(1) while frame: l = frame.f_locals if 'BOOM' in l: # Sign of doctest return frame frame = frame.f_back raise LookupError( "Could not find doctest (only use this function *inside* a doctest)") __test__ = { 'basic': ''' >>> temp_install() >>> print """stuff""" ... >>> print """""" >>> print """blahblahblah""" # doctest: +NOPARSE_MARKUP, +ELLIPSIS ...foo /> '''} if __name__ == '__main__': import doctest doctest.testmod() ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/lxml/etree.h ================================================ /* Generated by Cython 0.29.13 */ #ifndef __PYX_HAVE__lxml__etree #define __PYX_HAVE__lxml__etree struct LxmlDocument; struct LxmlElement; struct LxmlElementTree; struct LxmlElementTagMatcher; struct LxmlElementIterator; struct LxmlElementBase; struct LxmlElementClassLookup; struct LxmlFallbackElementClassLookup; /* "lxml/etree.pyx":322 * * # type of a function that steps from node to node * ctypedef public xmlNode* (*_node_to_node_function)(xmlNode*) # <<<<<<<<<<<<<< * * */ typedef xmlNode *(*_node_to_node_function)(xmlNode *); /* "lxml/etree.pyx":338 * @cython.final * @cython.freelist(8) * cdef public class _Document [ type LxmlDocumentType, object LxmlDocument ]: # <<<<<<<<<<<<<< * u"""Internal base class to reference a libxml document. * */ struct LxmlDocument { PyObject_HEAD struct __pyx_vtabstruct_4lxml_5etree__Document *__pyx_vtab; int _ns_counter; PyObject *_prefix_tail; xmlDoc *_c_doc; struct __pyx_obj_4lxml_5etree__BaseParser *_parser; }; /* "lxml/etree.pyx":687 * * @cython.no_gc_clear * cdef public class _Element [ type LxmlElementType, object LxmlElement ]: # <<<<<<<<<<<<<< * u"""Element class. * */ struct LxmlElement { PyObject_HEAD struct LxmlDocument *_doc; xmlNode *_c_node; PyObject *_tag; }; /* "lxml/etree.pyx":1853 * * * cdef public class _ElementTree [ type LxmlElementTreeType, # <<<<<<<<<<<<<< * object LxmlElementTree ]: * cdef _Document _doc */ struct LxmlElementTree { PyObject_HEAD struct __pyx_vtabstruct_4lxml_5etree__ElementTree *__pyx_vtab; struct LxmlDocument *_doc; struct LxmlElement *_context_node; }; /* "lxml/etree.pyx":2597 * * * cdef public class _ElementTagMatcher [ object LxmlElementTagMatcher, # <<<<<<<<<<<<<< * type LxmlElementTagMatcherType ]: * """ */ struct LxmlElementTagMatcher { PyObject_HEAD struct __pyx_vtabstruct_4lxml_5etree__ElementTagMatcher *__pyx_vtab; PyObject *_pystrings; int _node_type; char *_href; char *_name; }; /* "lxml/etree.pyx":2628 * self._name = NULL * * cdef public class _ElementIterator(_ElementTagMatcher) [ # <<<<<<<<<<<<<< * object LxmlElementIterator, type LxmlElementIteratorType ]: * """ */ struct LxmlElementIterator { struct LxmlElementTagMatcher __pyx_base; struct LxmlElement *_node; _node_to_node_function _next_element; }; /* "src/lxml/classlookup.pxi":6 * # Custom Element classes * * cdef public class ElementBase(_Element) [ type LxmlElementBaseType, # <<<<<<<<<<<<<< * object LxmlElementBase ]: * u"""ElementBase(*children, attrib=None, nsmap=None, **_extra) */ struct LxmlElementBase { struct LxmlElement __pyx_base; }; /* "src/lxml/classlookup.pxi":210 * # Element class lookup * * ctypedef public object (*_element_class_lookup_function)(object, _Document, xmlNode*) # <<<<<<<<<<<<<< * * # class to store element class lookup functions */ typedef PyObject *(*_element_class_lookup_function)(PyObject *, struct LxmlDocument *, xmlNode *); /* "src/lxml/classlookup.pxi":213 * * # class to store element class lookup functions * cdef public class ElementClassLookup [ type LxmlElementClassLookupType, # <<<<<<<<<<<<<< * object LxmlElementClassLookup ]: * u"""ElementClassLookup(self) */ struct LxmlElementClassLookup { PyObject_HEAD _element_class_lookup_function _lookup_function; }; /* "src/lxml/classlookup.pxi":221 * * * cdef public class FallbackElementClassLookup(ElementClassLookup) \ # <<<<<<<<<<<<<< * [ type LxmlFallbackElementClassLookupType, * object LxmlFallbackElementClassLookup ]: */ struct LxmlFallbackElementClassLookup { struct LxmlElementClassLookup __pyx_base; struct __pyx_vtabstruct_4lxml_5etree_FallbackElementClassLookup *__pyx_vtab; struct LxmlElementClassLookup *fallback; _element_class_lookup_function _fallback_function; }; #ifndef __PYX_HAVE_API__lxml__etree #ifndef __PYX_EXTERN_C #ifdef __cplusplus #define __PYX_EXTERN_C extern "C" #else #define __PYX_EXTERN_C extern #endif #endif #ifndef DL_IMPORT #define DL_IMPORT(_T) _T #endif __PYX_EXTERN_C DL_IMPORT(PyTypeObject) LxmlDocumentType; __PYX_EXTERN_C DL_IMPORT(PyTypeObject) LxmlElementType; __PYX_EXTERN_C DL_IMPORT(PyTypeObject) LxmlElementTreeType; __PYX_EXTERN_C DL_IMPORT(PyTypeObject) LxmlElementTagMatcherType; __PYX_EXTERN_C DL_IMPORT(PyTypeObject) LxmlElementIteratorType; __PYX_EXTERN_C DL_IMPORT(PyTypeObject) LxmlElementBaseType; __PYX_EXTERN_C DL_IMPORT(PyTypeObject) LxmlElementClassLookupType; __PYX_EXTERN_C DL_IMPORT(PyTypeObject) LxmlFallbackElementClassLookupType; __PYX_EXTERN_C struct LxmlElement *deepcopyNodeToDocument(struct LxmlDocument *, xmlNode *); __PYX_EXTERN_C struct LxmlElementTree *elementTreeFactory(struct LxmlElement *); __PYX_EXTERN_C struct LxmlElementTree *newElementTree(struct LxmlElement *, PyObject *); __PYX_EXTERN_C struct LxmlElementTree *adoptExternalDocument(xmlDoc *, PyObject *, int); __PYX_EXTERN_C struct LxmlElement *elementFactory(struct LxmlDocument *, xmlNode *); __PYX_EXTERN_C struct LxmlElement *makeElement(PyObject *, struct LxmlDocument *, PyObject *, PyObject *, PyObject *, PyObject *, PyObject *); __PYX_EXTERN_C struct LxmlElement *makeSubElement(struct LxmlElement *, PyObject *, PyObject *, PyObject *, PyObject *, PyObject *); __PYX_EXTERN_C void setElementClassLookupFunction(_element_class_lookup_function, PyObject *); __PYX_EXTERN_C PyObject *lookupDefaultElementClass(PyObject *, PyObject *, xmlNode *); __PYX_EXTERN_C PyObject *lookupNamespaceElementClass(PyObject *, PyObject *, xmlNode *); __PYX_EXTERN_C PyObject *callLookupFallback(struct LxmlFallbackElementClassLookup *, struct LxmlDocument *, xmlNode *); __PYX_EXTERN_C int tagMatches(xmlNode *, const xmlChar *, const xmlChar *); __PYX_EXTERN_C struct LxmlDocument *documentOrRaise(PyObject *); __PYX_EXTERN_C struct LxmlElement *rootNodeOrRaise(PyObject *); __PYX_EXTERN_C int hasText(xmlNode *); __PYX_EXTERN_C int hasTail(xmlNode *); __PYX_EXTERN_C PyObject *textOf(xmlNode *); __PYX_EXTERN_C PyObject *tailOf(xmlNode *); __PYX_EXTERN_C int setNodeText(xmlNode *, PyObject *); __PYX_EXTERN_C int setTailText(xmlNode *, PyObject *); __PYX_EXTERN_C PyObject *attributeValue(xmlNode *, xmlAttr *); __PYX_EXTERN_C PyObject *attributeValueFromNsName(xmlNode *, const xmlChar *, const xmlChar *); __PYX_EXTERN_C PyObject *getAttributeValue(struct LxmlElement *, PyObject *, PyObject *); __PYX_EXTERN_C PyObject *iterattributes(struct LxmlElement *, int); __PYX_EXTERN_C PyObject *collectAttributes(xmlNode *, int); __PYX_EXTERN_C int setAttributeValue(struct LxmlElement *, PyObject *, PyObject *); __PYX_EXTERN_C int delAttribute(struct LxmlElement *, PyObject *); __PYX_EXTERN_C int delAttributeFromNsName(xmlNode *, const xmlChar *, const xmlChar *); __PYX_EXTERN_C int hasChild(xmlNode *); __PYX_EXTERN_C xmlNode *findChild(xmlNode *, Py_ssize_t); __PYX_EXTERN_C xmlNode *findChildForwards(xmlNode *, Py_ssize_t); __PYX_EXTERN_C xmlNode *findChildBackwards(xmlNode *, Py_ssize_t); __PYX_EXTERN_C xmlNode *nextElement(xmlNode *); __PYX_EXTERN_C xmlNode *previousElement(xmlNode *); __PYX_EXTERN_C void appendChild(struct LxmlElement *, struct LxmlElement *); __PYX_EXTERN_C int appendChildToElement(struct LxmlElement *, struct LxmlElement *); __PYX_EXTERN_C PyObject *pyunicode(const xmlChar *); __PYX_EXTERN_C PyObject *utf8(PyObject *); __PYX_EXTERN_C PyObject *getNsTag(PyObject *); __PYX_EXTERN_C PyObject *getNsTagWithEmptyNs(PyObject *); __PYX_EXTERN_C PyObject *namespacedName(xmlNode *); __PYX_EXTERN_C PyObject *namespacedNameFromNsName(const xmlChar *, const xmlChar *); __PYX_EXTERN_C void iteratorStoreNext(struct LxmlElementIterator *, struct LxmlElement *); __PYX_EXTERN_C void initTagMatch(struct LxmlElementTagMatcher *, PyObject *); __PYX_EXTERN_C xmlNs *findOrBuildNodeNsPrefix(struct LxmlDocument *, xmlNode *, const xmlChar *, const xmlChar *); #endif /* !__PYX_HAVE_API__lxml__etree */ /* WARNING: the interface of the module init function changed in CPython 3.5. */ /* It now returns a PyModuleDef instance instead of a PyModule instance. */ #if PY_MAJOR_VERSION < 3 PyMODINIT_FUNC initetree(void); #else PyMODINIT_FUNC PyInit_etree(void); #endif #endif /* !__PYX_HAVE__lxml__etree */ ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/lxml/etree_api.h ================================================ /* Generated by Cython 0.29.13 */ #ifndef __PYX_HAVE_API__lxml__etree #define __PYX_HAVE_API__lxml__etree #ifdef __MINGW64__ #define MS_WIN64 #endif #include "Python.h" #include "etree.h" static struct LxmlElement *(*__pyx_api_f_4lxml_5etree_deepcopyNodeToDocument)(struct LxmlDocument *, xmlNode *) = 0; #define deepcopyNodeToDocument __pyx_api_f_4lxml_5etree_deepcopyNodeToDocument static struct LxmlElementTree *(*__pyx_api_f_4lxml_5etree_elementTreeFactory)(struct LxmlElement *) = 0; #define elementTreeFactory __pyx_api_f_4lxml_5etree_elementTreeFactory static struct LxmlElementTree *(*__pyx_api_f_4lxml_5etree_newElementTree)(struct LxmlElement *, PyObject *) = 0; #define newElementTree __pyx_api_f_4lxml_5etree_newElementTree static struct LxmlElementTree *(*__pyx_api_f_4lxml_5etree_adoptExternalDocument)(xmlDoc *, PyObject *, int) = 0; #define adoptExternalDocument __pyx_api_f_4lxml_5etree_adoptExternalDocument static struct LxmlElement *(*__pyx_api_f_4lxml_5etree_elementFactory)(struct LxmlDocument *, xmlNode *) = 0; #define elementFactory __pyx_api_f_4lxml_5etree_elementFactory static struct LxmlElement *(*__pyx_api_f_4lxml_5etree_makeElement)(PyObject *, struct LxmlDocument *, PyObject *, PyObject *, PyObject *, PyObject *, PyObject *) = 0; #define makeElement __pyx_api_f_4lxml_5etree_makeElement static struct LxmlElement *(*__pyx_api_f_4lxml_5etree_makeSubElement)(struct LxmlElement *, PyObject *, PyObject *, PyObject *, PyObject *, PyObject *) = 0; #define makeSubElement __pyx_api_f_4lxml_5etree_makeSubElement static void (*__pyx_api_f_4lxml_5etree_setElementClassLookupFunction)(_element_class_lookup_function, PyObject *) = 0; #define setElementClassLookupFunction __pyx_api_f_4lxml_5etree_setElementClassLookupFunction static PyObject *(*__pyx_api_f_4lxml_5etree_lookupDefaultElementClass)(PyObject *, PyObject *, xmlNode *) = 0; #define lookupDefaultElementClass __pyx_api_f_4lxml_5etree_lookupDefaultElementClass static PyObject *(*__pyx_api_f_4lxml_5etree_lookupNamespaceElementClass)(PyObject *, PyObject *, xmlNode *) = 0; #define lookupNamespaceElementClass __pyx_api_f_4lxml_5etree_lookupNamespaceElementClass static PyObject *(*__pyx_api_f_4lxml_5etree_callLookupFallback)(struct LxmlFallbackElementClassLookup *, struct LxmlDocument *, xmlNode *) = 0; #define callLookupFallback __pyx_api_f_4lxml_5etree_callLookupFallback static int (*__pyx_api_f_4lxml_5etree_tagMatches)(xmlNode *, const xmlChar *, const xmlChar *) = 0; #define tagMatches __pyx_api_f_4lxml_5etree_tagMatches static struct LxmlDocument *(*__pyx_api_f_4lxml_5etree_documentOrRaise)(PyObject *) = 0; #define documentOrRaise __pyx_api_f_4lxml_5etree_documentOrRaise static struct LxmlElement *(*__pyx_api_f_4lxml_5etree_rootNodeOrRaise)(PyObject *) = 0; #define rootNodeOrRaise __pyx_api_f_4lxml_5etree_rootNodeOrRaise static int (*__pyx_api_f_4lxml_5etree_hasText)(xmlNode *) = 0; #define hasText __pyx_api_f_4lxml_5etree_hasText static int (*__pyx_api_f_4lxml_5etree_hasTail)(xmlNode *) = 0; #define hasTail __pyx_api_f_4lxml_5etree_hasTail static PyObject *(*__pyx_api_f_4lxml_5etree_textOf)(xmlNode *) = 0; #define textOf __pyx_api_f_4lxml_5etree_textOf static PyObject *(*__pyx_api_f_4lxml_5etree_tailOf)(xmlNode *) = 0; #define tailOf __pyx_api_f_4lxml_5etree_tailOf static int (*__pyx_api_f_4lxml_5etree_setNodeText)(xmlNode *, PyObject *) = 0; #define setNodeText __pyx_api_f_4lxml_5etree_setNodeText static int (*__pyx_api_f_4lxml_5etree_setTailText)(xmlNode *, PyObject *) = 0; #define setTailText __pyx_api_f_4lxml_5etree_setTailText static PyObject *(*__pyx_api_f_4lxml_5etree_attributeValue)(xmlNode *, xmlAttr *) = 0; #define attributeValue __pyx_api_f_4lxml_5etree_attributeValue static PyObject *(*__pyx_api_f_4lxml_5etree_attributeValueFromNsName)(xmlNode *, const xmlChar *, const xmlChar *) = 0; #define attributeValueFromNsName __pyx_api_f_4lxml_5etree_attributeValueFromNsName static PyObject *(*__pyx_api_f_4lxml_5etree_getAttributeValue)(struct LxmlElement *, PyObject *, PyObject *) = 0; #define getAttributeValue __pyx_api_f_4lxml_5etree_getAttributeValue static PyObject *(*__pyx_api_f_4lxml_5etree_iterattributes)(struct LxmlElement *, int) = 0; #define iterattributes __pyx_api_f_4lxml_5etree_iterattributes static PyObject *(*__pyx_api_f_4lxml_5etree_collectAttributes)(xmlNode *, int) = 0; #define collectAttributes __pyx_api_f_4lxml_5etree_collectAttributes static int (*__pyx_api_f_4lxml_5etree_setAttributeValue)(struct LxmlElement *, PyObject *, PyObject *) = 0; #define setAttributeValue __pyx_api_f_4lxml_5etree_setAttributeValue static int (*__pyx_api_f_4lxml_5etree_delAttribute)(struct LxmlElement *, PyObject *) = 0; #define delAttribute __pyx_api_f_4lxml_5etree_delAttribute static int (*__pyx_api_f_4lxml_5etree_delAttributeFromNsName)(xmlNode *, const xmlChar *, const xmlChar *) = 0; #define delAttributeFromNsName __pyx_api_f_4lxml_5etree_delAttributeFromNsName static int (*__pyx_api_f_4lxml_5etree_hasChild)(xmlNode *) = 0; #define hasChild __pyx_api_f_4lxml_5etree_hasChild static xmlNode *(*__pyx_api_f_4lxml_5etree_findChild)(xmlNode *, Py_ssize_t) = 0; #define findChild __pyx_api_f_4lxml_5etree_findChild static xmlNode *(*__pyx_api_f_4lxml_5etree_findChildForwards)(xmlNode *, Py_ssize_t) = 0; #define findChildForwards __pyx_api_f_4lxml_5etree_findChildForwards static xmlNode *(*__pyx_api_f_4lxml_5etree_findChildBackwards)(xmlNode *, Py_ssize_t) = 0; #define findChildBackwards __pyx_api_f_4lxml_5etree_findChildBackwards static xmlNode *(*__pyx_api_f_4lxml_5etree_nextElement)(xmlNode *) = 0; #define nextElement __pyx_api_f_4lxml_5etree_nextElement static xmlNode *(*__pyx_api_f_4lxml_5etree_previousElement)(xmlNode *) = 0; #define previousElement __pyx_api_f_4lxml_5etree_previousElement static void (*__pyx_api_f_4lxml_5etree_appendChild)(struct LxmlElement *, struct LxmlElement *) = 0; #define appendChild __pyx_api_f_4lxml_5etree_appendChild static int (*__pyx_api_f_4lxml_5etree_appendChildToElement)(struct LxmlElement *, struct LxmlElement *) = 0; #define appendChildToElement __pyx_api_f_4lxml_5etree_appendChildToElement static PyObject *(*__pyx_api_f_4lxml_5etree_pyunicode)(const xmlChar *) = 0; #define pyunicode __pyx_api_f_4lxml_5etree_pyunicode static PyObject *(*__pyx_api_f_4lxml_5etree_utf8)(PyObject *) = 0; #define utf8 __pyx_api_f_4lxml_5etree_utf8 static PyObject *(*__pyx_api_f_4lxml_5etree_getNsTag)(PyObject *) = 0; #define getNsTag __pyx_api_f_4lxml_5etree_getNsTag static PyObject *(*__pyx_api_f_4lxml_5etree_getNsTagWithEmptyNs)(PyObject *) = 0; #define getNsTagWithEmptyNs __pyx_api_f_4lxml_5etree_getNsTagWithEmptyNs static PyObject *(*__pyx_api_f_4lxml_5etree_namespacedName)(xmlNode *) = 0; #define namespacedName __pyx_api_f_4lxml_5etree_namespacedName static PyObject *(*__pyx_api_f_4lxml_5etree_namespacedNameFromNsName)(const xmlChar *, const xmlChar *) = 0; #define namespacedNameFromNsName __pyx_api_f_4lxml_5etree_namespacedNameFromNsName static void (*__pyx_api_f_4lxml_5etree_iteratorStoreNext)(struct LxmlElementIterator *, struct LxmlElement *) = 0; #define iteratorStoreNext __pyx_api_f_4lxml_5etree_iteratorStoreNext static void (*__pyx_api_f_4lxml_5etree_initTagMatch)(struct LxmlElementTagMatcher *, PyObject *) = 0; #define initTagMatch __pyx_api_f_4lxml_5etree_initTagMatch static xmlNs *(*__pyx_api_f_4lxml_5etree_findOrBuildNodeNsPrefix)(struct LxmlDocument *, xmlNode *, const xmlChar *, const xmlChar *) = 0; #define findOrBuildNodeNsPrefix __pyx_api_f_4lxml_5etree_findOrBuildNodeNsPrefix #if !defined(__Pyx_PyIdentifier_FromString) #if PY_MAJOR_VERSION < 3 #define __Pyx_PyIdentifier_FromString(s) PyString_FromString(s) #else #define __Pyx_PyIdentifier_FromString(s) PyUnicode_FromString(s) #endif #endif #ifndef __PYX_HAVE_RT_ImportFunction #define __PYX_HAVE_RT_ImportFunction static int __Pyx_ImportFunction(PyObject *module, const char *funcname, void (**f)(void), const char *sig) { PyObject *d = 0; PyObject *cobj = 0; union { void (*fp)(void); void *p; } tmp; d = PyObject_GetAttrString(module, (char *)"__pyx_capi__"); if (!d) goto bad; cobj = PyDict_GetItemString(d, funcname); if (!cobj) { PyErr_Format(PyExc_ImportError, "%.200s does not export expected C function %.200s", PyModule_GetName(module), funcname); goto bad; } #if PY_VERSION_HEX >= 0x02070000 if (!PyCapsule_IsValid(cobj, sig)) { PyErr_Format(PyExc_TypeError, "C function %.200s.%.200s has wrong signature (expected %.500s, got %.500s)", PyModule_GetName(module), funcname, sig, PyCapsule_GetName(cobj)); goto bad; } tmp.p = PyCapsule_GetPointer(cobj, sig); #else {const char *desc, *s1, *s2; desc = (const char *)PyCObject_GetDesc(cobj); if (!desc) goto bad; s1 = desc; s2 = sig; while (*s1 != '\0' && *s1 == *s2) { s1++; s2++; } if (*s1 != *s2) { PyErr_Format(PyExc_TypeError, "C function %.200s.%.200s has wrong signature (expected %.500s, got %.500s)", PyModule_GetName(module), funcname, sig, desc); goto bad; } tmp.p = PyCObject_AsVoidPtr(cobj);} #endif *f = tmp.fp; if (!(*f)) goto bad; Py_DECREF(d); return 0; bad: Py_XDECREF(d); return -1; } #endif static int import_lxml__etree(void) { PyObject *module = 0; module = PyImport_ImportModule("lxml.etree"); if (!module) goto bad; if (__Pyx_ImportFunction(module, "deepcopyNodeToDocument", (void (**)(void))&__pyx_api_f_4lxml_5etree_deepcopyNodeToDocument, "struct LxmlElement *(struct LxmlDocument *, xmlNode *)") < 0) goto bad; if (__Pyx_ImportFunction(module, "elementTreeFactory", (void (**)(void))&__pyx_api_f_4lxml_5etree_elementTreeFactory, "struct LxmlElementTree *(struct LxmlElement *)") < 0) goto bad; if (__Pyx_ImportFunction(module, "newElementTree", (void (**)(void))&__pyx_api_f_4lxml_5etree_newElementTree, "struct LxmlElementTree *(struct LxmlElement *, PyObject *)") < 0) goto bad; if (__Pyx_ImportFunction(module, "adoptExternalDocument", (void (**)(void))&__pyx_api_f_4lxml_5etree_adoptExternalDocument, "struct LxmlElementTree *(xmlDoc *, PyObject *, int)") < 0) goto bad; if (__Pyx_ImportFunction(module, "elementFactory", (void (**)(void))&__pyx_api_f_4lxml_5etree_elementFactory, "struct LxmlElement *(struct LxmlDocument *, xmlNode *)") < 0) goto bad; if (__Pyx_ImportFunction(module, "makeElement", (void (**)(void))&__pyx_api_f_4lxml_5etree_makeElement, "struct LxmlElement *(PyObject *, struct LxmlDocument *, PyObject *, PyObject *, PyObject *, PyObject *, PyObject *)") < 0) goto bad; if (__Pyx_ImportFunction(module, "makeSubElement", (void (**)(void))&__pyx_api_f_4lxml_5etree_makeSubElement, "struct LxmlElement *(struct LxmlElement *, PyObject *, PyObject *, PyObject *, PyObject *, PyObject *)") < 0) goto bad; if (__Pyx_ImportFunction(module, "setElementClassLookupFunction", (void (**)(void))&__pyx_api_f_4lxml_5etree_setElementClassLookupFunction, "void (_element_class_lookup_function, PyObject *)") < 0) goto bad; if (__Pyx_ImportFunction(module, "lookupDefaultElementClass", (void (**)(void))&__pyx_api_f_4lxml_5etree_lookupDefaultElementClass, "PyObject *(PyObject *, PyObject *, xmlNode *)") < 0) goto bad; if (__Pyx_ImportFunction(module, "lookupNamespaceElementClass", (void (**)(void))&__pyx_api_f_4lxml_5etree_lookupNamespaceElementClass, "PyObject *(PyObject *, PyObject *, xmlNode *)") < 0) goto bad; if (__Pyx_ImportFunction(module, "callLookupFallback", (void (**)(void))&__pyx_api_f_4lxml_5etree_callLookupFallback, "PyObject *(struct LxmlFallbackElementClassLookup *, struct LxmlDocument *, xmlNode *)") < 0) goto bad; if (__Pyx_ImportFunction(module, "tagMatches", (void (**)(void))&__pyx_api_f_4lxml_5etree_tagMatches, "int (xmlNode *, const xmlChar *, const xmlChar *)") < 0) goto bad; if (__Pyx_ImportFunction(module, "documentOrRaise", (void (**)(void))&__pyx_api_f_4lxml_5etree_documentOrRaise, "struct LxmlDocument *(PyObject *)") < 0) goto bad; if (__Pyx_ImportFunction(module, "rootNodeOrRaise", (void (**)(void))&__pyx_api_f_4lxml_5etree_rootNodeOrRaise, "struct LxmlElement *(PyObject *)") < 0) goto bad; if (__Pyx_ImportFunction(module, "hasText", (void (**)(void))&__pyx_api_f_4lxml_5etree_hasText, "int (xmlNode *)") < 0) goto bad; if (__Pyx_ImportFunction(module, "hasTail", (void (**)(void))&__pyx_api_f_4lxml_5etree_hasTail, "int (xmlNode *)") < 0) goto bad; if (__Pyx_ImportFunction(module, "textOf", (void (**)(void))&__pyx_api_f_4lxml_5etree_textOf, "PyObject *(xmlNode *)") < 0) goto bad; if (__Pyx_ImportFunction(module, "tailOf", (void (**)(void))&__pyx_api_f_4lxml_5etree_tailOf, "PyObject *(xmlNode *)") < 0) goto bad; if (__Pyx_ImportFunction(module, "setNodeText", (void (**)(void))&__pyx_api_f_4lxml_5etree_setNodeText, "int (xmlNode *, PyObject *)") < 0) goto bad; if (__Pyx_ImportFunction(module, "setTailText", (void (**)(void))&__pyx_api_f_4lxml_5etree_setTailText, "int (xmlNode *, PyObject *)") < 0) goto bad; if (__Pyx_ImportFunction(module, "attributeValue", (void (**)(void))&__pyx_api_f_4lxml_5etree_attributeValue, "PyObject *(xmlNode *, xmlAttr *)") < 0) goto bad; if (__Pyx_ImportFunction(module, "attributeValueFromNsName", (void (**)(void))&__pyx_api_f_4lxml_5etree_attributeValueFromNsName, "PyObject *(xmlNode *, const xmlChar *, const xmlChar *)") < 0) goto bad; if (__Pyx_ImportFunction(module, "getAttributeValue", (void (**)(void))&__pyx_api_f_4lxml_5etree_getAttributeValue, "PyObject *(struct LxmlElement *, PyObject *, PyObject *)") < 0) goto bad; if (__Pyx_ImportFunction(module, "iterattributes", (void (**)(void))&__pyx_api_f_4lxml_5etree_iterattributes, "PyObject *(struct LxmlElement *, int)") < 0) goto bad; if (__Pyx_ImportFunction(module, "collectAttributes", (void (**)(void))&__pyx_api_f_4lxml_5etree_collectAttributes, "PyObject *(xmlNode *, int)") < 0) goto bad; if (__Pyx_ImportFunction(module, "setAttributeValue", (void (**)(void))&__pyx_api_f_4lxml_5etree_setAttributeValue, "int (struct LxmlElement *, PyObject *, PyObject *)") < 0) goto bad; if (__Pyx_ImportFunction(module, "delAttribute", (void (**)(void))&__pyx_api_f_4lxml_5etree_delAttribute, "int (struct LxmlElement *, PyObject *)") < 0) goto bad; if (__Pyx_ImportFunction(module, "delAttributeFromNsName", (void (**)(void))&__pyx_api_f_4lxml_5etree_delAttributeFromNsName, "int (xmlNode *, const xmlChar *, const xmlChar *)") < 0) goto bad; if (__Pyx_ImportFunction(module, "hasChild", (void (**)(void))&__pyx_api_f_4lxml_5etree_hasChild, "int (xmlNode *)") < 0) goto bad; if (__Pyx_ImportFunction(module, "findChild", (void (**)(void))&__pyx_api_f_4lxml_5etree_findChild, "xmlNode *(xmlNode *, Py_ssize_t)") < 0) goto bad; if (__Pyx_ImportFunction(module, "findChildForwards", (void (**)(void))&__pyx_api_f_4lxml_5etree_findChildForwards, "xmlNode *(xmlNode *, Py_ssize_t)") < 0) goto bad; if (__Pyx_ImportFunction(module, "findChildBackwards", (void (**)(void))&__pyx_api_f_4lxml_5etree_findChildBackwards, "xmlNode *(xmlNode *, Py_ssize_t)") < 0) goto bad; if (__Pyx_ImportFunction(module, "nextElement", (void (**)(void))&__pyx_api_f_4lxml_5etree_nextElement, "xmlNode *(xmlNode *)") < 0) goto bad; if (__Pyx_ImportFunction(module, "previousElement", (void (**)(void))&__pyx_api_f_4lxml_5etree_previousElement, "xmlNode *(xmlNode *)") < 0) goto bad; if (__Pyx_ImportFunction(module, "appendChild", (void (**)(void))&__pyx_api_f_4lxml_5etree_appendChild, "void (struct LxmlElement *, struct LxmlElement *)") < 0) goto bad; if (__Pyx_ImportFunction(module, "appendChildToElement", (void (**)(void))&__pyx_api_f_4lxml_5etree_appendChildToElement, "int (struct LxmlElement *, struct LxmlElement *)") < 0) goto bad; if (__Pyx_ImportFunction(module, "pyunicode", (void (**)(void))&__pyx_api_f_4lxml_5etree_pyunicode, "PyObject *(const xmlChar *)") < 0) goto bad; if (__Pyx_ImportFunction(module, "utf8", (void (**)(void))&__pyx_api_f_4lxml_5etree_utf8, "PyObject *(PyObject *)") < 0) goto bad; if (__Pyx_ImportFunction(module, "getNsTag", (void (**)(void))&__pyx_api_f_4lxml_5etree_getNsTag, "PyObject *(PyObject *)") < 0) goto bad; if (__Pyx_ImportFunction(module, "getNsTagWithEmptyNs", (void (**)(void))&__pyx_api_f_4lxml_5etree_getNsTagWithEmptyNs, "PyObject *(PyObject *)") < 0) goto bad; if (__Pyx_ImportFunction(module, "namespacedName", (void (**)(void))&__pyx_api_f_4lxml_5etree_namespacedName, "PyObject *(xmlNode *)") < 0) goto bad; if (__Pyx_ImportFunction(module, "namespacedNameFromNsName", (void (**)(void))&__pyx_api_f_4lxml_5etree_namespacedNameFromNsName, "PyObject *(const xmlChar *, const xmlChar *)") < 0) goto bad; if (__Pyx_ImportFunction(module, "iteratorStoreNext", (void (**)(void))&__pyx_api_f_4lxml_5etree_iteratorStoreNext, "void (struct LxmlElementIterator *, struct LxmlElement *)") < 0) goto bad; if (__Pyx_ImportFunction(module, "initTagMatch", (void (**)(void))&__pyx_api_f_4lxml_5etree_initTagMatch, "void (struct LxmlElementTagMatcher *, PyObject *)") < 0) goto bad; if (__Pyx_ImportFunction(module, "findOrBuildNodeNsPrefix", (void (**)(void))&__pyx_api_f_4lxml_5etree_findOrBuildNodeNsPrefix, "xmlNs *(struct LxmlDocument *, xmlNode *, const xmlChar *, const xmlChar *)") < 0) goto bad; Py_DECREF(module); module = 0; return 0; bad: Py_XDECREF(module); return -1; } #endif /* !__PYX_HAVE_API__lxml__etree */ ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/lxml/html/ElementSoup.py ================================================ __doc__ = """Legacy interface to the BeautifulSoup HTML parser. """ __all__ = ["parse", "convert_tree"] from soupparser import convert_tree, parse as _parse def parse(file, beautifulsoup=None, makeelement=None): root = _parse(file, beautifulsoup=beautifulsoup, makeelement=makeelement) return root.getroot() ================================================ FILE: stackoverflow/venv/lib/python3.6/site-packages/lxml/html/__init__.py ================================================ # Copyright (c) 2004 Ian Bicking. All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # # 3. Neither the name of Ian Bicking nor the names of its contributors may # be used to endorse or promote products derived from this software # without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL IAN BICKING OR # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """The ``lxml.html`` tool set for HTML handling. """ from __future__ import absolute_import __all__ = [ 'document_fromstring', 'fragment_fromstring', 'fragments_fromstring', 'fromstring', 'tostring', 'Element', 'defs', 'open_in_browser', 'submit_form', 'find_rel_links', 'find_class', 'make_links_absolute', 'resolve_base_href', 'iterlinks', 'rewrite_links', 'open_in_browser', 'parse'] import copy import sys import re from functools import partial try: from collections.abc import MutableMapping, MutableSet except ImportError: from collections import MutableMapping, MutableSet from .. import etree from . import defs from ._setmixin import SetMixin try: from urlparse import urljoin except ImportError: # Python 3 from urllib.parse import urljoin try: unicode except NameError: # Python 3 unicode = str try: basestring except NameError: # Python 3 basestring = (str, bytes) def __fix_docstring(s): if not s: return s if sys.version_info[0] >= 3: sub = re.compile(r"^(\s*)u'", re.M).sub else: sub = re.compile(r"^(\s*)b'", re.M).sub return sub(r"\1'", s) XHTML_NAMESPACE = "http://www.w3.org/1999/xhtml" _rel_links_xpath = etree.XPath("descendant-or-self::a[@rel]|descendant-or-self::x:a[@rel]", namespaces={'x':XHTML_NAMESPACE}) _options_xpath = etree.XPath("descendant-or-self::option|descendant-or-self::x:option", namespaces={'x':XHTML_NAMESPACE}) _forms_xpath = etree.XPath("descendant-or-self::form|descendant-or-self::x:form", namespaces={'x':XHTML_NAMESPACE}) #_class_xpath = etree.XPath(r"descendant-or-self::*[regexp:match(@class, concat('\b', $class_name, '\b'))]", {'regexp': 'http://exslt.org/regular-expressions'}) _class_xpath = etree.XPath("descendant-or-self::*[@class and contains(concat(' ', normalize-space(@class), ' '), concat(' ', $class_name, ' '))]") _id_xpath = etree.XPath("descendant-or-self::*[@id=$id]") _collect_string_content = etree.XPath("string()") _iter_css_urls = re.compile(r'url\(('+'["][^"]*["]|'+"['][^']*[']|"+r'[^)]*)\)', re.I).finditer _iter_css_imports = re.compile(r'@import "(.*?)"').finditer _label_xpath = etree.XPath("//label[@for=$id]|//x:label[@for=$id]", namespaces={'x':XHTML_NAMESPACE}) _archive_re = re.compile(r'[^ ]+') _parse_meta_refresh_url = re.compile( r'[^;=]*;\s*(?:url\s*=\s*)?(?P.*)$', re.I).search def _unquote_match(s, pos): if s[:1] == '"' and s[-1:] == '"' or s[:1] == "'" and s[-1:] == "'": return s[1:-1], pos+1 else: return s,pos def _transform_result(typ, result): """Convert the result back into the input type. """ if issubclass(typ, bytes): return tostring(result, encoding='utf-8') elif issubclass(typ, unicode): return tostring(result, encoding='unicode') else: return result def _nons(tag): if isinstance(tag, basestring): if tag[0] == '{' and tag[1:len(XHTML_NAMESPACE)+1] == XHTML_NAMESPACE: return tag.split('}')[-1] return tag class Classes(MutableSet): """Provides access to an element's class attribute as a set-like collection. Usage:: >>> el = fromstring('') >>> classes = el.classes # or: classes = Classes(el.attrib) >>> classes |= ['block', 'paragraph'] >>> el.get('class') 'hidden large block paragraph' >>> classes.toggle('hidden') False >>> el.get('class') 'large block paragraph' >>> classes -= ('some', 'classes', 'block') >>> el.get('class') 'large paragraph' """ def __init__(self, attributes): self._attributes = attributes self._get_class_value = partial(attributes.get, 'class', '') def add(self, value): """ Add a class. This has no effect if the class is already present. """ if not value or re.search(r'\s', value): raise ValueError("Invalid class name: %r" % value) classes = self._get_class_value().split() if value in classes: return classes.append(value) self._attributes['class'] = ' '.join(classes) def discard(self, value): """ Remove a class if it is currently present. If the class is not present, do nothing. """ if not value or re.search(r'\s', value): raise ValueError("Invalid class name: %r" % value) classes = [name for name in self._get_class_value().split() if name != value] if classes: self._attributes['class'] = ' '.join(classes) elif 'class' in self._attributes: del self._attributes['class'] def remove(self, value): """ Remove a class; it must currently be present. If the class is not present, raise a KeyError. """ if not value or re.search(r'\s', value): raise ValueError("Invalid class name: %r" % value) super(Classes, self).remove(value) def __contains__(self, name): classes = self._get_class_value() return name in classes and name in classes.split() def __iter__(self): return iter(self._get_class_value().split()) def __len__(self): return len(self._get_class_value().split()) # non-standard methods def update(self, values): """ Add all names from 'values'. """ classes = self._get_class_value().split() extended = False for value in values: if value not in classes: classes.append(value) extended = True if extended: self._attributes['class'] = ' '.join(classes) def toggle(self, value): """ Add a class name if it isn't there yet, or remove it if it exists. Returns true if the class was added (and is now enabled) and false if it was removed (and is now disabled). """ if not value or re.search(r'\s', value): raise ValueError("Invalid class name: %r" % value) classes = self._get_class_value().split() try: classes.remove(value) enabled = False except ValueError: classes.append(value) enabled = True if classes: self._attributes['class'] = ' '.join(classes) else: del self._attributes['class'] return enabled class HtmlMixin(object): def set(self, key, value=None): """set(self, key, value=None) Sets an element attribute. If no value is provided, or if the value is None, creates a 'boolean' attribute without value, e.g. "
" for ``form.set('novalidate')``. """ super(HtmlElement, self).set(key, value) @property def classes(self): """ A set-like wrapper around the 'class' attribute. """ return Classes(self.attrib) @classes.setter def classes(self, classes): assert isinstance(classes, Classes) # only allow "el.classes |= ..." etc. value = classes._get_class_value() if value: self.set('class', value) elif self.get('class') is not None: del self.attrib['class'] @property def base_url(self): """ Returns the base URL, given when the page was parsed. Use with ``urlparse.urljoin(el.base_url, href)`` to get absolute URLs. """ return self.getroottree().docinfo.URL @property def forms(self): """ Return a list of all the forms """ return _forms_xpath(self) @property def body(self): """ Return the element. Can be called from a child element to get the document's head. """ return self.xpath('//body|//x:body', namespaces={'x':XHTML_NAMESPACE})[0] @property def head(self): """ Returns the element. Can be called from a child element to get the document's head. """ return self.xpath('//head|//x:head', namespaces={'x':XHTML_NAMESPACE})[0] @property def label(self): """ Get or set any