diff --git a/rules/combo/backdoor/py_setuptools.yara b/rules/combo/backdoor/py_setuptools.yara index f69836af7..a71a598b8 100644 --- a/rules/combo/backdoor/py_setuptools.yara +++ b/rules/combo/backdoor/py_setuptools.yara @@ -24,6 +24,7 @@ rule setuptools_cmd_exec : suspicious { $f_subprocess = /subprocess.\w{0,32}\([\"\'\/\w\ \-\)]{0,64}/ $not_comment = "Editable install to a prefix should be discoverable." $not_egg_info_requires = "os.path.join(egg_info_dir, 'requires.txt')" + $not_requests = "'Documentation': 'https://requests.readthedocs.io'" condition: pythonSetup and any of ($f*) and none of ($not*) } @@ -34,7 +35,12 @@ rule setuptools_eval : critical { strings: $f_sys_val = /eval\([\"\'\w\ \-\)\/]{0,64}/ fullword $f_subprocess_val = /exec\([\"\'\/\w\ \-\)]{0,64}/ fullword + $not_apache = "# Licensed under the Apache License, Version 2.0 (the \"License\")" $not_comment = "Editable install to a prefix should be discoverable." + $not_google = /# Copyright [1-2][0-9]{3} Google Inc/ + $not_idna = "A library to support the Internationalised Domain Names in Applications" + $not_idna2 = "(IDNA) protocol as specified in RFC 5890 et.al." + $not_requests = "'Documentation': 'https://requests.readthedocs.io'" $not_test_egg_class = "class TestEggInfo" condition: pythonSetup and any of ($f*) and none of ($not*) diff --git a/rules/combo/backdoor/remote_eval.yara b/rules/combo/backdoor/remote_eval.yara index 5e7d05b0c..33ac26f13 100644 --- a/rules/combo/backdoor/remote_eval.yara +++ b/rules/combo/backdoor/remote_eval.yara @@ -57,10 +57,13 @@ rule python_exec_near_get : critical { hash_2024_xFileSyncerx_xfilesyncerx = "c68e907642a8462c6b82a50bf4fde82bbf71245ab4edace246dd341dc72e5867" hash_2024_2024_d3duct1v_xfilesyncerx = "b87023e546bcbde77dae065ad3634e7a6bd4cc6056167a6ed348eee6f2a168ae" strings: - $exec = "exec(" - $requests = /[a-z]{1,4}.get\(/ fullword + $f_exec = "exec(" + $f_requests = /[a-z]{1,4}.get\(/ fullword + $not_pyparser = "All of the heavy" + $not_pyparser2 = "lifting is handled by pyparsing (http://pyparsing.sf.net)." + $not_sparser = "sparser.py [options] filename" condition: - all of them and math.abs(@requests - @exec) <= 32 + all of ($f*) and math.abs(@f_requests - @f_exec) <= 32 and none of ($not*) } rule python_eval_near_get : critical { diff --git a/samples/Python/clean/google-auth-library-python/setup.py b/samples/Python/clean/google-auth-library-python/setup.py new file mode 100644 index 000000000..50ac473ba --- /dev/null +++ b/samples/Python/clean/google-auth-library-python/setup.py @@ -0,0 +1,89 @@ +# Copyright 2014 Google 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. + +import io +import os + +from setuptools import find_packages +from setuptools import setup + + +DEPENDENCIES = ( + "cachetools>=2.0.0,<6.0", + "pyasn1-modules>=0.2.1", + # rsa==4.5 is the last version to support 2.7 + # https://github.com/sybrenstuvel/python-rsa/issues/152#issuecomment-643470233 + 'rsa<4.6; python_version < "3.6"', + 'rsa>=3.1.4,<5; python_version >= "3.6"', + # install enum34 to support 2.7. enum34 only works up to python version 3.3. + 'enum34>=1.1.10; python_version < "3.4"', + "six>=1.9.0", +) + +extras = { + "aiohttp": [ + "aiohttp >= 3.6.2, < 4.0.0dev; python_version>='3.6'", + "requests >= 2.20.0, < 3.0.0dev", + ], + "pyopenssl": ["pyopenssl>=20.0.0", "cryptography>=38.0.3"], + "requests": "requests >= 2.20.0, < 3.0.0dev", + "reauth": "pyu2f>=0.1.5", + # Enterprise cert only works for OpenSSL 1.1.1. Newer versions of these + # dependencies are built with OpenSSL 3.0 so we need to fix the version. + "enterprise_cert": ["cryptography==36.0.2", "pyopenssl==22.0.0"], +} + +with io.open("README.rst", "r") as fh: + long_description = fh.read() + +package_root = os.path.abspath(os.path.dirname(__file__)) + +version = {} +with open(os.path.join(package_root, "google/auth/version.py")) as fp: + exec(fp.read(), version) +version = version["__version__"] + +setup( + name="google-auth", + version=version, + author="Google Cloud Platform", + author_email="googleapis-packages@google.com", + description="Google Authentication Library", + long_description=long_description, + url="https://github.com/googleapis/google-auth-library-python", + packages=find_packages(exclude=("tests*", "system_tests*")), + namespace_packages=("google",), + install_requires=DEPENDENCIES, + extras_require=extras, + python_requires=">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*", + license="Apache 2.0", + keywords="google auth oauth client", + classifiers=[ + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.6", + "Programming Language :: Python :: 3.7", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Development Status :: 5 - Production/Stable", + "Intended Audience :: Developers", + "License :: OSI Approved :: Apache Software License", + "Operating System :: POSIX", + "Operating System :: Microsoft :: Windows", + "Operating System :: MacOS :: MacOS X", + "Operating System :: OS Independent", + "Topic :: Internet :: WWW/HTTP", + ], +) diff --git a/samples/Python/clean/google-auth-library-python/setup.py.simple b/samples/Python/clean/google-auth-library-python/setup.py.simple new file mode 100644 index 000000000..4f7e1a478 --- /dev/null +++ b/samples/Python/clean/google-auth-library-python/setup.py.simple @@ -0,0 +1,5 @@ +# Python/clean/google-auth-library-python/setup.py +exec/shell_command +fd/read +ref/site/url +techniques/code_eval diff --git a/samples/Python/clean/idna/setup.py b/samples/Python/clean/idna/setup.py new file mode 100644 index 000000000..dffa23d7b --- /dev/null +++ b/samples/Python/clean/idna/setup.py @@ -0,0 +1,62 @@ +""" +A library to support the Internationalised Domain Names in Applications +(IDNA) protocol as specified in RFC 5890 et.al. This new methodology, +known as IDNA 2008, can generate materially different results to the +previous standard. The library can act as a drop-in replacement for +the "encodings.idna" module. +""" + +import io, sys +from setuptools import setup + + +def main(): + + python_version = sys.version_info[:2] + if python_version < (3,4): + raise SystemExit("Sorry, Python 3.4 or newer required") + + package_data = {} + exec(open('idna/package_data.py').read(), package_data) + + arguments = { + 'name': 'idna', + 'packages': ['idna'], + 'package_data': {'idna': ['py.typed']}, + 'include_package_data': True, + 'version': package_data['__version__'], + 'description': 'Internationalized Domain Names in Applications (IDNA)', + 'long_description': open("README.rst", encoding="UTF-8").read(), + 'author': 'Kim Davies', + 'author_email': 'kim@cynosure.com.au', + 'license': 'BSD-3-Clause', + 'url': 'https://github.com/kjd/idna', + 'classifiers': [ + 'Development Status :: 5 - Production/Stable', + 'Intended Audience :: Developers', + 'Intended Audience :: System Administrators', + 'License :: OSI Approved :: BSD License', + 'Operating System :: OS Independent', + 'Programming Language :: Python', + 'Programming Language :: Python :: 3', + 'Programming Language :: Python :: 3 :: Only', + 'Programming Language :: Python :: 3.5', + 'Programming Language :: Python :: 3.6', + 'Programming Language :: Python :: 3.7', + 'Programming Language :: Python :: 3.8', + 'Programming Language :: Python :: 3.9', + 'Programming Language :: Python :: 3.10', + 'Programming Language :: Python :: Implementation :: CPython', + 'Programming Language :: Python :: Implementation :: PyPy', + 'Topic :: Internet :: Name Service (DNS)', + 'Topic :: Software Development :: Libraries :: Python Modules', + 'Topic :: Utilities', + ], + 'python_requires': '>=3.5', + 'test_suite': 'tests', + } + + setup(**arguments) + +if __name__ == '__main__': + main() diff --git a/samples/Python/clean/idna/setup.py.simple b/samples/Python/clean/idna/setup.py.simple new file mode 100644 index 000000000..3fac82bb4 --- /dev/null +++ b/samples/Python/clean/idna/setup.py.simple @@ -0,0 +1,4 @@ +# Python/clean/idna/setup.py +fd/read +ref/site/url +techniques/code_eval diff --git a/samples/Python/clean/ml_sdk/setup.py b/samples/Python/clean/ml_sdk/setup.py new file mode 100644 index 000000000..e63fe26a7 --- /dev/null +++ b/samples/Python/clean/ml_sdk/setup.py @@ -0,0 +1,48 @@ +# Copyright 2016 Google Inc. All Rights Reserved. +# +# 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. +"""Package Setup for the Google Cloud ML SDK. +""" + +import os +from setuptools import find_packages +from setuptools import setup + + +def get_required_install_packages(): + global_names = {} + # pylint: disable=exec-used + with open(os.path.normpath('google/cloud/ml/version.py')) as f: + exec(f.read(), global_names) + return global_names['required_install_packages'] + + +def get_version(): + global_names = {} + # pylint: disable=exec-used + with open(os.path.normpath('google/cloud/ml/version.py')) as f: + exec(f.read(), global_names) + return global_names['__version__'] + + +setup( + name='cloudml', + version=get_version(), + author='Google', + author_email='cloudml-feedback@google.com', + namespace_packages=['google', 'google.cloud'], + install_requires=get_required_install_packages(), + packages=find_packages(), + include_package_data=True, + description='Google Cloud Machine Learning Prediction SDK', + requires=[]) diff --git a/samples/Python/clean/ml_sdk/setup.py.simple b/samples/Python/clean/ml_sdk/setup.py.simple new file mode 100644 index 000000000..0996ffc81 --- /dev/null +++ b/samples/Python/clean/ml_sdk/setup.py.simple @@ -0,0 +1,4 @@ +# Python/clean/ml_sdk/setup.py +fd/read +ref/site/url +techniques/code_eval diff --git a/samples/Python/clean/pyparsing/sparser.py b/samples/Python/clean/pyparsing/sparser.py new file mode 100644 index 000000000..d4604dabf --- /dev/null +++ b/samples/Python/clean/pyparsing/sparser.py @@ -0,0 +1,363 @@ +#!/usr/bin/env python + +""" +NAME: + sparser.py + +SYNOPSIS: + sparser.py [options] filename + +DESCRIPTION: + The sparser.py script is a Specified PARSER. It is unique (as far as I can + tell) because it doesn't care about the delimiter(s). The user specifies + what is expected, and the order, for each line of text. All of the heavy + lifting is handled by pyparsing (http://pyparsing.sf.net). + +OPTIONS: + -h,--help this message + -v,--version version + -d,--debug turn on debug messages + +EXAMPLES: + 1. As standalone + sparser.py myfile + 2. As library + import sparser + ... + +#Copyright (C) 2006 Tim Cera timcera@earthlink.net +# +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the Free +# Software Foundation; either version 2 of the License, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 675 Mass Ave, Cambridge, MA 02139, USA. +""" + +#===imports====================== +import sys +import os +import getopt + +from pyparsing import * + + +#===globals====================== +modname = "sparser" +__version__ = "0.1" + + +#--option args-- +debug_p = 0 +#opt_b=None #string arg, default is undefined + + +#---positional args, default is empty--- +pargs = [] + + +#---other--- + + +#===utilities==================== +def msg(txt): + """Send message to stdout.""" + sys.stdout.write(txt) + sys.stdout.flush() + +def debug(ftn, txt): + """Used for debugging.""" + if debug_p: + sys.stdout.write("{0}.{1}:{2}\n".format(modname, ftn, txt)) + sys.stdout.flush() + +def fatal(ftn, txt): + """If can't continue.""" + msg = "{0}.{1}:FATAL:{2}\n".format(modname, ftn, txt) + raise SystemExit(msg) + +def usage(): + """Prints the docstring.""" + print(__doc__) + + + +#==================================== +class ToInteger(TokenConverter): + """Converter to make token into an integer.""" + def postParse( self, instring, loc, tokenlist ): + return int(tokenlist[0]) + +class ToFloat(TokenConverter): + """Converter to make token into a float.""" + def postParse( self, instring, loc, tokenlist ): + return float(tokenlist[0]) + +class ParseFileLineByLine: + """ + Bring data from text files into a program, optionally parsing each line + according to specifications in a parse definition file. + + ParseFileLineByLine instances can be used like normal file objects (i.e. by + calling readline(), readlines(), and write()), but can also be used as + sequences of lines in for-loops. + + ParseFileLineByLine objects also handle compression transparently. i.e. it + is possible to read lines from a compressed text file as if it were not + compressed. Compression is deduced from the file name suffixes '.Z' + (compress/uncompress), '.gz' (gzip/gunzip), and '.bz2' (bzip2). + + The parse definition fi le name is developed based on the input file name. + If the input file name is 'basename.ext', then the definition file is + 'basename_def.ext'. If a definition file specific to the input file is not + found, then the program searches for the file 'sparse.def' which would be + the definition file for all files in that directory without a file specific + definition file. + + Finally, ParseFileLineByLine objects accept file names that start with '~' + or '~user' to indicate a home directory, as well as URLs (for reading + only). + + Constructor: + ParseFileLineByLine(|filename|, |mode|='"r"'), where |filename| is the name + of the file (or a URL) and |mode| is one of '"r"' (read), '"w"' (write) or + '"a"' (append, not supported for .Z files). + """ + + def __init__(self, filename, mode = 'r'): + """Opens input file, and if available the definition file. If the + definition file is available __init__ will then create some pyparsing + helper variables. """ + if mode not in ['r', 'w', 'a']: + raise IOError(0, 'Illegal mode: ' + repr(mode)) + + if string.find(filename, ':/') > 1: # URL + if mode == 'w': + raise IOError("can't write to a URL") + import urllib.request, urllib.parse, urllib.error + self.file = urllib.request.urlopen(filename) + else: + filename = os.path.expanduser(filename) + if mode == 'r' or mode == 'a': + if not os.path.exists(filename): + raise IOError(2, 'No such file or directory: ' + filename) + filen, file_extension = os.path.splitext(filename) + command_dict = { + ('.Z', 'r'): + "self.file = os.popen('uncompress -c ' + filename, mode)", + ('.gz', 'r'): + "self.file = gzip.GzipFile(filename, 'rb')", + ('.bz2', 'r'): + "self.file = os.popen('bzip2 -dc ' + filename, mode)", + ('.Z', 'w'): + "self.file = os.popen('compress > ' + filename, mode)", + ('.gz', 'w'): + "self.file = gzip.GzipFile(filename, 'wb')", + ('.bz2', 'w'): + "self.file = os.popen('bzip2 > ' + filename, mode)", + ('.Z', 'a'): + "raise IOError, (0, 'Can\'t append to .Z files')", + ('.gz', 'a'): + "self.file = gzip.GzipFile(filename, 'ab')", + ('.bz2', 'a'): + "raise IOError, (0, 'Can\'t append to .bz2 files')", + } + + exec(command_dict.get((file_extension, mode), + 'self.file = open(filename, mode)')) + + self.grammar = None + + # Try to find a parse ('*_def.ext') definition file. First try to find + # a file specific parse definition file, then look for 'sparse.def' + # that would be the definition file for all files within the directory. + + # The definition file is pure Python. The one variable that needs to + # be specified is 'parse'. The 'parse' variable is a list of tuples + # defining the name, type, and because it is a list, the order of + # variables on each line in the data file. The variable name is a + # string, the type variable is defined as integer, real, and qString. + + # parse = [ + # ('year', integer), + # ('month', integer), + # ('day', integer), + # ('value', real), + # ] + + definition_file_one = filen + "_def" + file_extension + definition_file_two = os.path.dirname(filen) + os.sep + "sparse.def" + if os.path.exists(definition_file_one): + self.parsedef = definition_file_one + elif os.path.exists(definition_file_two): + self.parsedef = definition_file_two + else: + self.parsedef = None + return None + + # Create some handy pyparsing constructs. I kept 'decimal_sep' so that + # could easily change to parse if the decimal separator is a ",". + decimal_sep = "." + sign = oneOf("+ -") + # part of printables without decimal_sep, +, - + special_chars = string.replace('!"#$%&\'()*,./:;<=>?@[\\]^_`{|}~', + decimal_sep, "") + integer = ToInteger( + Combine(Optional(sign) + + Word(nums))).setName("integer") + positive_integer = ToInteger( + Combine(Optional("+") + + Word(nums))).setName("integer") + negative_integer = ToInteger( + Combine("-" + + Word(nums))).setName("integer") + real = ToFloat( + Combine(Optional(sign) + + Word(nums) + + decimal_sep + + Optional(Word(nums)) + + Optional(oneOf("E e") + + Word(nums)))).setName("real") + positive_real = ToFloat( + Combine(Optional("+") + + Word(nums) + + decimal_sep + + Optional(Word(nums)) + + Optional(oneOf("E e") + + Word(nums)))).setName("real") + negative_real = ToFloat( + Combine("-" + + Word(nums) + + decimal_sep + + Optional(Word(nums)) + + Optional(oneOf("E e") + + Word(nums)))).setName("real") + qString = ( sglQuotedString | dblQuotedString ).setName("qString") + + # add other characters we should skip over between interesting fields + integer_junk = Optional( + Suppress( + Word(alphas + + special_chars + + decimal_sep))).setName("integer_junk") + real_junk = Optional( + Suppress( + Word(alphas + + special_chars))).setName("real_junk") + qString_junk = SkipTo(qString).setName("qString_junk") + + # Now that 'integer', 'real', and 'qString' have been assigned I can + # execute the definition file. + exec(compile(open(self.parsedef).read(), self.parsedef, 'exec')) + + # Build the grammar, combination of the 'integer', 'real, 'qString', + # and '*_junk' variables assigned above in the order specified in the + # definition file. + grammar = [] + for nam, expr in parse: + grammar.append( eval(expr.name + "_junk")) + grammar.append( expr.setResultsName(nam) ) + self.grammar = And( grammar[1:] + [restOfLine] ) + + def __del__(self): + """Delete (close) the file wrapper.""" + self.close() + + def __getitem__(self, item): + """Used in 'for line in fp:' idiom.""" + line = self.readline() + if not line: + raise IndexError + return line + + def readline(self): + """Reads (and optionally parses) a single line.""" + line = self.file.readline() + if self.grammar and line: + try: + return self.grammar.parseString(line).asDict() + except ParseException: + return self.readline() + else: + return line + + def readlines(self): + """Returns a list of all lines (optionally parsed) in the file.""" + if self.grammar: + tot = [] + # Used this way instead of a 'for' loop against + # self.file.readlines() so that there wasn't two copies of the file + # in memory. + while 1: + line = self.file.readline() + if not line: + break + tot.append(line) + return tot + return self.file.readlines() + + def write(self, data): + """Write to a file.""" + self.file.write(data) + + def writelines(self, list): + """Write a list to a file. Each item in the list is a line in the + file. + """ + for line in list: + self.file.write(line) + + def close(self): + """Close the file.""" + self.file.close() + + def flush(self): + """Flush in memory contents to file.""" + self.file.flush() + + +#============================= +def main(pargs): + """This should only be used for testing. The primary mode of operation is + as an imported library. + """ + input_file = sys.argv[1] + fp = ParseFileLineByLine(input_file) + for i in fp: + print(i) + + +#------------------------- +if __name__ == '__main__': + ftn = "main" + opts, pargs = getopt.getopt(sys.argv[1:], 'hvd', + ['help', 'version', 'debug', 'bb=']) + for opt in opts: + if opt[0] == '-h' or opt[0] == '--help': + print(modname+": version="+__version__) + usage() + sys.exit(0) + elif opt[0] == '-v' or opt[0] == '--version': + print(modname+": version="+__version__) + sys.exit(0) + elif opt[0] == '-d' or opt[0] == '--debug': + debug_p = 1 + elif opt[0] == '--bb': + opt_b = opt[1] + + #---make the object and run it--- + main(pargs) + +#===Revision Log=== +#Created by mkpythonproj: +#2006-02-06 Tim Cera +# diff --git a/samples/Python/clean/pyparsing/sparser.py.simple b/samples/Python/clean/pyparsing/sparser.py.simple new file mode 100644 index 000000000..9f46bf208 --- /dev/null +++ b/samples/Python/clean/pyparsing/sparser.py.simple @@ -0,0 +1,11 @@ +# Python/clean/pyparsing/sparser.py +compression/bzip2 +compression/gzip +exec/pipe +fd/read +fd/write +net/url +net/url/request +ref/path/usr/bin +ref/site/url +techniques/code_eval diff --git a/samples/Python/clean/requests/setup.py b/samples/Python/clean/requests/setup.py new file mode 100644 index 000000000..c279c81ba --- /dev/null +++ b/samples/Python/clean/requests/setup.py @@ -0,0 +1,118 @@ +#!/usr/bin/env python +# Learn more: https://github.com/kennethreitz/setup.py +import os +import sys + +from codecs import open + +from setuptools import setup +from setuptools.command.test import test as TestCommand + +here = os.path.abspath(os.path.dirname(__file__)) + +class PyTest(TestCommand): + user_options = [('pytest-args=', 'a', "Arguments to pass into py.test")] + + def initialize_options(self): + TestCommand.initialize_options(self) + try: + from multiprocessing import cpu_count + self.pytest_args = ['-n', str(cpu_count()), '--boxed'] + except (ImportError, NotImplementedError): + self.pytest_args = ['-n', '1', '--boxed'] + + def finalize_options(self): + TestCommand.finalize_options(self) + self.test_args = [] + self.test_suite = True + + def run_tests(self): + import pytest + + errno = pytest.main(self.pytest_args) + sys.exit(errno) + +# 'setup.py publish' shortcut. +if sys.argv[-1] == 'publish': + os.system('python setup.py sdist bdist_wheel') + os.system('twine upload dist/*') + sys.exit() + +packages = ['requests'] + +requires = [ + 'charset_normalizer~=2.0.0; python_version >= "3"', + 'chardet>=3.0.2,<5; python_version < "3"', + 'idna>=2.5,<3; python_version < "3"', + 'idna>=2.5,<4; python_version >= "3"', + 'urllib3>=1.21.1,<1.27', + 'certifi>=2017.4.17' + +] +test_requirements = [ + 'pytest-httpbin==0.0.7', + 'pytest-cov', + 'pytest-mock', + 'pytest-xdist', + 'PySocks>=1.5.6, !=1.5.7', + 'pytest>=3' +] + +about = {} +with open(os.path.join(here, 'requests', '__version__.py'), 'r', 'utf-8') as f: + exec(f.read(), about) + +with open('README.md', 'r', 'utf-8') as f: + readme = f.read() + +setup( + name=about['__title__'], + version=about['__version__'], + description=about['__description__'], + long_description=readme, + long_description_content_type='text/markdown', + author=about['__author__'], + author_email=about['__author_email__'], + url=about['__url__'], + packages=packages, + package_data={'': ['LICENSE', 'NOTICE']}, + package_dir={'requests': 'requests'}, + include_package_data=True, + python_requires=">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*", + install_requires=requires, + license=about['__license__'], + zip_safe=False, + classifiers=[ + 'Development Status :: 5 - Production/Stable', + 'Environment :: Web Environment', + 'Intended Audience :: Developers', + 'License :: OSI Approved :: Apache Software License', + 'Natural Language :: English', + 'Operating System :: OS Independent', + 'Programming Language :: Python', + 'Programming Language :: Python :: 2', + 'Programming Language :: Python :: 2.7', + 'Programming Language :: Python :: 3', + 'Programming Language :: Python :: 3.6', + 'Programming Language :: Python :: 3.7', + 'Programming Language :: Python :: 3.8', + 'Programming Language :: Python :: 3.9', + 'Programming Language :: Python :: 3.10', + 'Programming Language :: Python :: Implementation :: CPython', + 'Programming Language :: Python :: Implementation :: PyPy', + 'Topic :: Internet :: WWW/HTTP', + 'Topic :: Software Development :: Libraries', + ], + cmdclass={'test': PyTest}, + tests_require=test_requirements, + extras_require={ + 'security': [], + 'socks': ['PySocks>=1.5.6, !=1.5.7'], + 'socks:sys_platform == "win32" and python_version == "2.7"': ['win_inet_pton'], + 'use_chardet_on_py3': ['chardet>=3.0.2,<5'] + }, + project_urls={ + 'Documentation': 'https://requests.readthedocs.io', + 'Source': 'https://github.com/psf/requests', + }, +) diff --git a/samples/Python/clean/requests/setup.py.simple b/samples/Python/clean/requests/setup.py.simple new file mode 100644 index 000000000..f4f98362f --- /dev/null +++ b/samples/Python/clean/requests/setup.py.simple @@ -0,0 +1,11 @@ +# Python/clean/requests/setup.py +exec/program +fd/read +net/ip/parse +net/upload +net/url +process/multiprocess +ref/path/usr/bin +ref/site/download +ref/site/url +techniques/code_eval