chatmcp-cli 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- aider/__init__.py +20 -0
- aider/__main__.py +4 -0
- aider/_version.py +21 -0
- aider/analytics.py +250 -0
- aider/args.py +926 -0
- aider/args_formatter.py +228 -0
- aider/coders/__init__.py +34 -0
- aider/coders/architect_coder.py +48 -0
- aider/coders/architect_prompts.py +40 -0
- aider/coders/ask_coder.py +9 -0
- aider/coders/ask_prompts.py +35 -0
- aider/coders/base_coder.py +2483 -0
- aider/coders/base_prompts.py +60 -0
- aider/coders/chat_chunks.py +64 -0
- aider/coders/context_coder.py +53 -0
- aider/coders/context_prompts.py +75 -0
- aider/coders/editblock_coder.py +657 -0
- aider/coders/editblock_fenced_coder.py +10 -0
- aider/coders/editblock_fenced_prompts.py +143 -0
- aider/coders/editblock_func_coder.py +141 -0
- aider/coders/editblock_func_prompts.py +27 -0
- aider/coders/editblock_prompts.py +174 -0
- aider/coders/editor_diff_fenced_coder.py +9 -0
- aider/coders/editor_diff_fenced_prompts.py +11 -0
- aider/coders/editor_editblock_coder.py +8 -0
- aider/coders/editor_editblock_prompts.py +18 -0
- aider/coders/editor_whole_coder.py +8 -0
- aider/coders/editor_whole_prompts.py +10 -0
- aider/coders/help_coder.py +16 -0
- aider/coders/help_prompts.py +46 -0
- aider/coders/patch_coder.py +706 -0
- aider/coders/patch_prompts.py +161 -0
- aider/coders/search_replace.py +757 -0
- aider/coders/shell.py +37 -0
- aider/coders/single_wholefile_func_coder.py +102 -0
- aider/coders/single_wholefile_func_prompts.py +27 -0
- aider/coders/udiff_coder.py +429 -0
- aider/coders/udiff_prompts.py +115 -0
- aider/coders/udiff_simple.py +14 -0
- aider/coders/udiff_simple_prompts.py +25 -0
- aider/coders/wholefile_coder.py +144 -0
- aider/coders/wholefile_func_coder.py +134 -0
- aider/coders/wholefile_func_prompts.py +27 -0
- aider/coders/wholefile_prompts.py +67 -0
- aider/commands.py +1665 -0
- aider/copypaste.py +72 -0
- aider/deprecated.py +126 -0
- aider/diffs.py +128 -0
- aider/dump.py +29 -0
- aider/editor.py +147 -0
- aider/exceptions.py +107 -0
- aider/format_settings.py +26 -0
- aider/gui.py +545 -0
- aider/help.py +163 -0
- aider/help_pats.py +19 -0
- aider/history.py +143 -0
- aider/io.py +1175 -0
- aider/linter.py +304 -0
- aider/llm.py +47 -0
- aider/main.py +1267 -0
- aider/mdstream.py +243 -0
- aider/models.py +1286 -0
- aider/onboarding.py +428 -0
- aider/openrouter.py +128 -0
- aider/prompts.py +64 -0
- aider/queries/tree-sitter-language-pack/README.md +7 -0
- aider/queries/tree-sitter-language-pack/arduino-tags.scm +5 -0
- aider/queries/tree-sitter-language-pack/c-tags.scm +9 -0
- aider/queries/tree-sitter-language-pack/chatito-tags.scm +16 -0
- aider/queries/tree-sitter-language-pack/commonlisp-tags.scm +122 -0
- aider/queries/tree-sitter-language-pack/cpp-tags.scm +15 -0
- aider/queries/tree-sitter-language-pack/csharp-tags.scm +26 -0
- aider/queries/tree-sitter-language-pack/d-tags.scm +26 -0
- aider/queries/tree-sitter-language-pack/dart-tags.scm +92 -0
- aider/queries/tree-sitter-language-pack/elisp-tags.scm +5 -0
- aider/queries/tree-sitter-language-pack/elixir-tags.scm +54 -0
- aider/queries/tree-sitter-language-pack/elm-tags.scm +19 -0
- aider/queries/tree-sitter-language-pack/gleam-tags.scm +41 -0
- aider/queries/tree-sitter-language-pack/go-tags.scm +42 -0
- aider/queries/tree-sitter-language-pack/java-tags.scm +20 -0
- aider/queries/tree-sitter-language-pack/javascript-tags.scm +88 -0
- aider/queries/tree-sitter-language-pack/lua-tags.scm +34 -0
- aider/queries/tree-sitter-language-pack/ocaml-tags.scm +115 -0
- aider/queries/tree-sitter-language-pack/ocaml_interface-tags.scm +98 -0
- aider/queries/tree-sitter-language-pack/pony-tags.scm +39 -0
- aider/queries/tree-sitter-language-pack/properties-tags.scm +5 -0
- aider/queries/tree-sitter-language-pack/python-tags.scm +14 -0
- aider/queries/tree-sitter-language-pack/r-tags.scm +21 -0
- aider/queries/tree-sitter-language-pack/racket-tags.scm +12 -0
- aider/queries/tree-sitter-language-pack/ruby-tags.scm +64 -0
- aider/queries/tree-sitter-language-pack/rust-tags.scm +60 -0
- aider/queries/tree-sitter-language-pack/solidity-tags.scm +43 -0
- aider/queries/tree-sitter-language-pack/swift-tags.scm +51 -0
- aider/queries/tree-sitter-language-pack/udev-tags.scm +20 -0
- aider/queries/tree-sitter-languages/README.md +23 -0
- aider/queries/tree-sitter-languages/c-tags.scm +9 -0
- aider/queries/tree-sitter-languages/c_sharp-tags.scm +46 -0
- aider/queries/tree-sitter-languages/cpp-tags.scm +15 -0
- aider/queries/tree-sitter-languages/dart-tags.scm +91 -0
- aider/queries/tree-sitter-languages/elisp-tags.scm +8 -0
- aider/queries/tree-sitter-languages/elixir-tags.scm +54 -0
- aider/queries/tree-sitter-languages/elm-tags.scm +19 -0
- aider/queries/tree-sitter-languages/go-tags.scm +30 -0
- aider/queries/tree-sitter-languages/hcl-tags.scm +77 -0
- aider/queries/tree-sitter-languages/java-tags.scm +20 -0
- aider/queries/tree-sitter-languages/javascript-tags.scm +88 -0
- aider/queries/tree-sitter-languages/kotlin-tags.scm +27 -0
- aider/queries/tree-sitter-languages/ocaml-tags.scm +115 -0
- aider/queries/tree-sitter-languages/ocaml_interface-tags.scm +98 -0
- aider/queries/tree-sitter-languages/php-tags.scm +26 -0
- aider/queries/tree-sitter-languages/python-tags.scm +12 -0
- aider/queries/tree-sitter-languages/ql-tags.scm +26 -0
- aider/queries/tree-sitter-languages/ruby-tags.scm +64 -0
- aider/queries/tree-sitter-languages/rust-tags.scm +60 -0
- aider/queries/tree-sitter-languages/scala-tags.scm +65 -0
- aider/queries/tree-sitter-languages/typescript-tags.scm +41 -0
- aider/reasoning_tags.py +82 -0
- aider/repo.py +623 -0
- aider/repomap.py +847 -0
- aider/report.py +200 -0
- aider/resources/__init__.py +3 -0
- aider/resources/model-metadata.json +468 -0
- aider/resources/model-settings.yml +1767 -0
- aider/run_cmd.py +132 -0
- aider/scrape.py +284 -0
- aider/sendchat.py +61 -0
- aider/special.py +203 -0
- aider/urls.py +17 -0
- aider/utils.py +338 -0
- aider/versioncheck.py +113 -0
- aider/voice.py +187 -0
- aider/waiting.py +221 -0
- aider/watch.py +318 -0
- aider/watch_prompts.py +12 -0
- aider/website/Gemfile +8 -0
- aider/website/_includes/blame.md +162 -0
- aider/website/_includes/get-started.md +22 -0
- aider/website/_includes/help-tip.md +5 -0
- aider/website/_includes/help.md +24 -0
- aider/website/_includes/install.md +5 -0
- aider/website/_includes/keys.md +4 -0
- aider/website/_includes/model-warnings.md +67 -0
- aider/website/_includes/multi-line.md +22 -0
- aider/website/_includes/python-m-aider.md +5 -0
- aider/website/_includes/recording.css +228 -0
- aider/website/_includes/recording.md +34 -0
- aider/website/_includes/replit-pipx.md +9 -0
- aider/website/_includes/works-best.md +1 -0
- aider/website/_sass/custom/custom.scss +103 -0
- aider/website/docs/config/adv-model-settings.md +1881 -0
- aider/website/docs/config/aider_conf.md +527 -0
- aider/website/docs/config/api-keys.md +90 -0
- aider/website/docs/config/dotenv.md +478 -0
- aider/website/docs/config/editor.md +127 -0
- aider/website/docs/config/model-aliases.md +103 -0
- aider/website/docs/config/options.md +843 -0
- aider/website/docs/config/reasoning.md +209 -0
- aider/website/docs/config.md +44 -0
- aider/website/docs/faq.md +378 -0
- aider/website/docs/git.md +76 -0
- aider/website/docs/index.md +47 -0
- aider/website/docs/install/codespaces.md +39 -0
- aider/website/docs/install/docker.md +57 -0
- aider/website/docs/install/optional.md +100 -0
- aider/website/docs/install/replit.md +8 -0
- aider/website/docs/install.md +115 -0
- aider/website/docs/languages.md +264 -0
- aider/website/docs/legal/contributor-agreement.md +111 -0
- aider/website/docs/legal/privacy.md +104 -0
- aider/website/docs/llms/anthropic.md +77 -0
- aider/website/docs/llms/azure.md +48 -0
- aider/website/docs/llms/bedrock.md +132 -0
- aider/website/docs/llms/cohere.md +34 -0
- aider/website/docs/llms/deepseek.md +32 -0
- aider/website/docs/llms/gemini.md +49 -0
- aider/website/docs/llms/github.md +105 -0
- aider/website/docs/llms/groq.md +36 -0
- aider/website/docs/llms/lm-studio.md +39 -0
- aider/website/docs/llms/ollama.md +75 -0
- aider/website/docs/llms/openai-compat.md +39 -0
- aider/website/docs/llms/openai.md +58 -0
- aider/website/docs/llms/openrouter.md +78 -0
- aider/website/docs/llms/other.md +103 -0
- aider/website/docs/llms/vertex.md +50 -0
- aider/website/docs/llms/warnings.md +10 -0
- aider/website/docs/llms/xai.md +53 -0
- aider/website/docs/llms.md +54 -0
- aider/website/docs/more/analytics.md +122 -0
- aider/website/docs/more/edit-formats.md +116 -0
- aider/website/docs/more/infinite-output.md +137 -0
- aider/website/docs/more-info.md +8 -0
- aider/website/docs/recordings/auto-accept-architect.md +31 -0
- aider/website/docs/recordings/dont-drop-original-read-files.md +35 -0
- aider/website/docs/recordings/index.md +21 -0
- aider/website/docs/recordings/model-accepts-settings.md +69 -0
- aider/website/docs/recordings/tree-sitter-language-pack.md +80 -0
- aider/website/docs/repomap.md +112 -0
- aider/website/docs/scripting.md +100 -0
- aider/website/docs/troubleshooting/aider-not-found.md +24 -0
- aider/website/docs/troubleshooting/edit-errors.md +76 -0
- aider/website/docs/troubleshooting/imports.md +62 -0
- aider/website/docs/troubleshooting/models-and-keys.md +54 -0
- aider/website/docs/troubleshooting/support.md +79 -0
- aider/website/docs/troubleshooting/token-limits.md +96 -0
- aider/website/docs/troubleshooting/warnings.md +12 -0
- aider/website/docs/troubleshooting.md +11 -0
- aider/website/docs/usage/browser.md +57 -0
- aider/website/docs/usage/caching.md +49 -0
- aider/website/docs/usage/commands.md +132 -0
- aider/website/docs/usage/conventions.md +119 -0
- aider/website/docs/usage/copypaste.md +121 -0
- aider/website/docs/usage/images-urls.md +48 -0
- aider/website/docs/usage/lint-test.md +118 -0
- aider/website/docs/usage/modes.md +211 -0
- aider/website/docs/usage/not-code.md +179 -0
- aider/website/docs/usage/notifications.md +87 -0
- aider/website/docs/usage/tips.md +79 -0
- aider/website/docs/usage/tutorials.md +30 -0
- aider/website/docs/usage/voice.md +121 -0
- aider/website/docs/usage/watch.md +294 -0
- aider/website/docs/usage.md +92 -0
- aider/website/share/index.md +101 -0
- chatmcp_cli-0.1.0.dist-info/METADATA +502 -0
- chatmcp_cli-0.1.0.dist-info/RECORD +228 -0
- chatmcp_cli-0.1.0.dist-info/WHEEL +5 -0
- chatmcp_cli-0.1.0.dist-info/entry_points.txt +3 -0
- chatmcp_cli-0.1.0.dist-info/licenses/LICENSE.txt +202 -0
- chatmcp_cli-0.1.0.dist-info/top_level.txt +1 -0
aider/__init__.py
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
from packaging import version
|
2
|
+
|
3
|
+
__version__ = "0.84.1.dev"
|
4
|
+
safe_version = __version__
|
5
|
+
|
6
|
+
try:
|
7
|
+
from aider._version import __version__
|
8
|
+
except Exception:
|
9
|
+
__version__ = safe_version + "+import"
|
10
|
+
|
11
|
+
if type(__version__) is not str:
|
12
|
+
__version__ = safe_version + "+type"
|
13
|
+
else:
|
14
|
+
try:
|
15
|
+
if version.parse(__version__) < version.parse(safe_version):
|
16
|
+
__version__ = safe_version + "+less"
|
17
|
+
except Exception:
|
18
|
+
__version__ = safe_version + "+parse"
|
19
|
+
|
20
|
+
__all__ = [__version__]
|
aider/__main__.py
ADDED
aider/_version.py
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
# file generated by setuptools-scm
|
2
|
+
# don't change, don't track in version control
|
3
|
+
|
4
|
+
__all__ = ["__version__", "__version_tuple__", "version", "version_tuple"]
|
5
|
+
|
6
|
+
TYPE_CHECKING = False
|
7
|
+
if TYPE_CHECKING:
|
8
|
+
from typing import Tuple
|
9
|
+
from typing import Union
|
10
|
+
|
11
|
+
VERSION_TUPLE = Tuple[Union[int, str], ...]
|
12
|
+
else:
|
13
|
+
VERSION_TUPLE = object
|
14
|
+
|
15
|
+
version: str
|
16
|
+
__version__: str
|
17
|
+
__version_tuple__: VERSION_TUPLE
|
18
|
+
version_tuple: VERSION_TUPLE
|
19
|
+
|
20
|
+
__version__ = version = '0.1.0'
|
21
|
+
__version_tuple__ = version_tuple = (0, 1, 0)
|
aider/analytics.py
ADDED
@@ -0,0 +1,250 @@
|
|
1
|
+
import json
|
2
|
+
import platform
|
3
|
+
import sys
|
4
|
+
import time
|
5
|
+
import uuid
|
6
|
+
from pathlib import Path
|
7
|
+
|
8
|
+
from mixpanel import MixpanelException
|
9
|
+
from posthog import Posthog
|
10
|
+
|
11
|
+
from aider import __version__
|
12
|
+
from aider.dump import dump # noqa: F401
|
13
|
+
from aider.models import model_info_manager
|
14
|
+
|
15
|
+
PERCENT = 10
|
16
|
+
|
17
|
+
|
18
|
+
def compute_hex_threshold(percent):
|
19
|
+
"""Convert percentage to 6-digit hex threshold.
|
20
|
+
|
21
|
+
Args:
|
22
|
+
percent: Percentage threshold (0-100)
|
23
|
+
|
24
|
+
Returns:
|
25
|
+
str: 6-digit hex threshold
|
26
|
+
"""
|
27
|
+
return format(int(0xFFFFFF * percent / 100), "06x")
|
28
|
+
|
29
|
+
|
30
|
+
def is_uuid_in_percentage(uuid_str, percent):
|
31
|
+
"""Check if a UUID string falls within the first X percent of the UUID space.
|
32
|
+
|
33
|
+
Args:
|
34
|
+
uuid_str: UUID string to test
|
35
|
+
percent: Percentage threshold (0-100)
|
36
|
+
|
37
|
+
Returns:
|
38
|
+
bool: True if UUID falls within the first X percent
|
39
|
+
"""
|
40
|
+
if not (0 <= percent <= 100):
|
41
|
+
raise ValueError("Percentage must be between 0 and 100")
|
42
|
+
|
43
|
+
if not uuid_str:
|
44
|
+
return False
|
45
|
+
|
46
|
+
# Convert percentage to hex threshold (1% = "04...", 10% = "1a...", etc)
|
47
|
+
# Using first 6 hex digits
|
48
|
+
if percent == 0:
|
49
|
+
return False
|
50
|
+
|
51
|
+
threshold = compute_hex_threshold(percent)
|
52
|
+
return uuid_str[:6] <= threshold
|
53
|
+
|
54
|
+
|
55
|
+
mixpanel_project_token = "6da9a43058a5d1b9f3353153921fb04d"
|
56
|
+
posthog_project_api_key = "phc_99T7muzafUMMZX15H8XePbMSreEUzahHbtWjy3l5Qbv"
|
57
|
+
posthog_host = "https://us.i.posthog.com"
|
58
|
+
|
59
|
+
|
60
|
+
class Analytics:
|
61
|
+
# providers
|
62
|
+
mp = None
|
63
|
+
ph = None
|
64
|
+
|
65
|
+
# saved
|
66
|
+
user_id = None
|
67
|
+
permanently_disable = None
|
68
|
+
asked_opt_in = None
|
69
|
+
|
70
|
+
# ephemeral
|
71
|
+
logfile = None
|
72
|
+
|
73
|
+
def __init__(self, logfile=None, permanently_disable=False):
|
74
|
+
self.logfile = logfile
|
75
|
+
self.get_or_create_uuid()
|
76
|
+
|
77
|
+
if self.permanently_disable or permanently_disable or not self.asked_opt_in:
|
78
|
+
self.disable(permanently_disable)
|
79
|
+
|
80
|
+
def enable(self):
|
81
|
+
if not self.user_id:
|
82
|
+
self.disable(False)
|
83
|
+
return
|
84
|
+
|
85
|
+
if self.permanently_disable:
|
86
|
+
self.disable(True)
|
87
|
+
return
|
88
|
+
|
89
|
+
if not self.asked_opt_in:
|
90
|
+
self.disable(False)
|
91
|
+
return
|
92
|
+
|
93
|
+
# self.mp = Mixpanel(mixpanel_project_token)
|
94
|
+
self.ph = Posthog(
|
95
|
+
project_api_key=posthog_project_api_key,
|
96
|
+
host=posthog_host,
|
97
|
+
on_error=self.posthog_error,
|
98
|
+
enable_exception_autocapture=True,
|
99
|
+
super_properties=self.get_system_info(), # Add system info to all events
|
100
|
+
)
|
101
|
+
|
102
|
+
def disable(self, permanently):
|
103
|
+
self.mp = None
|
104
|
+
self.ph = None
|
105
|
+
|
106
|
+
if permanently:
|
107
|
+
self.asked_opt_in = True
|
108
|
+
self.permanently_disable = True
|
109
|
+
self.save_data()
|
110
|
+
|
111
|
+
def need_to_ask(self, args_analytics):
|
112
|
+
if args_analytics is False:
|
113
|
+
return False
|
114
|
+
|
115
|
+
could_ask = not self.asked_opt_in and not self.permanently_disable
|
116
|
+
if not could_ask:
|
117
|
+
return False
|
118
|
+
|
119
|
+
if args_analytics is True:
|
120
|
+
return True
|
121
|
+
|
122
|
+
assert args_analytics is None, args_analytics
|
123
|
+
|
124
|
+
if not self.user_id:
|
125
|
+
return False
|
126
|
+
|
127
|
+
return is_uuid_in_percentage(self.user_id, PERCENT)
|
128
|
+
|
129
|
+
def get_data_file_path(self):
|
130
|
+
try:
|
131
|
+
data_file = Path.home() / ".aider" / "analytics.json"
|
132
|
+
data_file.parent.mkdir(parents=True, exist_ok=True)
|
133
|
+
return data_file
|
134
|
+
except OSError:
|
135
|
+
# If we can't create/access the directory, just disable analytics
|
136
|
+
self.disable(permanently=False)
|
137
|
+
return None
|
138
|
+
|
139
|
+
def get_or_create_uuid(self):
|
140
|
+
self.load_data()
|
141
|
+
if self.user_id:
|
142
|
+
return
|
143
|
+
|
144
|
+
self.user_id = str(uuid.uuid4())
|
145
|
+
self.save_data()
|
146
|
+
|
147
|
+
def load_data(self):
|
148
|
+
data_file = self.get_data_file_path()
|
149
|
+
if not data_file:
|
150
|
+
return
|
151
|
+
|
152
|
+
if data_file.exists():
|
153
|
+
try:
|
154
|
+
data = json.loads(data_file.read_text())
|
155
|
+
self.permanently_disable = data.get("permanently_disable")
|
156
|
+
self.user_id = data.get("uuid")
|
157
|
+
self.asked_opt_in = data.get("asked_opt_in", False)
|
158
|
+
except (json.decoder.JSONDecodeError, OSError):
|
159
|
+
self.disable(permanently=False)
|
160
|
+
|
161
|
+
def save_data(self):
|
162
|
+
data_file = self.get_data_file_path()
|
163
|
+
if not data_file:
|
164
|
+
return
|
165
|
+
|
166
|
+
data = dict(
|
167
|
+
uuid=self.user_id,
|
168
|
+
permanently_disable=self.permanently_disable,
|
169
|
+
asked_opt_in=self.asked_opt_in,
|
170
|
+
)
|
171
|
+
|
172
|
+
try:
|
173
|
+
data_file.write_text(json.dumps(data, indent=4))
|
174
|
+
except OSError:
|
175
|
+
# If we can't write the file, just disable analytics
|
176
|
+
self.disable(permanently=False)
|
177
|
+
|
178
|
+
def get_system_info(self):
|
179
|
+
return {
|
180
|
+
"python_version": sys.version.split()[0],
|
181
|
+
"os_platform": platform.system(),
|
182
|
+
"os_release": platform.release(),
|
183
|
+
"machine": platform.machine(),
|
184
|
+
"aider_version": __version__,
|
185
|
+
}
|
186
|
+
|
187
|
+
def _redact_model_name(self, model):
|
188
|
+
if not model:
|
189
|
+
return None
|
190
|
+
|
191
|
+
info = model_info_manager.get_model_from_cached_json_db(model.name)
|
192
|
+
if info:
|
193
|
+
return model.name
|
194
|
+
elif "/" in model.name:
|
195
|
+
return model.name.split("/")[0] + "/REDACTED"
|
196
|
+
return None
|
197
|
+
|
198
|
+
def posthog_error(self):
|
199
|
+
"""disable posthog if we get an error"""
|
200
|
+
print("X" * 100)
|
201
|
+
# https://github.com/PostHog/posthog-python/blob/9e1bb8c58afaa229da24c4fb576c08bb88a75752/posthog/consumer.py#L86
|
202
|
+
# https://github.com/Aider-AI/aider/issues/2532
|
203
|
+
self.ph = None
|
204
|
+
|
205
|
+
def event(self, event_name, main_model=None, **kwargs):
|
206
|
+
if not self.mp and not self.ph and not self.logfile:
|
207
|
+
return
|
208
|
+
|
209
|
+
properties = {}
|
210
|
+
|
211
|
+
if main_model:
|
212
|
+
properties["main_model"] = self._redact_model_name(main_model)
|
213
|
+
properties["weak_model"] = self._redact_model_name(main_model.weak_model)
|
214
|
+
properties["editor_model"] = self._redact_model_name(main_model.editor_model)
|
215
|
+
|
216
|
+
properties.update(kwargs)
|
217
|
+
|
218
|
+
# Handle numeric values
|
219
|
+
for key, value in properties.items():
|
220
|
+
if isinstance(value, (int, float)):
|
221
|
+
properties[key] = value
|
222
|
+
else:
|
223
|
+
properties[key] = str(value)
|
224
|
+
|
225
|
+
if self.mp:
|
226
|
+
try:
|
227
|
+
self.mp.track(self.user_id, event_name, dict(properties))
|
228
|
+
except MixpanelException:
|
229
|
+
self.mp = None # Disable mixpanel on connection errors
|
230
|
+
|
231
|
+
if self.ph:
|
232
|
+
self.ph.capture(self.user_id, event_name, dict(properties))
|
233
|
+
|
234
|
+
if self.logfile:
|
235
|
+
log_entry = {
|
236
|
+
"event": event_name,
|
237
|
+
"properties": properties,
|
238
|
+
"user_id": self.user_id,
|
239
|
+
"time": int(time.time()),
|
240
|
+
}
|
241
|
+
try:
|
242
|
+
with open(self.logfile, "a") as f:
|
243
|
+
json.dump(log_entry, f)
|
244
|
+
f.write("\n")
|
245
|
+
except OSError:
|
246
|
+
pass # Ignore OS errors when writing to logfile
|
247
|
+
|
248
|
+
|
249
|
+
if __name__ == "__main__":
|
250
|
+
dump(compute_hex_threshold(PERCENT))
|