diff --git a/.circleci/config.yml b/.circleci/config.yml deleted file mode 100644 index bb80c74e..00000000 --- a/.circleci/config.yml +++ /dev/null @@ -1,110 +0,0 @@ -version: 2 -defaults: - taggedReleasesFilter: &taggedReleasesFilter - tags: - only: /^\d+\.\d+\.\d+((a|b|rc)\d)?$/ # matches 1.2.3, 1.2.3a1, 1.2.3b1, 1.2.3rc1 etc.. -jobs: - build: - docker: - - image: circleci/python:3.8 - steps: - - checkout - - run: pip3 install python-dateutil backoff monotonic - - run: pip3 install --user . - - run: sudo pip3 install pylint==2.8.0 flake8 mock==3.0.5 python-dateutil - - run: make test - - store_artifacts: - path: pylint.out - - store_artifacts: - path: flake8.out - - snyk: - docker: - - image: circleci/python:3.9 - steps: - - checkout - - attach_workspace: { at: . } - - run: pip3 install pipreqs - - run: pip3 install --user appdirs - - run: pipreqs . - - run: pip3 install --user -r requirements.txt - - run: curl -sL https://raw.githubusercontent.com/segmentio/snyk_helpers/master/initialization/snyk.sh | sh - - test_37: &test - docker: - - image: circleci/python:3.7 - steps: - - checkout - - run: pip3 install python-dateutil backoff monotonic - - run: pip3 install --user .[test] - - run: - name: Linting with Flake8 - command: | - git diff origin/master..HEAD analytics | flake8 --diff --max-complexity=10 analytics - - run: make test - - run: make e2e_test - - test_38: - <<: *test - docker: - - image: circleci/python:3.8 - - test_39: - <<: *test - docker: - - image: circleci/python:3.9 - - publish: - docker: - - image: circleci/python:3.9 - steps: - - checkout - - run: sudo pip install twine - - run: make release - -workflows: - version: 2 - build_test_release: - jobs: - - build: - filters: - <<: *taggedReleasesFilter - - test_37: - filters: - <<: *taggedReleasesFilter - - test_38: - filters: - <<: *taggedReleasesFilter - - test_39: - filters: - <<: *taggedReleasesFilter - - publish: - requires: - - build - - test_37 - - test_38 - - test_39 - filters: - <<: *taggedReleasesFilter - branches: - ignore: /.*/ - static_analysis: - jobs: - - build - - snyk: - context: snyk - requires: - - build - scheduled_e2e_test: - triggers: - - schedule: - cron: "0 * * * *" - filters: - branches: - only: - - master - - scheduled_e2e_testing - jobs: - - test_37 - - test_38 - - test_39 diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 3d54fd2a..a17f8887 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -21,9 +21,9 @@ jobs: pip install -r requirements.txt pip install python-dateutil backoff monotonic pip install --user . - sudo pip install pylint==2.8.0 flake8 mock==3.0.5 python-dateutil + sudo pip install pylint==2.8.0 flake8 mock==3.0.5 python-dateutil aiohttp==3.9.1 - name: Run tests - run: make e2e_test + run: python -m unittest discover -s segment # snyk: # runs-on: ubuntu-latest diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 7d1c621d..257b7077 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -1,14 +1,15 @@ -name: e2e tests +name: analytics test suite on: push: branches: - master + - '**Tests**' paths-ignore: - '**.md' pull_request: paths-ignore: - - '**.md' + - '**.md' jobs: test-setup-python: @@ -16,44 +17,49 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Run with setup-python 3.7 - uses: ./ + uses: actions/setup-python@v5 with: - python-version: 3.7 + python-version: '3.7' + - name: Setup required modules + run: python -m pip install -r requirements.txt - name: Run tests - run: make test - run: make e2e_test + run: python -m unittest discover -s segment - name: Run with setup-python 3.8 - uses: ./ + uses: actions/setup-python@v5 with: - python-version: 3.8 + python-version: '3.8' + - name: Setup required modules + run: python -m pip install -r requirements.txt - name: Run tests - run: make test - run: make e2e_test + run: python -m unittest discover -s segment - name: Run with setup-python 3.9 - uses: ./ + uses: actions/setup-python@v5 with: - python-version: 3.9 + python-version: '3.9' + - name: Setup required modules + run: python -m pip install -r requirements.txt - name: Run tests - run: make test - run: make e2e_test + run: python -m unittest discover -s segment - name: Run with setup-python 3.10 - uses: ./ + uses: actions/setup-python@v5 with: - python-version: 3.10 + python-version: '3.10' + - name: Setup required modules + run: python -m pip install -r requirements.txt - name: Run tests - run: make test - run: make e2e_test + run: python -m unittest discover -s segment - name: Run with setup-python 3.11 - uses: ./ + uses: actions/setup-python@v5 with: - python-version: 3.11 + python-version: '3.11' + - name: Setup required modules + run: python -m pip install -r requirements.txt - name: Run tests - run: make test - run: make e2e_test \ No newline at end of file + run: python -m unittest discover -s segment \ No newline at end of file diff --git a/.pylintrc b/.pylintrc index 568c4cc2..4712a015 100644 --- a/.pylintrc +++ b/.pylintrc @@ -1,184 +1,139 @@ -[MASTER] - -# Add files or directories to the ignore list. They should be base names, not -# paths. -ignore=CVS - -# Add files or directories matching the regex patterns to the denylist. The -# regex matches against base names, not paths. -ignore-patterns= +[MAIN] # Python code to execute, usually for sys.path manipulation such as # pygtk.require(). #init-hook= -# Use multiple processes to speed up Pylint. -jobs=1 +# Files or directories to be skipped. They should be base names, not +# paths. +ignore=CVS -# List of plugins (as comma separated values of python modules names) to load, -# usually to register additional checkers. -load-plugins= +# Add files or directories matching the regex patterns to the ignore-list. The +# regex matches against paths and can be in Posix or Windows format. +ignore-paths= + +# Files or directories matching the regex patterns are skipped. The regex +# matches against base names, not paths. +ignore-patterns=^\.# # Pickle collected data for later comparisons. persistent=yes -# Specify a configuration file. -#rcfile= +# List of plugins (as comma separated values of python modules names) to load, +# usually to register additional checkers. +load-plugins= + pylint.extensions.check_elif, + pylint.extensions.bad_builtin, + pylint.extensions.docparams, + pylint.extensions.for_any_all, + pylint.extensions.set_membership, + pylint.extensions.code_style, + pylint.extensions.overlapping_exceptions, + pylint.extensions.typing, + pylint.extensions.redefined_variable_type, + pylint.extensions.comparison_placement, + pylint.extensions.broad_try_clause, + pylint.extensions.dict_init_mutate, + pylint.extensions.consider_refactoring_into_while_condition, + +# Use multiple processes to speed up Pylint. Specifying 0 will auto-detect the +# number of processors available to use. +jobs=1 # When enabled, pylint would attempt to guess common misconfiguration and emit -# user-friendly hints instead of false-positive error messages +# user-friendly hints instead of false-positive error messages. suggestion-mode=yes # Allow loading of arbitrary C extensions. Extensions are imported into the # active Python interpreter and may run arbitrary code. unsafe-load-any-extension=no +# A comma-separated list of package or module names from where C extensions may +# be loaded. Extensions are loading into the active Python interpreter and may +# run arbitrary code +extension-pkg-allow-list= + +# Minimum supported python version +py-version = 3.8.0 + +# Control the amount of potential inferred values when inferring a single +# object. This can help the performance when dealing with large functions or +# complex, nested conditions. +limit-inference-results=100 + +# Specify a score threshold under which the program will exit with error. +fail-under=10.0 + +# Return non-zero exit code if any of these messages/categories are detected, +# even if score is above --fail-under value. Syntax same as enable. Messages +# specified are enabled, while categories only check already-enabled messages. +fail-on= + +# Clear in-memory caches upon conclusion of linting. Useful if running pylint in +# a server-like mode. +clear-cache-post-run=no + [MESSAGES CONTROL] # Only show warnings with the listed confidence levels. Leave empty to show # all. Valid levels: HIGH, INFERENCE, INFERENCE_FAILURE, UNDEFINED -confidence= +# confidence= + +# Enable the message, report, category or checker with the given id(s). You can +# either give multiple identifier separated by comma (,) or put this option +# multiple time (only on the command line, not in the configuration file where +# it should appear only once). See also the "--disable" option for examples. +enable= + use-symbolic-message-instead, + useless-suppression, # Disable the message, report, category or checker with the given id(s). You # can either give multiple identifiers separated by comma (,) or put this # option multiple times (only on the command line, not in the configuration # file where it should appear only once).You can also use "--disable=all" to -# disable everything first and then reenable specific checks. For example, if +# disable everything first and then re-enable specific checks. For example, if # you want to run only the similarities checker, you can use "--disable=all # --enable=similarities". If you want to run only the classes checker, but have # no Warning level messages displayed, use"--disable=all --enable=classes # --disable=W" -disable=too-many-public-methods, - no-else-return, - print-statement, - invalid-name, - global-statement, - too-many-arguments, - missing-docstring, - too-many-instance-attributes, - parameter-unpacking, - unpacking-in-except, - old-raise-syntax, - backtick, - long-suffix, - old-ne-operator, - old-octal-literal, - import-star-module-level, - non-ascii-bytes-literal, - invalid-unicode-literal, - raw-checker-failed, - bad-inline-option, - locally-disabled, - locally-enabled, - file-ignored, - suppressed-message, - useless-suppression, - deprecated-pragma, - apply-builtin, - basestring-builtin, - buffer-builtin, - cmp-builtin, - coerce-builtin, - execfile-builtin, - file-builtin, - long-builtin, - raw_input-builtin, - reduce-builtin, - standarderror-builtin, - unicode-builtin, - xrange-builtin, - coerce-method, - delslice-method, - getslice-method, - setslice-method, - no-absolute-import, - old-division, - dict-iter-method, - dict-view-method, - next-method-called, - metaclass-assignment, - indexing-exception, - raising-string, - reload-builtin, - oct-method, - hex-method, - nonzero-method, - cmp-method, - input-builtin, - round-builtin, - intern-builtin, - unichr-builtin, - map-builtin-not-iterating, - zip-builtin-not-iterating, - range-builtin-not-iterating, - filter-builtin-not-iterating, - using-cmp-argument, - eq-without-hash, - div-method, - idiv-method, - rdiv-method, - exception-message-attribute, - invalid-str-codec, - sys-max-int, - bad-python3-import, - deprecated-string-function, - deprecated-str-translate-call, - deprecated-itertools-function, - deprecated-types-field, - next-method-defined, - dict-items-not-iterating, - dict-keys-not-iterating, - dict-values-not-iterating, - deprecated-operator-function, - deprecated-urllib-function, - xreadlines-attribute, - deprecated-sys-function, - exception-escape, - comprehension-escape -# Enable the message, report, category or checker with the given id(s). You can -# either give multiple identifier separated by comma (,) or put this option -# multiple time (only on the command line, not in the configuration file where -# it should appear only once). See also the "--disable" option for examples. -enable=c-extension-no-member +disable= + attribute-defined-outside-init, + invalid-name, + missing-docstring, + protected-access, + too-few-public-methods, + # handled by black + format, + # We anticipate #3512 where it will become optional + fixme, + consider-using-assignment-expr, [REPORTS] -# Python expression which should return a note less than 10 (10 is the highest -# note). You have access to the variables errors warning, statement which -# respectively contain the number of errors / warnings messages and the total -# number of statements analyzed. This is used by the global evaluation report -# (RP0004). -evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10) - -# Template used to display messages. This is a python new-style format string -# used to format the message information. See doc for all details -msg-template={path}:{line}: [{msg_id}({symbol}), {obj}] {msg} - -# Set the output format. Available formats are text, parseable, colorized, json -# and msvs (visual studio).You can also give a reporter class, eg +# Set the output format. Available formats are text, parseable, colorized, msvs +# (visual studio) and html. You can also give a reporter class, eg # mypackage.mymodule.MyReporterClass. output-format=text # Tells whether to display a full report or only the messages reports=no -# Activate the evaluation score. -score=yes - - -[REFACTORING] +# Python expression which should return a note less than 10 (10 is the highest +# note). You have access to the variables 'fatal', 'error', 'warning', 'refactor', 'convention' +# and 'info', which contain the number of messages in each category, as +# well as 'statement', which is the total number of statements analyzed. This +# score is used by the global evaluation report (RP0004). +evaluation=max(0, 0 if fatal else 10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10)) -# Maximum number of nested blocks for function / method body -max-nested-blocks=5 +# Template used to display messages. This is a python new-style format string +# used to format the message information. See doc for all details +#msg-template= -# Complete name of functions that never returns. When checking for -# inconsistent-return-statements if a never returning function is called then -# it will be considered as an explicit return statement and no message will be -# printed. -never-returning-functions=optparse.Values,sys.exit +# Activate the evaluation score. +score=yes [LOGGING] @@ -187,37 +142,25 @@ never-returning-functions=optparse.Values,sys.exit # function parameter format logging-modules=logging - -[SPELLING] - -# Limits count of emitted suggestions for spelling mistakes -max-spelling-suggestions=4 - -# Spelling dictionary name. Available dictionaries: none. To make it working -# install python-enchant package. -spelling-dict= - -# List of comma separated words that should not be checked. -spelling-ignore-words= - -# A path to a file that contains private dictionary; one word per line. -spelling-private-dict-file= - -# Tells whether to store unknown words to indicated private dictionary in -# --spelling-private-dict-file option instead of raising a message. -spelling-store-unknown-words=no +# The type of string formatting that logging methods do. `old` means using % +# formatting, `new` is for `{}` formatting. +logging-format-style=old [MISCELLANEOUS] # List of note tags to take in consideration, separated by a comma. -notes=FIXME, - XXX, - TODO +notes=FIXME,XXX,TODO + +# Regular expression of note tags to take in consideration. +#notes-rgx= [SIMILARITIES] +# Minimum lines number of a similarity. +min-similarity-lines=6 + # Ignore comments when computing similarities. ignore-comments=yes @@ -225,281 +168,274 @@ ignore-comments=yes ignore-docstrings=yes # Ignore imports when computing similarities. -ignore-imports=no - -# Minimum lines number of a similarity. -min-similarity-lines=4 +ignore-imports=yes - -[TYPECHECK] - -# List of decorators that produce context managers, such as -# contextlib.contextmanager. Add to this list to register other decorators that -# produce valid context managers. -contextmanager-decorators=contextlib.contextmanager - -# List of members which are set dynamically and missed by pylint inference -# system, and so shouldn't trigger E1101 when accessed. Python regular -# expressions are accepted. -generated-members= - -# Tells whether missing members accessed in mixin class should be ignored. A -# mixin class is detected if its name ends with "mixin" (case insensitive). -ignore-mixin-members=yes - -# This flag controls whether pylint should warn about no-member and similar -# checks whenever an opaque object is returned when inferring. The inference -# can return multiple potential results while evaluating a Python object, but -# some branches might not be evaluated, which results in partial inference. In -# that case, it might be useful to still emit no-member and other checks for -# the rest of the inferred objects. -ignore-on-opaque-inference=yes - -# List of class names for which member attributes should not be checked (useful -# for classes with dynamically set attributes). This supports the use of -# qualified names. -ignored-classes=optparse.Values,thread._local,_thread._local - -# List of module names for which member attributes should not be checked -# (useful for modules/projects where namespaces are manipulated during runtime -# and thus existing member attributes cannot be deduced by static analysis. It -# supports qualified module names, as well as Unix pattern matching. -ignored-modules= - -# Show a hint with possible names when a member name was not found. The aspect -# of finding the hint is based on edit distance. -missing-member-hint=yes - -# The minimum edit distance a name should have in order to be considered a -# similar match for a missing member name. -missing-member-hint-distance=1 - -# The total number of similar names that should be taken in consideration when -# showing a hint for a missing member. -missing-member-max-choices=1 +# Signatures are removed from the similarity computation +ignore-signatures=yes [VARIABLES] +# Tells whether we should check for unused import in __init__ files. +init-import=no + # List of additional names supposed to be defined in builtins. Remember that -# you should avoid to define new builtins when possible. +# you should avoid defining new builtins when possible. additional-builtins= -# Tells whether unused global variables should be treated as a violation. -allow-global-unused-variables=yes - # List of strings which can identify a callback function by name. A callback # name must start or end with one of those strings. -callbacks=cb_, - _cb +callbacks=cb_,_cb -# A regular expression matching the name of dummy variables (i.e. expectedly -# not used). -dummy-variables-rgx=_+$|(_[a-zA-Z0-9_]*[a-zA-Z0-9]+?$)|dummy|^ignored_|^unused_ - -# Argument names that match this expression will be ignored. Default to name -# with leading underscore -ignored-argument-names=_.*|^ignored_|^unused_ +# Tells whether unused global variables should be treated as a violation. +allow-global-unused-variables=yes -# Tells whether we should check for unused import in __init__ files. -init-import=no +# List of names allowed to shadow builtins +allowed-redefined-builtins= # List of qualified module names which can have objects that can redefine # builtins. -redefining-builtins-modules=past.builtins,future.builtins,io,builtins +redefining-builtins-modules=six.moves,past.builtins,future.builtins,builtins,io [FORMAT] -# Expected format of line ending, e.g. empty (any line ending), LF or CRLF. -expected-line-ending-format= +# Maximum number of characters on a single line. +max-line-length=100 # Regexp for a line that is allowed to be longer than the limit. ignore-long-lines=^\s*(# )??$ -# Number of spaces of indent required inside a hanging or continued line. -indent-after-paren=4 +# Allow the body of an if to be on the same line as the test if there is no +# else. +single-line-if-stmt=no + +# Allow the body of a class to be on the same line as the declaration if body +# contains single statement. +single-line-class-stmt=no + +# Maximum number of lines in a module +max-module-lines=2000 # String used as indentation unit. This is usually " " (4 spaces) or "\t" (1 # tab). indent-string=' ' -# Maximum number of characters on a single line. -max-line-length=100 +# Number of spaces of indent required inside a hanging or continued line. +indent-after-paren=4 -# Maximum number of lines in a module -max-module-lines=1000 +# Expected format of line ending, e.g. empty (any line ending), LF or CRLF. +expected-line-ending-format= -# List of optional constructs for which whitespace checking is disabled. `dict- -# separator` is used to allow tabulation in dicts, etc.: {1 : 1,\n222: 2}. -# `trailing-comma` allows a space between comma and closing bracket: (a, ). -# `empty-line` allows space-only lines. -no-space-check=trailing-comma, - dict-separator -# Allow the body of a class to be on the same line as the declaration if body -# contains single statement. -single-line-class-stmt=no +[BASIC] -# Allow the body of an if to be on the same line as the test if there is no -# else. -single-line-if-stmt=no +# Good variable names which should always be accepted, separated by a comma +good-names=i,j,k,ex,Run,_ +# Good variable names regexes, separated by a comma. If names match any regex, +# they will always be accepted +good-names-rgxs= -[BASIC] +# Bad variable names which should always be refused, separated by a comma +bad-names=foo,bar,baz,toto,tutu,tata -# Naming style matching correct argument names -argument-naming-style=snake_case +# Bad variable names regexes, separated by a comma. If names match any regex, +# they will always be refused +bad-names-rgxs= + +# Colon-delimited sets of names that determine each other's naming style when +# the name regexes allow several styles. +name-group= + +# Include a hint for the correct naming format with invalid-name +include-naming-hint=no + +# Naming style matching correct function names. +function-naming-style=snake_case + +# Regular expression matching correct function names +function-rgx=[a-z_][a-z0-9_]{2,30}$ + +# Naming style matching correct variable names. +variable-naming-style=snake_case -# Regular expression matching correct argument names. Overrides argument- -# naming-style -#argument-rgx= +# Regular expression matching correct variable names +variable-rgx=[a-z_][a-z0-9_]{2,30}$ -# Naming style matching correct attribute names +# Naming style matching correct constant names. +const-naming-style=UPPER_CASE + +# Regular expression matching correct constant names +const-rgx=(([A-Z_][A-Z0-9_]*)|(__.*__))$ + +# Naming style matching correct attribute names. attr-naming-style=snake_case -# Regular expression matching correct attribute names. Overrides attr-naming- -# style -#attr-rgx= +# Regular expression matching correct attribute names +attr-rgx=[a-z_][a-z0-9_]{2,}$ -# Bad variable names which should always be refused, separated by a comma -bad-names=foo, - bar, - baz, - toto, - tutu, - tata - -# Naming style matching correct class attribute names +# Naming style matching correct argument names. +argument-naming-style=snake_case + +# Regular expression matching correct argument names +argument-rgx=[a-z_][a-z0-9_]{2,30}$ + +# Naming style matching correct class attribute names. class-attribute-naming-style=any -# Regular expression matching correct class attribute names. Overrides class- -# attribute-naming-style -#class-attribute-rgx= +# Regular expression matching correct class attribute names +class-attribute-rgx=([A-Za-z_][A-Za-z0-9_]{2,30}|(__.*__))$ + +# Naming style matching correct class constant names. +class-const-naming-style=UPPER_CASE + +# Regular expression matching correct class constant names. Overrides class- +# const-naming-style. +#class-const-rgx= -# Naming style matching correct class names +# Naming style matching correct inline iteration names. +inlinevar-naming-style=any + +# Regular expression matching correct inline iteration names +inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$ + +# Naming style matching correct class names. class-naming-style=PascalCase -# Regular expression matching correct class names. Overrides class-naming-style -#class-rgx= +# Regular expression matching correct class names +class-rgx=[A-Z_][a-zA-Z0-9]+$ -# Naming style matching correct constant names -const-naming-style=UPPER_CASE -# Regular expression matching correct constant names. Overrides const-naming- -# style -#const-rgx= +# Naming style matching correct module names. +module-naming-style=snake_case + +# Regular expression matching correct module names +module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$ + + +# Naming style matching correct method names. +method-naming-style=snake_case + +# Regular expression matching correct method names +method-rgx=[a-z_][a-z0-9_]{2,}$ + +# Regular expression matching correct type variable names +#typevar-rgx= + +# Regular expression which should only match function or class names that do +# not require a docstring. Use ^(?!__init__$)_ to also check __init__. +no-docstring-rgx=__.*__ # Minimum line length for functions/classes that require docstrings, shorter # ones are exempt. docstring-min-length=-1 -# Naming style matching correct function names -function-naming-style=snake_case +# List of decorators that define properties, such as abc.abstractproperty. +property-classes=abc.abstractproperty -# Regular expression matching correct function names. Overrides function- -# naming-style -#function-rgx= -# Good variable names which should always be accepted, separated by a comma -good-names=i, - j, - k, - ex, - Run, - _ +[TYPECHECK] -# Include a hint for the correct naming format with invalid-name -include-naming-hint=no +# Regex pattern to define which classes are considered mixins if ignore-mixin- +# members is set to 'yes' +mixin-class-rgx=.*MixIn -# Naming style matching correct inline iteration names -inlinevar-naming-style=any +# List of module names for which member attributes should not be checked +# (useful for modules/projects where namespaces are manipulated during runtime +# and thus existing member attributes cannot be deduced by static analysis). It +# supports qualified module names, as well as Unix pattern matching. +ignored-modules= -# Regular expression matching correct inline iteration names. Overrides -# inlinevar-naming-style -#inlinevar-rgx= +# List of class names for which member attributes should not be checked (useful +# for classes with dynamically set attributes). This supports the use of +# qualified names. +ignored-classes=SQLObject, optparse.Values, thread._local, _thread._local -# Naming style matching correct method names -method-naming-style=snake_case +# List of members which are set dynamically and missed by pylint inference +# system, and so shouldn't trigger E1101 when accessed. Python regular +# expressions are accepted. +generated-members=REQUEST,acl_users,aq_parent,argparse.Namespace -# Regular expression matching correct method names. Overrides method-naming- -# style -#method-rgx= +# List of decorators that create context managers from functions, such as +# contextlib.contextmanager. +contextmanager-decorators=contextlib.contextmanager -# Naming style matching correct module names -module-naming-style=snake_case +# Tells whether to warn about missing members when the owner of the attribute +# is inferred to be None. +ignore-none=yes -# Regular expression matching correct module names. Overrides module-naming- -# style -#module-rgx= +# This flag controls whether pylint should warn about no-member and similar +# checks whenever an opaque object is returned when inferring. The inference +# can return multiple potential results while evaluating a Python object, but +# some branches might not be evaluated, which results in partial inference. In +# that case, it might be useful to still emit no-member and other checks for +# the rest of the inferred objects. +ignore-on-opaque-inference=yes -# Colon-delimited sets of names that determine each other's naming style when -# the name regexes allow several styles. -name-group= +# Show a hint with possible names when a member name was not found. The aspect +# of finding the hint is based on edit distance. +missing-member-hint=yes -# Regular expression which should only match function or class names that do -# not require a docstring. -no-docstring-rgx=^_ +# The minimum edit distance a name should have in order to be considered a +# similar match for a missing member name. +missing-member-hint-distance=1 -# List of decorators that produce properties, such as abc.abstractproperty. Add -# to this list to register other decorators that produce valid properties. -property-classes=abc.abstractproperty +# The total number of similar names that should be taken in consideration when +# showing a hint for a missing member. +missing-member-max-choices=1 -# Naming style matching correct variable names -variable-naming-style=snake_case +[SPELLING] -# Regular expression matching correct variable names. Overrides variable- -# naming-style -#variable-rgx= +# Spelling dictionary name. Available dictionaries: none. To make it working +# install python-enchant package. +spelling-dict= +# List of comma separated words that should not be checked. +spelling-ignore-words= -[DESIGN] +# List of comma separated words that should be considered directives if they +# appear and the beginning of a comment and should not be checked. +spelling-ignore-comment-directives=fmt: on,fmt: off,noqa:,noqa,nosec,isort:skip,mypy:,pragma:,# noinspection -# Maximum number of arguments for function / method -max-args=5 +# A path to a file that contains private dictionary; one word per line. +spelling-private-dict-file=.pyenchant_pylint_custom_dict.txt -# Maximum number of attributes for a class (see R0902). -max-attributes=7 +# Tells whether to store unknown words to indicated private dictionary in +# --spelling-private-dict-file option instead of raising a message. +spelling-store-unknown-words=no -# Maximum number of boolean expressions in a if statement -max-bool-expr=5 +# Limits count of emitted suggestions for spelling mistakes. +max-spelling-suggestions=2 -# Maximum number of branch for function / method body -max-branches=12 -# Maximum number of locals for function / method body -max-locals=20 +[DESIGN] -# Maximum number of parents for a class (see R0901). -max-parents=7 +# Maximum number of arguments for function / method +max-args = 9 -# Maximum number of public methods for a class (see R0904). -max-public-methods=20 +# Maximum number of locals for function / method body +max-locals = 19 # Maximum number of return / yield for function / method body -max-returns=6 +max-returns=11 + +# Maximum number of branch for function / method body +max-branches = 20 # Maximum number of statements in function / method body -max-statements=50 +max-statements = 50 -# Minimum number of public methods for a class (see R0903). -min-public-methods=2 +# Maximum number of attributes for a class (see R0902). +max-attributes=11 +# Maximum number of statements in a try-block +max-try-statements = 7 [CLASSES] # List of method names used to declare (i.e. assign) instance attributes. -defining-attr-methods=__init__, - __new__, - setUp - -# List of member names, which should be excluded from the protected access -# warning. -exclude-protected=_asdict, - _fields, - _replace, - _source, - _make +defining-attr-methods=__init__,__new__,setUp,__post_init__ # List of valid names for the first argument in a class method. valid-classmethod-first-arg=cls @@ -507,31 +443,41 @@ valid-classmethod-first-arg=cls # List of valid names for the first argument in a metaclass class method. valid-metaclass-classmethod-first-arg=mcs +# List of member names, which should be excluded from the protected access +# warning. +exclude-protected=_asdict,_fields,_replace,_source,_make + +# Warn about protected attribute access inside special methods +check-protected-access-in-special-methods=no [IMPORTS] +# List of modules that can be imported at any level, not just the top level +# one. +allow-any-import-level= + # Allow wildcard imports from modules that define __all__. allow-wildcard-with-all=no +# Allow explicit reexports by alias from a package __init__. +allow-reexport-from-package=no + # Analyse import fallback blocks. This can be used to support both Python 2 and # 3 compatible code, which means that the block might have code that exists # only in one or another interpreter, leading to false positives when analysed. analyse-fallback-blocks=no # Deprecated modules which should not be used, separated by a comma -deprecated-modules=regsub, - TERMIOS, - Bastion, - rexec - -# Create a graph of external dependencies in the given file (report RP0402 must -# not be disabled) -ext-import-graph= +deprecated-modules=regsub,TERMIOS,Bastion,rexec # Create a graph of every (i.e. internal and external) dependencies in the # given file (report RP0402 must not be disabled) import-graph= +# Create a graph of external dependencies in the given file (report RP0402 must +# not be disabled) +ext-import-graph= + # Create a graph of internal dependencies in the given file (report RP0402 must # not be disabled) int-import-graph= @@ -543,9 +489,60 @@ known-standard-library= # Force import order to recognize a module as part of a third party library. known-third-party=enchant +# Couples of modules and preferred modules, separated by a comma. +preferred-modules= + [EXCEPTIONS] # Exceptions that will emit a warning when being caught. Defaults to # "Exception" -overgeneral-exceptions=Exception +overgeneral-exceptions=builtins.Exception + + +[TYPING] + +# Set to ``no`` if the app / library does **NOT** need to support runtime +# introspection of type annotations. If you use type annotations +# **exclusively** for type checking of an application, you're probably fine. +# For libraries, evaluate if some users what to access the type hints at +# runtime first, e.g., through ``typing.get_type_hints``. Applies to Python +# versions 3.7 - 3.9 +runtime-typing = no + + +[DEPRECATED_BUILTINS] + +# List of builtins function names that should not be used, separated by a comma +bad-functions=map,input + + +[REFACTORING] + +# Maximum number of nested blocks for function / method body +max-nested-blocks=5 + +# Complete name of functions that never returns. When checking for +# inconsistent-return-statements if a never returning function is called then +# it will be considered as an explicit return statement and no message will be +# printed. +never-returning-functions=sys.exit,argparse.parse_error + + +[STRING] + +# This flag controls whether inconsistent-quotes generates a warning when the +# character used as a quote delimiter is used inconsistently within a module. +check-quote-consistency=no + +# This flag controls whether the implicit-str-concat should generate a warning +# on implicit string concatenation in sequences defined over several lines. +check-str-concat-over-line-jumps=no + + +[CODE_STYLE] + +# Max line length for which to sill emit suggestions. Used to prevent optional +# suggestions which would get split by a code formatter (e.g., black). Will +# default to the setting for ``max-line-length``. +#max-line-length-suggestions= \ No newline at end of file diff --git a/README.md b/README.md index 11a75110..fdcd72cf 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,13 @@ analytics-python ============== +======= +[![Run Python Tests](https://github.com/North-Two-Five/analytics-python/actions/workflows/main.yml/badge.svg)](https://github.com/North-Two-Five/analytics-python/actions/workflows/main.yml) +[![.github/workflows/tests.yml](https://github.com/North-Two-Five/analytics-python/actions/workflows/tests.yml/badge.svg)](https://github.com/North-Two-Five/analytics-python/actions/workflows/tests.yml) +======= + + + analytics-python is a python client for [Segment](https://segment.com) ### ⚠️ Maintenance ⚠️ diff --git a/requirements.txt b/requirements.txt index 512f8a54..cf0cbbee 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,76 +1,8 @@ -aiohttp==3.7.4.post0 -appdirs==1.4.4 -astroid==1.6.6 -async-timeout==3.0.1 -attrs==23.1.0 backoff==2.2.1 -bleach==6.0.0 -botocore==1.29.40 -Cerberus==1.3.5 -certifi==2023.7.22 -chardet==4.0.0 -charset-normalizer==3.2.0 -colorama==0.4.4 -dephell==0.8.3 -dephell-archive==0.1.7 -dephell-argparse==0.1.3 -dephell-changelogs==0.0.1 -dephell-discover==0.2.10 -dephell-licenses==0.1.7 -dephell-links==0.1.5 -dephell-markers==1.0.3 -dephell-pythons==0.1.15 -dephell-setuptools==0.2.5 -dephell-shells==0.1.5 -dephell-specifier==0.2.2 -dephell-venvs==0.1.18 -dephell-versioning==0.1.2 -docutils==0.20.1 -entrypoints==0.3 +cryptography==41.0.3 flake8==3.7.9 -git-remote-codecommit==1.16 -idna==3.4 -importlib-metadata==4.11.2 -isort==5.9.3 -Jinja2==3.1.3 -jmespath==1.0.1 -keyring==23.5.0 -lazy-object-proxy==1.9.0 -m2r==0.3.1 -MarkupSafe==2.1.3 -mccabe==0.6.1 -mistune==0.8.4 mock==2.0.0 -multidict==5.1.0 -packaging==21.0 -pbr==5.11.1 -pexpect==4.8.0 -pkginfo==1.9.6 -protobuf==4.24.2 -ptyprocess==0.7.0 -pycodestyle==2.5.0 -pyflakes==2.1.1 -Pygments==2.16.1 PyJWT==2.8.0 -pylint==1.9.3 -pyparsing==3.1.1 +pylint==2.8.0 python-dateutil==2.8.2 -readme-renderer==32.0 requests==2.31.0 -requests-toolbelt==1.0.0 -rfc3986==2.0.0 -ruamel.yaml==0.17.32 -ruamel.yaml.clib==0.2.7 -shellingham==1.4.0 -six==1.15.0 -termcolor==1.1.0 -tomlkit==0.7.2 -tqdm==4.66.1 -twine==3.8.0 -typing-extensions==3.10.0.2 -urllib3==1.26.6 -webencodings==0.5.1 -wrapt==1.12.1 -yarl==1.9.2 -yaspin==2.1.0 -zipp==3.7.0 diff --git a/segment/analytics/test/__init__.py b/segment/analytics/test/__init__.py index 98ad6aa3..e69de29b 100644 --- a/segment/analytics/test/__init__.py +++ b/segment/analytics/test/__init__.py @@ -1,87 +0,0 @@ -import unittest -import pkgutil -import logging -import sys -import segment.analytics as analytics -from segment.analytics.client import Client - - -def all_names(): - for _, modname, _ in pkgutil.iter_modules(__path__): - yield 'segment.analytics.test.' + modname - - -def all(): - logging.basicConfig(stream=sys.stderr) - return unittest.defaultTestLoader.loadTestsFromNames(all_names()) - - -class TestInit(unittest.TestCase): - def test_writeKey(self): - self.assertIsNone(analytics.default_client) - analytics.flush() - self.assertEqual(analytics.default_client.write_key, 'test-init') - - def test_debug(self): - self.assertIsNone(analytics.default_client) - analytics.debug = True - analytics.flush() - self.assertTrue(analytics.default_client.debug) - analytics.default_client = None - analytics.debug = False - analytics.flush() - self.assertFalse(analytics.default_client.debug) - analytics.default_client.log.setLevel(0) # reset log level after debug enable - - def test_gzip(self): - self.assertIsNone(analytics.default_client) - analytics.gzip = True - analytics.flush() - self.assertTrue(analytics.default_client.gzip) - analytics.default_client = None - analytics.gzip = False - analytics.flush() - self.assertFalse(analytics.default_client.gzip) - - def test_host(self): - self.assertIsNone(analytics.default_client) - analytics.host = 'http://test-host' - analytics.flush() - self.assertEqual(analytics.default_client.host, 'http://test-host') - analytics.host = None - analytics.default_client = None - - def test_max_queue_size(self): - self.assertIsNone(analytics.default_client) - analytics.max_queue_size = 1337 - analytics.flush() - self.assertEqual(analytics.default_client.queue.maxsize, 1337) - - def test_max_retries(self): - self.assertIsNone(analytics.default_client) - client = Client('testsecret', max_retries=42) - for consumer in client.consumers: - self.assertEqual(consumer.retries, 42) - - def test_sync_mode(self): - self.assertIsNone(analytics.default_client) - analytics.sync_mode = True - analytics.flush() - self.assertTrue(analytics.default_client.sync_mode) - analytics.default_client = None - analytics.sync_mode = False - analytics.flush() - self.assertFalse(analytics.default_client.sync_mode) - - def test_timeout(self): - self.assertIsNone(analytics.default_client) - analytics.timeout = 1.234 - analytics.flush() - self.assertEqual(analytics.default_client.timeout, 1.234) - - def setUp(self): - analytics.write_key = 'test-init' - analytics.default_client = None - -if __name__ == '__main__': - unittest.main() \ No newline at end of file diff --git a/segment/analytics/test/client.py b/segment/analytics/test/test_client.py similarity index 100% rename from segment/analytics/test/client.py rename to segment/analytics/test/test_client.py diff --git a/segment/analytics/test/consumer.py b/segment/analytics/test/test_consumer.py similarity index 100% rename from segment/analytics/test/consumer.py rename to segment/analytics/test/test_consumer.py diff --git a/segment/analytics/test/test_init.py b/segment/analytics/test/test_init.py new file mode 100644 index 00000000..98ad6aa3 --- /dev/null +++ b/segment/analytics/test/test_init.py @@ -0,0 +1,87 @@ +import unittest +import pkgutil +import logging +import sys +import segment.analytics as analytics +from segment.analytics.client import Client + + +def all_names(): + for _, modname, _ in pkgutil.iter_modules(__path__): + yield 'segment.analytics.test.' + modname + + +def all(): + logging.basicConfig(stream=sys.stderr) + return unittest.defaultTestLoader.loadTestsFromNames(all_names()) + + +class TestInit(unittest.TestCase): + def test_writeKey(self): + self.assertIsNone(analytics.default_client) + analytics.flush() + self.assertEqual(analytics.default_client.write_key, 'test-init') + + def test_debug(self): + self.assertIsNone(analytics.default_client) + analytics.debug = True + analytics.flush() + self.assertTrue(analytics.default_client.debug) + analytics.default_client = None + analytics.debug = False + analytics.flush() + self.assertFalse(analytics.default_client.debug) + analytics.default_client.log.setLevel(0) # reset log level after debug enable + + def test_gzip(self): + self.assertIsNone(analytics.default_client) + analytics.gzip = True + analytics.flush() + self.assertTrue(analytics.default_client.gzip) + analytics.default_client = None + analytics.gzip = False + analytics.flush() + self.assertFalse(analytics.default_client.gzip) + + def test_host(self): + self.assertIsNone(analytics.default_client) + analytics.host = 'http://test-host' + analytics.flush() + self.assertEqual(analytics.default_client.host, 'http://test-host') + analytics.host = None + analytics.default_client = None + + def test_max_queue_size(self): + self.assertIsNone(analytics.default_client) + analytics.max_queue_size = 1337 + analytics.flush() + self.assertEqual(analytics.default_client.queue.maxsize, 1337) + + def test_max_retries(self): + self.assertIsNone(analytics.default_client) + client = Client('testsecret', max_retries=42) + for consumer in client.consumers: + self.assertEqual(consumer.retries, 42) + + def test_sync_mode(self): + self.assertIsNone(analytics.default_client) + analytics.sync_mode = True + analytics.flush() + self.assertTrue(analytics.default_client.sync_mode) + analytics.default_client = None + analytics.sync_mode = False + analytics.flush() + self.assertFalse(analytics.default_client.sync_mode) + + def test_timeout(self): + self.assertIsNone(analytics.default_client) + analytics.timeout = 1.234 + analytics.flush() + self.assertEqual(analytics.default_client.timeout, 1.234) + + def setUp(self): + analytics.write_key = 'test-init' + analytics.default_client = None + +if __name__ == '__main__': + unittest.main() \ No newline at end of file diff --git a/segment/analytics/test/module.py b/segment/analytics/test/test_module.py similarity index 100% rename from segment/analytics/test/module.py rename to segment/analytics/test/test_module.py diff --git a/segment/analytics/test/oauth.py b/segment/analytics/test/test_oauth.py similarity index 100% rename from segment/analytics/test/oauth.py rename to segment/analytics/test/test_oauth.py diff --git a/segment/analytics/test/request.py b/segment/analytics/test/test_request.py similarity index 100% rename from segment/analytics/test/request.py rename to segment/analytics/test/test_request.py diff --git a/segment/analytics/test/utils.py b/segment/analytics/test/test_utils.py similarity index 100% rename from segment/analytics/test/utils.py rename to segment/analytics/test/test_utils.py