commit python-cloudflare for openSUSE:Factory
Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package python-cloudflare for openSUSE:Factory checked in at 2023-11-30 22:00:37 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-cloudflare (Old) and /work/SRC/openSUSE:Factory/.python-cloudflare.new.25432 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Package is "python-cloudflare" Thu Nov 30 22:00:37 2023 rev:14 rq:1129789 version:2.14.2 Changes: -------- --- /work/SRC/openSUSE:Factory/python-cloudflare/python-cloudflare.changes 2023-10-05 20:06:17.097501612 +0200 +++ /work/SRC/openSUSE:Factory/.python-cloudflare.new.25432/python-cloudflare.changes 2023-11-30 22:01:27.417359734 +0100 @@ -1,0 +2,19 @@ +Wed Nov 29 12:09:24 UTC 2023 - Dirk Müller <dmueller@suse.com> + +- update to 2.14.2: + * added AI info + * account name via -a flag now. should not be needed + * stable diffusion example + * move config info into code + * first pass a new AI API calls + * cleanup of usage, added more flag descriptions + * cleanup of usage and getops values - now consistent + * timeout values now work from config or api call, + added support for image binary results, fixed logging if binary + * handle raw byte output either via --image flag or if return + from api is bytes + * more api endpoints + * added ips and issue114 tests + * add importlib_resources info for older Python versions + +------------------------------------------------------------------- Old: ---- cloudflare-2.12.4.tar.gz New: ---- cloudflare-2.14.2.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-cloudflare.spec ++++++ --- /var/tmp/diff_new_pack.il9ClS/_old 2023-11-30 22:01:27.965379922 +0100 +++ /var/tmp/diff_new_pack.il9ClS/_new 2023-11-30 22:01:27.969380070 +0100 @@ -18,7 +18,7 @@ %{?sle15_python_module_pythons} Name: python-cloudflare -Version: 2.12.4 +Version: 2.14.2 Release: 0 Summary: Python wrapper for the Cloudflare v4 API License: MIT ++++++ cloudflare-2.12.4.tar.gz -> cloudflare-2.14.2.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cloudflare-2.12.4/CloudFlare/__init__.py new/cloudflare-2.14.2/CloudFlare/__init__.py --- old/cloudflare-2.12.4/CloudFlare/__init__.py 2023-09-22 03:45:07.000000000 +0200 +++ new/cloudflare-2.14.2/CloudFlare/__init__.py 2023-11-26 05:05:05.000000000 +0100 @@ -1,6 +1,6 @@ """ Cloudflare v4 API""" -__version__ = '2.12.4' +__version__ = '2.14.2' from .cloudflare import CloudFlare diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cloudflare-2.12.4/CloudFlare/api_v4.py new/cloudflare-2.14.2/CloudFlare/api_v4.py --- old/cloudflare-2.12.4/CloudFlare/api_v4.py 2023-09-19 21:23:01.000000000 +0200 +++ new/cloudflare-2.14.2/CloudFlare/api_v4.py 2023-11-25 19:04:44.000000000 +0100 @@ -390,12 +390,15 @@ self.add('AUTH', 'accounts', 'custom_pages') self.add('VOID', 'accounts', 'dlp') + self.add('AUTH', 'accounts', 'dlp/datasets') + self.add('AUTH', 'accounts', 'dlp/datasets', 'upload') self.add('VOID', 'accounts', 'dlp/patterns') self.add('AUTH', 'accounts', 'dlp/patterns/validate') self.add('AUTH', 'accounts', 'dlp/payload_log') self.add('AUTH', 'accounts', 'dlp/profiles') self.add('AUTH', 'accounts', 'dlp/profiles/custom') self.add('AUTH', 'accounts', 'dlp/profiles/predefined') + self.add('AUTH', 'accounts', 'members') self.add('VOID', 'accounts', 'mnm') self.add('AUTH', 'accounts', 'mnm/config') @@ -447,6 +450,9 @@ self.add('VOID', 'accounts', 'vectorize') self.add('AUTH', 'accounts', 'vectorize/index') self.add('AUTH', 'accounts', 'vectorize/indexes') + self.add('AUTH', 'accounts', 'vectorize/indexes', 'insert') + self.add('AUTH', 'accounts', 'vectorize/indexes', 'query') + self.add('AUTH', 'accounts', 'vectorize/indexes', 'upsert') self.add('AUTH', 'accounts', 'virtual_dns') self.add('VOID', 'accounts', 'virtual_dns', 'dns_analytics') @@ -624,8 +630,12 @@ self.add('VOID', 'accounts', 'access/logs') self.add('AUTH', 'accounts', 'access/logs/access_requests') self.add('AUTH', 'accounts', 'access/seats') + self.add('AUTH', 'accounts', 'access/tags') self.add('AUTH', 'accounts', 'access/users') self.add('AUTH', 'accounts', 'access/users', 'failed_logins') + self.add('AUTH', 'accounts', 'access/users', 'active_sessions') + self.add('AUTH', 'accounts', 'access/users', 'last_seen_identity') + def accounts_diagnostics(self): """ accounts diagnostics """ @@ -647,12 +657,16 @@ def accounts_extras(self): """ extras """ + self.add('VOID', 'accounts', 'ai') + self.add('AUTH', 'accounts', 'ai/run') + self.add('VOID', 'accounts', 'alerting') self.add('VOID', 'accounts', 'alerting/v3') self.add('AUTH', 'accounts', 'alerting/v3/available_alerts') self.add('VOID', 'accounts', 'alerting/v3/destinations') self.add('AUTH', 'accounts', 'alerting/v3/destinations/eligible') self.add('AUTH', 'accounts', 'alerting/v3/destinations/pagerduty') + self.add('AUTH', 'accounts', 'alerting/v3/destinations/pagerduty/connect') self.add('AUTH', 'accounts', 'alerting/v3/destinations/webhooks') self.add('AUTH', 'accounts', 'alerting/v3/history') self.add('AUTH', 'accounts', 'alerting/v3/policies') @@ -682,13 +696,19 @@ self.add('VOID', 'accounts', 'dex') self.add('AUTH', 'accounts', 'dex/colos') + self.add('VOID', 'accounts', 'dex/fleet-status') + self.add('AUTH', 'accounts', 'dex/fleet-status/devices') + self.add('AUTH', 'accounts', 'dex/fleet-status/live') + self.add('AUTH', 'accounts', 'dex/fleet-status/over-time') self.add('AUTH', 'accounts', 'dex/http-tests') + self.add('AUTH', 'accounts', 'dex/http-tests', 'percentiles') self.add('AUTH', 'accounts', 'dex/tests') self.add('AUTH', 'accounts', 'dex/tests/unique-devices') self.add('VOID', 'accounts', 'dex/traceroute-test-results') self.add('AUTH', 'accounts', 'dex/traceroute-test-results', 'network-path') self.add('AUTH', 'accounts', 'dex/traceroute-tests') self.add('AUTH', 'accounts', 'dex/traceroute-tests', 'network-path') + self.add('AUTH', 'accounts', 'dex/traceroute-tests', 'percentiles') self.add('AUTH', 'accounts', 'dns_firewall') self.add('VOID', 'accounts', 'dns_firewall', 'dns_analytics') @@ -697,6 +717,7 @@ self.add('AUTH', 'accounts', 'gateway') self.add('AUTH', 'accounts', 'gateway/app_types') + self.add('AUTH', 'accounts', 'gateway/audit_ssh_settings') self.add('AUTH', 'accounts', 'gateway/categories') self.add('AUTH', 'accounts', 'gateway/configuration') self.add('AUTH', 'accounts', 'gateway/lists') @@ -773,17 +794,30 @@ self.add('VOID', 'accounts', 'hyperdrive') self.add('AUTH', 'accounts', 'hyperdrive/configs') + self.add('AUTH', 'accounts', 'warp_connector') + self.add('AUTH', 'accounts', 'warp_connector', 'token') + + self.add('VOID', 'accounts', 'zerotrust') + self.add('AUTH', 'accounts', 'zerotrust/connectivity_settings') + + self.add('VOID', 'accounts', 'd1') + self.add('AUTH', 'accounts', 'd1/database') + self.add('AUTH', 'accounts', 'd1/database', 'query') def zones_extras(self): """ zones extras """ self.add('VOID', 'zones', 'acm') self.add('AUTH', 'zones', 'acm/total_tls') + self.add('VOID', 'zones', 'cache') - self.add('AUTH', 'zones', 'cache/variants') self.add('AUTH', 'zones', 'cache/cache_reserve') + self.add('AUTH', 'zones', 'cache/cache_reserve_clear') + self.add('AUTH', 'zones', 'cache/origin_post_quantum_encryption') self.add('AUTH', 'zones', 'cache/regional_tiered_cache') self.add('AUTH', 'zones', 'cache/tiered_cache_smart_topology_enable') + self.add('AUTH', 'zones', 'cache/variants') + self.add('AUTH', 'zones', 'managed_headers') self.add('AUTH', 'zones', 'page_shield') self.add('AUTH', 'zones', 'page_shield/policies') @@ -857,8 +891,16 @@ self.add('VOID', 'zones', 'api_gateway') self.add('AUTH', 'zones', 'api_gateway/configuration') self.add('AUTH', 'zones', 'api_gateway/discovery') + self.add('AUTH', 'zones', 'api_gateway/discovery/operations') self.add('AUTH', 'zones', 'api_gateway/operations') + self.add('AUTH', 'zones', 'api_gateway/operations', 'schema_validation') +# self.add('AUTH', 'zones', 'api_gateway/operations/schema_validation') self.add('AUTH', 'zones', 'api_gateway/schemas') + self.add('VOID', 'zones', 'api_gateway/settings') + self.add('AUTH', 'zones', 'api_gateway/settings/schema_validation') + self.add('AUTH', 'zones', 'api_gateway/user_schemas') + self.add('AUTH', 'zones', 'api_gateway/user_schemas', 'operations') + def radar(self): """ radar """ @@ -919,20 +961,38 @@ self.add('AUTH', 'radar/attacks/layer3/timeseries_groups/vector') self.add('AUTH', 'radar/attacks/layer3/timeseries_groups/vertical') self.add('VOID', 'radar/attacks/layer3/top') + self.add('AUTH', 'radar/attacks/layer3/top/attacks') self.add('AUTH', 'radar/attacks/layer3/top/industry') + self.add('VOID', 'radar/attacks/layer3/top/locations') + self.add('AUTH', 'radar/attacks/layer3/top/locations/origin') + self.add('AUTH', 'radar/attacks/layer3/top/locations/target') self.add('AUTH', 'radar/attacks/layer3/top/vertical') self.add('VOID', 'radar/attacks/layer7') self.add('AUTH', 'radar/attacks/layer7/summary') + self.add('AUTH', 'radar/attacks/layer7/summary/http_method') + self.add('AUTH', 'radar/attacks/layer7/summary/http_version') + self.add('AUTH', 'radar/attacks/layer7/summary/ip_version') + self.add('AUTH', 'radar/attacks/layer7/summary/managed_rules') + self.add('AUTH', 'radar/attacks/layer7/summary/mitigation_product') self.add('AUTH', 'radar/attacks/layer7/timeseries') self.add('AUTH', 'radar/attacks/layer7/timeseries_groups') + self.add('AUTH', 'radar/attacks/layer7/timeseries_groups/http_method') + self.add('AUTH', 'radar/attacks/layer7/timeseries_groups/http_version') + self.add('AUTH', 'radar/attacks/layer7/timeseries_groups/industry') + self.add('AUTH', 'radar/attacks/layer7/timeseries_groups/ip_version') + self.add('AUTH', 'radar/attacks/layer7/timeseries_groups/managed_rules') + self.add('AUTH', 'radar/attacks/layer7/timeseries_groups/mitigation_product') + self.add('AUTH', 'radar/attacks/layer7/timeseries_groups/vertical') self.add('VOID', 'radar/attacks/layer7/top') self.add('VOID', 'radar/attacks/layer7/top/ases') self.add('AUTH', 'radar/attacks/layer7/top/ases/origin') self.add('AUTH', 'radar/attacks/layer7/top/attacks') + self.add('AUTH', 'radar/attacks/layer7/top/industry') self.add('VOID', 'radar/attacks/layer7/top/locations') self.add('AUTH', 'radar/attacks/layer7/top/locations/origin') self.add('AUTH', 'radar/attacks/layer7/top/locations/target') + self.add('AUTH', 'radar/attacks/layer7/top/vertical') self.add('VOID', 'radar/bgp') self.add('VOID', 'radar/bgp/leaks') @@ -1102,6 +1162,7 @@ self.add('AUTH', 'radar/traffic_anomalies') self.add('AUTH', 'radar/traffic_anomalies/locations') + def from_developers(self): """ from_developers """ self.add('VOID', 'accounts', 'analytics_engine') diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cloudflare-2.12.4/CloudFlare/cloudflare.py new/cloudflare-2.14.2/CloudFlare/cloudflare.py --- old/cloudflare-2.12.4/CloudFlare/cloudflare.py 2023-09-21 19:03:51.000000000 +0200 +++ new/cloudflare-2.14.2/CloudFlare/cloudflare.py 2023-11-25 21:03:43.000000000 +0100 @@ -15,6 +15,9 @@ BASE_URL = 'https://api.cloudflare.com/client/v4' +DEFAULT_GLOBAL_REQUEST_TIMEOUT = 5 +DEFAULT_MAX_REQUEST_RETRIES = 5 + class CloudFlare(): """ Cloudflare v4 API""" @@ -24,6 +27,7 @@ def __init__(self, config): """ Cloudflare v4 API""" + self.network = None self.config = config self.api_email = config['email'] if 'email' in config else None @@ -36,8 +40,16 @@ self.raw = config['raw'] self.use_sessions = config['use_sessions'] - self.global_request_timeout = config['global_request_timeout'] if 'global_request_timeout' in config else None - self.max_request_retries = config['max_request_retries'] if 'max_request_retries' in config else None + self.global_request_timeout = config['global_request_timeout'] if 'global_request_timeout' in config else DEFAULT_GLOBAL_REQUEST_TIMEOUT + self.max_request_retries = config['max_request_retries'] if 'max_request_retries' in config else DEFAULT_MAX_REQUEST_RETRIES + try: + self.global_request_timeout = int(self.global_request_timeout) + except (TypeError, ValueError): + self.global_request_timeout = DEFAULT_GLOBAL_REQUEST_TIMEOUT + try: + self.max_request_retries = int(self.max_request_retries) + except (TypeError, ValueError): + self.max_request_retries = DEFAULT_MAX_REQUEST_RETRIES self.profile = config['profile'] self.network = CFnetwork( use_sessions=self.use_sessions, @@ -245,7 +257,10 @@ response_data = response_data.decode("utf-8") if self.logger: - self.logger.debug('Response: %d, %s, %s', response_code, response_type, response_data) + if 'text/' == response_type[0:5] or response_type in ['application/javascript', 'application/json']: + self.logger.debug('Response: %d, %s, %s', response_code, response_type, response_data[0:100]) + else: + self.logger.debug('Response: %d, %s, %s', response_code, response_type, '...') if response_code >= 500 and response_code <= 599: # 500 Internal Server Error @@ -421,6 +436,14 @@ 'code': response_code, 'result': str(response_data)} + elif response_type[0:6] in ['audio/', 'image/', 'video/']: + # raw - just pass thru + if response_code == requests_codes.ok: + response_data = {'success': True, 'result': response_data} + else: + response_data = {'success': False, + 'code': response_code, + 'result': response_data} else: # Assuming nothing - but continuing anyway # A single value is returned (vs an array or object) @@ -531,7 +554,10 @@ except: result = response_data if self.logger: - self.logger.debug('Response: %s', result) + if isinstance(result, str): + self.logger.debug('Response: %s', result[0:100]) + else: + self.logger.debug('Response: %s', '...') return result def _call_unwrapped(self, method, headers, parts, identifiers, params, data, files): @@ -913,7 +939,7 @@ return api_decode_from_openapi(self._base.api_from_openapi(url)) - def __init__(self, email=None, key=None, token=None, certtoken=None, debug=False, raw=False, use_sessions=True, profile=None, base_url=None, global_request_timeout=5, max_request_retries=5): + def __init__(self, email=None, key=None, token=None, certtoken=None, debug=False, raw=False, use_sessions=True, profile=None, base_url=None, global_request_timeout=None, max_request_retries=None): """ Cloudflare v4 API""" self._base = None diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cloudflare-2.12.4/CloudFlare/network.py new/cloudflare-2.14.2/CloudFlare/network.py --- old/cloudflare-2.12.4/CloudFlare/network.py 2023-09-21 19:03:51.000000000 +0200 +++ new/cloudflare-2.14.2/CloudFlare/network.py 2023-11-25 19:54:13.000000000 +0100 @@ -12,7 +12,7 @@ """Network for Cloudflare API""" def __init__( - self, max_request_retries, use_sessions=True, global_request_timeout=5, + self, use_sessions=True, global_request_timeout=5, max_request_retries=5 ): """Network for Cloudflare API""" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cloudflare-2.12.4/CloudFlare/read_configs.py new/cloudflare-2.14.2/CloudFlare/read_configs.py --- old/cloudflare-2.12.4/CloudFlare/read_configs.py 2022-09-08 01:46:45.000000000 +0200 +++ new/cloudflare-2.14.2/CloudFlare/read_configs.py 2023-11-25 20:15:16.000000000 +0100 @@ -21,6 +21,9 @@ config['extras'] = os.getenv('CLOUDFLARE_API_EXTRAS') if os.getenv('CLOUDFLARE_API_EXTRAS') is not None else os.getenv('CF_API_EXTRAS') config['base_url'] = os.getenv('CLOUDFLARE_API_URL') if os.getenv('CLOUDFLARE_API_URL') is not None else os.getenv('CF_API_URL') + config['global_request_timeout'] = os.getenv('CLOUDFLARE_GLOBAL_REQUEST_TIMEOUT') + config['max_request_retries'] = os.getenv('CLOUDFLARE_MAX_REQUEST_RETRIES') + # grab values from config files cp = configparser.ConfigParser() try: @@ -55,7 +58,7 @@ if not cp.has_section(profile): raise Exception("%s: configuration section missing - configuration file only has these sections: %s" % (profile, ','.join(cp.sections()))) - for option in ['email', 'key', 'token', 'certtoken', 'extras', 'base_url']: + for option in ['email', 'key', 'token', 'certtoken', 'extras', 'base_url', 'global_request_timeout', 'max_request_retries']: try: config_value = cp.get(profile, option) if option == 'extras': diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cloudflare-2.12.4/PKG-INFO new/cloudflare-2.14.2/PKG-INFO --- old/cloudflare-2.12.4/PKG-INFO 2023-09-22 03:47:10.381636400 +0200 +++ new/cloudflare-2.14.2/PKG-INFO 2023-11-26 05:05:51.078833000 +0100 @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: cloudflare -Version: 2.12.4 +Version: 2.14.2 Summary: Python wrapper for the Cloudflare v4 API Home-page: https://github.com/cloudflare/python-cloudflare Author: Martin J. Levy @@ -481,7 +481,7 @@ ### Exception examples -Here's examples using the CLI command cli4 of the responses passed back in exceptions. +Here's examples using the CLI command `cli4` of the responses passed back in exceptions. First a simple get with a clean (non-error) response. @@ -551,16 +551,16 @@ $ ``` -It will show up if you are running on an older system. For example, this is the results from running on Win7): +It will show up if you are running on an older system. For example, this is the results from running on Win7: ```bash -U:\Users\█████>cli4 -e +U:\Users\Bobby>cli4 -e Module "importlib_resources" missing - please "pip install importlib_resources" as your Python version is lower than 3.9 -U:\Users\█████>python -V +U:\Users\Bobby>python -V Python 3.8.3 -U:\Users\█████> +U:\Users\Bobby> ``` Upgrading from an older version of Python is always recommended. Upgrading from Win7 is by-default even more important! @@ -622,12 +622,23 @@ ## CLI -All API calls can be called from the command line. -The command will convert domain names prefixed with a colon (`:`) into zone_identifiers: e.g. to view `example.com` you must use `cli4 /zones/:example.com` (the zone ID cannot be used). - -```bash -$ cli4 [-V|--version] [-h|--help] [-v|--verbose] [-q|--quiet] [-j|--json] [-y|--yaml] [-n|ndjson] [-r|--raw] [-d|--dump] [-A|--openapi url] [-b|--binary] [-p|--profile profile-name] [--get|--patch|--post|--put|--delete] [item=value|item=@filename|@filename ...] /command ... - +All API calls can be called from the command line via the `cli4` command. +Additionally, the `cli4` command will convert domain name or account name prefixed with a colon (`:`) into the correct identifier. +e.g. to view `example.com` you can use `cli4 /zones/:example.com`. +You can pass the zone identifier (or account identifier or any identifier) with a colon followed by the identifier as a hex number 32 characters long. + +```bash +$ cli4 [-V|--version] [-h|--help] [-v|--verbose] \ + [-e|--examples] \ + [-q|--quiet] \ + [-j|--json] [-y|--yaml] [-n|--ndjson] [-i|--image] \ + [-r|--raw] \ + [-d|--dump] \ + [-A|--openapi url] \ + [-b|--binary] \ + [-p|--profile profile-name] \ + [--get|--patch|--post|--put|--delete] \ + [item=value|item=@filename|@filename ...] /command ... ``` ### CLI parameters for POST/PUT/PATCH @@ -663,7 +674,13 @@ ### CLI output -The output from the CLI command is in JSON or YAML format (and human readable). This is controled by the **--yaml** or **--json** flags (JSON is the default). +The default output from the CLI command is in JSON. +It can also output YAML format (i.e. human readable). +This is controled by the `--yaml` or `--json` flags (JSON is the default). +There is also a `--ndjson` flag for use with line based JSON data - this is mainly used for log data. + +Additonally the output can be plain text or binary image format depending on the results from the API call (some calls results in non JSON results). +The `--image` flag will return the data in the same format as the API's results. ### Simple CLI examples @@ -1266,6 +1283,63 @@ For more information on how to use GraphQL at Cloudflare, refer to the [Cloudflare GraphQL Analytics API](https://developers.cloudflare.com/analytics/graphql-api). It contains a full overview of Cloudflare's GraphQL features and keywords. +## Cloudflare AI + +See https://blog.cloudflare.com/workers-ai-update-stable-diffusion-code-llama-wo... for the introduction, +along with https://developers.cloudflare.com/workers-ai/models/ for the nitty gritty details. + +There are two examples for AI calls included with the code. + +```bash +$ python examples/example_ai_images.py A happy llama running through an orange cloud > /tmp/image.png +$ +$ file /tmp/image.png +/tmp/image.png: PNG image data, 1024 x 1024, 8-bit/color RGB, non-interlaced +$ +``` + +```bash +$ python examples/example_ai_translate.py I\'ll have an order of the moule frites +Je vais avoir une commande des frites de moule +$ +``` + +This is presently work-in-progress because of the non-Python calling method. The syntax could change in the future. +The examples will be updated. + +They can also be called via `cli4`. + +```bash +$ cli4 --image --post text="I'll have an order of the moule frites" source_lang=english target_lang=french /accounts/:AccountID/ai/run/@cf/meta/m2m100-1.2b +{'translated_text': 'Je vais avoir une commande des frites de moule'} +$ +``` + +Presently you will need the following in your `cloudflare.cfg` file. + +```bash +$ cat ~/.cloudflare/cloudflare.cfg +[CloudFlare] +global_request_timeout = 120 +max_request_retries = 1 +extras = + /accounts/:id/ai/run/@cf/meta/llama-2-7b-chat-fp16 + /accounts/:id/ai/run/@cf/meta/llama-2-7b-chat-int8 + /accounts/:id/ai/run/@cf/mistral/mistral-7b-instruct-v0.1 + /accounts/:id/ai/run/@cf/openai/whisper + /accounts/:id/ai/run/@cf/meta/m2m100-1.2b + /accounts/:id/ai/run/@cf/huggingface/distilbert-sst-2-int8 + /accounts/:id/ai/run/@cf/microsoft/resnet-50 + /accounts/:id/ai/run/@cf/stabilityai/stable-diffusion-xl-base-1.0 + /accounts/:id/ai/run/@cf/baai/bge-base-en-v1.5 + /accounts/:id/ai/run/@cf/baai/bge-large-en-v1.5 + /accounts/:id/ai/run/@cf/baai/bge-small-en-v1.5 + +$ +``` + +Along with a version of the library above `2.14.1`. + ## Implemented API calls The **--dump** argument to cli4 will produce a list of all the call implemented within the library. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cloudflare-2.12.4/README.md new/cloudflare-2.14.2/README.md --- old/cloudflare-2.12.4/README.md 2023-09-21 19:32:37.000000000 +0200 +++ new/cloudflare-2.14.2/README.md 2023-11-26 05:04:23.000000000 +0100 @@ -463,7 +463,7 @@ ### Exception examples -Here's examples using the CLI command cli4 of the responses passed back in exceptions. +Here's examples using the CLI command `cli4` of the responses passed back in exceptions. First a simple get with a clean (non-error) response. @@ -533,16 +533,16 @@ $ ``` -It will show up if you are running on an older system. For example, this is the results from running on Win7): +It will show up if you are running on an older system. For example, this is the results from running on Win7: ```bash -U:\Users\█████>cli4 -e +U:\Users\Bobby>cli4 -e Module "importlib_resources" missing - please "pip install importlib_resources" as your Python version is lower than 3.9 -U:\Users\█████>python -V +U:\Users\Bobby>python -V Python 3.8.3 -U:\Users\█████> +U:\Users\Bobby> ``` Upgrading from an older version of Python is always recommended. Upgrading from Win7 is by-default even more important! @@ -604,12 +604,23 @@ ## CLI -All API calls can be called from the command line. -The command will convert domain names prefixed with a colon (`:`) into zone_identifiers: e.g. to view `example.com` you must use `cli4 /zones/:example.com` (the zone ID cannot be used). - -```bash -$ cli4 [-V|--version] [-h|--help] [-v|--verbose] [-q|--quiet] [-j|--json] [-y|--yaml] [-n|ndjson] [-r|--raw] [-d|--dump] [-A|--openapi url] [-b|--binary] [-p|--profile profile-name] [--get|--patch|--post|--put|--delete] [item=value|item=@filename|@filename ...] /command ... - +All API calls can be called from the command line via the `cli4` command. +Additionally, the `cli4` command will convert domain name or account name prefixed with a colon (`:`) into the correct identifier. +e.g. to view `example.com` you can use `cli4 /zones/:example.com`. +You can pass the zone identifier (or account identifier or any identifier) with a colon followed by the identifier as a hex number 32 characters long. + +```bash +$ cli4 [-V|--version] [-h|--help] [-v|--verbose] \ + [-e|--examples] \ + [-q|--quiet] \ + [-j|--json] [-y|--yaml] [-n|--ndjson] [-i|--image] \ + [-r|--raw] \ + [-d|--dump] \ + [-A|--openapi url] \ + [-b|--binary] \ + [-p|--profile profile-name] \ + [--get|--patch|--post|--put|--delete] \ + [item=value|item=@filename|@filename ...] /command ... ``` ### CLI parameters for POST/PUT/PATCH @@ -645,7 +656,13 @@ ### CLI output -The output from the CLI command is in JSON or YAML format (and human readable). This is controled by the **--yaml** or **--json** flags (JSON is the default). +The default output from the CLI command is in JSON. +It can also output YAML format (i.e. human readable). +This is controled by the `--yaml` or `--json` flags (JSON is the default). +There is also a `--ndjson` flag for use with line based JSON data - this is mainly used for log data. + +Additonally the output can be plain text or binary image format depending on the results from the API call (some calls results in non JSON results). +The `--image` flag will return the data in the same format as the API's results. ### Simple CLI examples @@ -1248,6 +1265,63 @@ For more information on how to use GraphQL at Cloudflare, refer to the [Cloudflare GraphQL Analytics API](https://developers.cloudflare.com/analytics/graphql-api). It contains a full overview of Cloudflare's GraphQL features and keywords. +## Cloudflare AI + +See https://blog.cloudflare.com/workers-ai-update-stable-diffusion-code-llama-wo... for the introduction, +along with https://developers.cloudflare.com/workers-ai/models/ for the nitty gritty details. + +There are two examples for AI calls included with the code. + +```bash +$ python examples/example_ai_images.py A happy llama running through an orange cloud > /tmp/image.png +$ +$ file /tmp/image.png +/tmp/image.png: PNG image data, 1024 x 1024, 8-bit/color RGB, non-interlaced +$ +``` + +```bash +$ python examples/example_ai_translate.py I\'ll have an order of the moule frites +Je vais avoir une commande des frites de moule +$ +``` + +This is presently work-in-progress because of the non-Python calling method. The syntax could change in the future. +The examples will be updated. + +They can also be called via `cli4`. + +```bash +$ cli4 --image --post text="I'll have an order of the moule frites" source_lang=english target_lang=french /accounts/:AccountID/ai/run/@cf/meta/m2m100-1.2b +{'translated_text': 'Je vais avoir une commande des frites de moule'} +$ +``` + +Presently you will need the following in your `cloudflare.cfg` file. + +```bash +$ cat ~/.cloudflare/cloudflare.cfg +[CloudFlare] +global_request_timeout = 120 +max_request_retries = 1 +extras = + /accounts/:id/ai/run/@cf/meta/llama-2-7b-chat-fp16 + /accounts/:id/ai/run/@cf/meta/llama-2-7b-chat-int8 + /accounts/:id/ai/run/@cf/mistral/mistral-7b-instruct-v0.1 + /accounts/:id/ai/run/@cf/openai/whisper + /accounts/:id/ai/run/@cf/meta/m2m100-1.2b + /accounts/:id/ai/run/@cf/huggingface/distilbert-sst-2-int8 + /accounts/:id/ai/run/@cf/microsoft/resnet-50 + /accounts/:id/ai/run/@cf/stabilityai/stable-diffusion-xl-base-1.0 + /accounts/:id/ai/run/@cf/baai/bge-base-en-v1.5 + /accounts/:id/ai/run/@cf/baai/bge-large-en-v1.5 + /accounts/:id/ai/run/@cf/baai/bge-small-en-v1.5 + +$ +``` + +Along with a version of the library above `2.14.1`. + ## Implemented API calls The **--dump** argument to cli4 will produce a list of all the call implemented within the library. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cloudflare-2.12.4/cli4/cli4.py new/cloudflare-2.14.2/cli4/cli4.py --- old/cloudflare-2.12.4/cli4/cli4.py 2023-09-19 18:52:10.000000000 +0200 +++ new/cloudflare-2.14.2/cli4/cli4.py 2023-11-25 21:55:10.000000000 +0100 @@ -320,9 +320,11 @@ if len(results) == 1: results = results[0] - if isinstance(results, str): + if isinstance(results, str) or isinstance(results, (bytes, bytearray)): # if the results are a simple string, then it should be dumped directly # this is only used for /zones/:id/dns_records/export presently + # or + # output is image or audio or video or something like that so we dump directly pass else: # anything more complex (dict, list, etc) should be dumped as JSON/YAML @@ -350,14 +352,18 @@ pass return else: - # Internal error - pass + # None of the above, so pass thru results except something in byte form + if not isinstance(results, (bytes, bytearray)): + results = str(results) if results: try: - sys.stdout.write(results) - if not results.endswith('\n'): - sys.stdout.write('\n') + if isinstance(results, (bytes, bytearray)): + sys.stdout.buffer.write(results) + else: + sys.stdout.write(results) + if not results.endswith('\n'): + sys.stdout.write('\n') except (BrokenPipeError, IOError): pass @@ -375,9 +381,10 @@ method = 'GET' usage = ('usage: cli4 ' - + '[-V|--version] [-h|--help] [-v|--verbose] [-q|--quiet] ' + + '[-V|--version] [-h|--help] [-v|--verbose] ' + '[-e|--examples] ' - + '[-j|--json] [-y|--yaml] [-n|ndjson] ' + + '[-q|--quiet] ' + + '[-j|--json] [-y|--yaml] [-n|--ndjson] [-i|--image] ' + '[-r|--raw] ' + '[-d|--dump] ' + '[-A|--openapi url] ' @@ -389,12 +396,15 @@ try: opts, args = getopt.getopt(args, - 'VhvqejyrdA:bp:GPOUD', + 'VhveqjynirdA:bp:GPOUD', [ - 'version', - 'help', 'verbose', 'quiet', 'examples', 'json', 'yaml', 'ndjson', + 'version', 'help', 'verbose', + 'examples', + 'quiet', + 'json', 'yaml', 'ndjson', 'image', 'raw', - 'dump', 'openapi=', + 'dump', + 'openapi=', 'binary', 'profile=', 'get', 'patch', 'post', 'put', 'delete' @@ -424,6 +434,8 @@ if not my_jsonlines.available(): sys.exit('cli4: install jsonlines support') output = 'ndjson' + elif opt in ('-i', '--image'): + output = 'image' elif opt in ('-r', '--raw'): raw = True elif opt in ('-p', '--profile'): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cloudflare-2.12.4/cloudflare.egg-info/PKG-INFO new/cloudflare-2.14.2/cloudflare.egg-info/PKG-INFO --- old/cloudflare-2.12.4/cloudflare.egg-info/PKG-INFO 2023-09-22 03:47:10.000000000 +0200 +++ new/cloudflare-2.14.2/cloudflare.egg-info/PKG-INFO 2023-11-26 05:05:51.000000000 +0100 @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: cloudflare -Version: 2.12.4 +Version: 2.14.2 Summary: Python wrapper for the Cloudflare v4 API Home-page: https://github.com/cloudflare/python-cloudflare Author: Martin J. Levy @@ -481,7 +481,7 @@ ### Exception examples -Here's examples using the CLI command cli4 of the responses passed back in exceptions. +Here's examples using the CLI command `cli4` of the responses passed back in exceptions. First a simple get with a clean (non-error) response. @@ -551,16 +551,16 @@ $ ``` -It will show up if you are running on an older system. For example, this is the results from running on Win7): +It will show up if you are running on an older system. For example, this is the results from running on Win7: ```bash -U:\Users\█████>cli4 -e +U:\Users\Bobby>cli4 -e Module "importlib_resources" missing - please "pip install importlib_resources" as your Python version is lower than 3.9 -U:\Users\█████>python -V +U:\Users\Bobby>python -V Python 3.8.3 -U:\Users\█████> +U:\Users\Bobby> ``` Upgrading from an older version of Python is always recommended. Upgrading from Win7 is by-default even more important! @@ -622,12 +622,23 @@ ## CLI -All API calls can be called from the command line. -The command will convert domain names prefixed with a colon (`:`) into zone_identifiers: e.g. to view `example.com` you must use `cli4 /zones/:example.com` (the zone ID cannot be used). - -```bash -$ cli4 [-V|--version] [-h|--help] [-v|--verbose] [-q|--quiet] [-j|--json] [-y|--yaml] [-n|ndjson] [-r|--raw] [-d|--dump] [-A|--openapi url] [-b|--binary] [-p|--profile profile-name] [--get|--patch|--post|--put|--delete] [item=value|item=@filename|@filename ...] /command ... - +All API calls can be called from the command line via the `cli4` command. +Additionally, the `cli4` command will convert domain name or account name prefixed with a colon (`:`) into the correct identifier. +e.g. to view `example.com` you can use `cli4 /zones/:example.com`. +You can pass the zone identifier (or account identifier or any identifier) with a colon followed by the identifier as a hex number 32 characters long. + +```bash +$ cli4 [-V|--version] [-h|--help] [-v|--verbose] \ + [-e|--examples] \ + [-q|--quiet] \ + [-j|--json] [-y|--yaml] [-n|--ndjson] [-i|--image] \ + [-r|--raw] \ + [-d|--dump] \ + [-A|--openapi url] \ + [-b|--binary] \ + [-p|--profile profile-name] \ + [--get|--patch|--post|--put|--delete] \ + [item=value|item=@filename|@filename ...] /command ... ``` ### CLI parameters for POST/PUT/PATCH @@ -663,7 +674,13 @@ ### CLI output -The output from the CLI command is in JSON or YAML format (and human readable). This is controled by the **--yaml** or **--json** flags (JSON is the default). +The default output from the CLI command is in JSON. +It can also output YAML format (i.e. human readable). +This is controled by the `--yaml` or `--json` flags (JSON is the default). +There is also a `--ndjson` flag for use with line based JSON data - this is mainly used for log data. + +Additonally the output can be plain text or binary image format depending on the results from the API call (some calls results in non JSON results). +The `--image` flag will return the data in the same format as the API's results. ### Simple CLI examples @@ -1266,6 +1283,63 @@ For more information on how to use GraphQL at Cloudflare, refer to the [Cloudflare GraphQL Analytics API](https://developers.cloudflare.com/analytics/graphql-api). It contains a full overview of Cloudflare's GraphQL features and keywords. +## Cloudflare AI + +See https://blog.cloudflare.com/workers-ai-update-stable-diffusion-code-llama-wo... for the introduction, +along with https://developers.cloudflare.com/workers-ai/models/ for the nitty gritty details. + +There are two examples for AI calls included with the code. + +```bash +$ python examples/example_ai_images.py A happy llama running through an orange cloud > /tmp/image.png +$ +$ file /tmp/image.png +/tmp/image.png: PNG image data, 1024 x 1024, 8-bit/color RGB, non-interlaced +$ +``` + +```bash +$ python examples/example_ai_translate.py I\'ll have an order of the moule frites +Je vais avoir une commande des frites de moule +$ +``` + +This is presently work-in-progress because of the non-Python calling method. The syntax could change in the future. +The examples will be updated. + +They can also be called via `cli4`. + +```bash +$ cli4 --image --post text="I'll have an order of the moule frites" source_lang=english target_lang=french /accounts/:AccountID/ai/run/@cf/meta/m2m100-1.2b +{'translated_text': 'Je vais avoir une commande des frites de moule'} +$ +``` + +Presently you will need the following in your `cloudflare.cfg` file. + +```bash +$ cat ~/.cloudflare/cloudflare.cfg +[CloudFlare] +global_request_timeout = 120 +max_request_retries = 1 +extras = + /accounts/:id/ai/run/@cf/meta/llama-2-7b-chat-fp16 + /accounts/:id/ai/run/@cf/meta/llama-2-7b-chat-int8 + /accounts/:id/ai/run/@cf/mistral/mistral-7b-instruct-v0.1 + /accounts/:id/ai/run/@cf/openai/whisper + /accounts/:id/ai/run/@cf/meta/m2m100-1.2b + /accounts/:id/ai/run/@cf/huggingface/distilbert-sst-2-int8 + /accounts/:id/ai/run/@cf/microsoft/resnet-50 + /accounts/:id/ai/run/@cf/stabilityai/stable-diffusion-xl-base-1.0 + /accounts/:id/ai/run/@cf/baai/bge-base-en-v1.5 + /accounts/:id/ai/run/@cf/baai/bge-large-en-v1.5 + /accounts/:id/ai/run/@cf/baai/bge-small-en-v1.5 + +$ +``` + +Along with a version of the library above `2.14.1`. + ## Implemented API calls The **--dump** argument to cli4 will produce a list of all the call implemented within the library. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cloudflare-2.12.4/cloudflare.egg-info/SOURCES.txt new/cloudflare-2.14.2/cloudflare.egg-info/SOURCES.txt --- old/cloudflare-2.12.4/cloudflare.egg-info/SOURCES.txt 2023-09-22 03:47:10.000000000 +0200 +++ new/cloudflare-2.14.2/cloudflare.egg-info/SOURCES.txt 2023-11-26 05:05:51.000000000 +0100 @@ -31,6 +31,8 @@ cloudflare.egg-info/top_level.txt examples/__init__.py examples/example_account_rules_lists_items.py +examples/example_ai_images.py +examples/example_ai_translate.py examples/example_always_use_https.py examples/example_are_zones_ipv6.py examples/example_are_zones_ipv6_simple.py diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cloudflare-2.12.4/examples/example_ai_images.py new/cloudflare-2.14.2/examples/example_ai_images.py --- old/cloudflare-2.12.4/examples/example_ai_images.py 1970-01-01 01:00:00.000000000 +0100 +++ new/cloudflare-2.14.2/examples/example_ai_images.py 2023-11-26 04:41:20.000000000 +0100 @@ -0,0 +1,67 @@ +#!/usr/bin/env python + +import os +import sys +import CloudFlare + +def find_call(cf, verbs): + # So we walk over the @ via a getattr() call. + # We also have to deal with a . in a verb - that does not work in Python. So sad. + # Also, the - is actually an _ in this Python library. + # This is not normally needed for other calls + m = cf + for verb in verbs.split('/'): + m = getattr(m, verb) + return m + +def doit(account_name, prompt_text): + + # Or place these in your cloudflare.cfg file + os.environ['CLOUDFLARE_API_EXTRAS'] = '/accounts/:id/ai/run/@cf/stabilityai/stable-diffusion-xl-base-1.0' + + # We set the timeout because these AI calls take longer than normal API calls + cf = CloudFlare.CloudFlare(global_request_timeout=120) + + try: + if account_name == None or account_name == '': + params = {'per_page': 1} + else: + params = {'name': account_name, 'per_page': 1} + accounts = cf.accounts.get(params=params) + except CloudFlare.exceptions.CloudFlareAPIError as e: + exit('/accounts %d %s - api call failed' % (e, e)) + + try: + account_id = accounts[0]['id'] + except IndexError: + exit('%s: account name not found' % (account_name)) + + image_create_data = { + 'prompt': prompt_text, + } + + try: + # This should be easy to call; however, the @ will not work in Python (or many languages) + # r = cf.accounts.ai.run.@cf.stabilityai.stable-diffusion-xl-base-1.0(account_id, data=image_create_data) + # We find the endpoint via a quick string search + r = find_call(cf, 'accounts/ai/run/@cf/stabilityai/stable_diffusion_xl_base_1.0').post(account_id, data=image_create_data) + except CloudFlare.exceptions.CloudFlareAPIError as e: + exit('/ai.run %d %s - api call failed' % (e, e)) + + sys.stdout.buffer.write(r) + +def main(): + if sys.argv[1] == '-a': + del sys.argv[1] + account_name = sys.argv[1] + del sys.argv[1] + else: + account_name = None + if len(sys.argv) > 1: + prompt_text = ' '.join(sys.argv[1:]) + else: + prompt_text = "A happy llama running through an orange cloud" + doit(account_name, prompt_text) + +if __name__ == '__main__': + main() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cloudflare-2.12.4/examples/example_ai_translate.py new/cloudflare-2.14.2/examples/example_ai_translate.py --- old/cloudflare-2.12.4/examples/example_ai_translate.py 1970-01-01 01:00:00.000000000 +0100 +++ new/cloudflare-2.14.2/examples/example_ai_translate.py 2023-11-26 04:41:35.000000000 +0100 @@ -0,0 +1,69 @@ +#!/usr/bin/env python + +import os +import sys +import CloudFlare + +def find_call(cf, verbs): + # So we walk over the @ via a getattr() call. + # We also have to deal with a . in a verb - that does not work in Python. So sad. + # Also, the - is actually an _ in this Python library. + # This is not normally needed for other calls + m = cf + for verb in verbs.split('/'): + m = getattr(m, verb) + return m + +def doit(account_name, english_text): + + # Or place these in your cloudflare.cfg file + os.environ['CLOUDFLARE_API_EXTRAS'] = '/accounts/:id/ai/run/@cf/meta/m2m100-1.2b' + + # We set the timeout because these AI calls take longer than normal API calls + cf = CloudFlare.CloudFlare(global_request_timeout=120) + + try: + if account_name == None or account_name == '': + params = {'per_page': 1} + else: + params = {'name': account_name, 'per_page': 1} + accounts = cf.accounts.get(params=params) + except CloudFlare.exceptions.CloudFlareAPIError as e: + exit('/accounts %d %s - api call failed' % (e, e)) + + try: + account_id = accounts[0]['id'] + except IndexError: + exit('%s: account name not found' % (account_name)) + + translate_data = { + 'text': english_text, + 'source_lang': 'english', + 'target_lang': 'french', + } + + try: + # This should be easy to call; however, the @ will not work in Python (or many languages) + # r = cf.accounts.ai.run.@cf.meta.m2m100-1.2b(account_id, data=translate_data) + # We find the endpoint via a quick string search + r = find_call(cf, 'accounts/ai/run/@cf/meta/m2m100_1.2b').post(account_id, data=translate_data) + except CloudFlare.exceptions.CloudFlareAPIError as e: + exit('/ai.run %d %s - api call failed' % (e, e)) + + print(r['translated_text']) + +def main(): + if sys.argv[1] == '-a': + del sys.argv[1] + account_name = sys.argv[1] + del sys.argv[1] + else: + account_name = None + if len(sys.argv) > 1: + english_text = ' '.join(sys.argv[1:]) + else: + english_text = "I'll have an order of the moule frites" + doit(account_name, english_text) + +if __name__ == '__main__': + main() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cloudflare-2.12.4/setup.py new/cloudflare-2.14.2/setup.py --- old/cloudflare-2.12.4/setup.py 2022-10-02 21:47:42.000000000 +0200 +++ new/cloudflare-2.14.2/setup.py 2023-11-25 19:20:54.000000000 +0100 @@ -9,7 +9,7 @@ def main(): """Cloudflare API code - setup.py file""" - with open('README.md') as read_me: + with open('README.md', encoding="utf-8") as read_me: long_description = read_me.read() with open('CloudFlare/__init__.py', 'r') as f:
participants (1)
-
Source-Sync