Saravanan666/pypi-org huggingface dataset:
Package: buffalofq
The objective of BuffaloFQ is to provide a very simple and reliable
method of moving files around an architecture.Background, Examples, and FAQPlease see the Wiki:https://github.com/kenfar/buffalofq/wikiInstallation:$ pip install buffalofqConfiguration:Most configuration is handled through a simple yaml file, that is kept
in the xdg-compliant config directory. On linux this would be:$HOME/.config/buffalofq_mover/[config-name1].yml$HOME/.config/buffalofq_mover/[config-name2].yml$HOME/.config/buffalofq_mover/[config-name3].ymlConfig example:name: ids_to_load #status: enabled # choices are: enabled, disabledpolling_seconds: None # delay in seconds between checks for new
files, defaults to 300limit_total: -1 # choices: -1 (run continuously), 0 (run until
source_dir is empty), [some number] run until this number have been
moved.port: None # defaults to 22key_filename: None # defaults to id_buffalofq_rsalog_dir: /data/logs # location buffalofq_mover will write its logslog_level: None # choices are: info, warning, error, critical,
defaults to debugsort_key: time # choices are: None, name, or name of a field within
filename, defaults to Nonesource_host: localhost # must be localhost at this timesource_user: None # not yet used, defaults to current useridsource_dir: /data/output #source_fn: ‘*’ # wild-card for selecting source filessource_post_dir: /data/archive #source_post_action: move # choices: move, delete, Nonedest_host: datawarehouse #dest_user: None # used to log into dest_host, defaults to current
useriddest_dir: /data/input #dest_fn: None # needed if dest_post_action is symlink or movedest_post_dir: None # not used yetdest_post_action: None # choices: symlink, move, NoneRun:To run once, you can simply run it like:$ ./buffalofq_mover –config-name [config-name1]A trivial way to keep it running continuously:$ nohup ./buffalofq_mover –config-name [config-name1] &0.0.3 - add dest_post_action of move - change config values of pass to
None - add config defaults & validation - housekeeping0.0.2 - initial genuinely usable working version - add ability to
receive files in order of their name, or any field within the name - add
ability to provide name of ssh key to use - rename audit file &
buffalofq program to buffalofq_mover - misc general improvements and
refactorings0.0.1 - initial working version
Package: buffalo-lab-data-to-nwb
Buffalo-lab-data-to-nwbScripts which convert Buffalo lab data to NWB format. Currently we only support conversion for processed data.authors: Luiz Tauffer, Maija Honig, Ryan Ly, Ben DichterInstallpip install git+https://github.com/ben-dichter-consulting/buffalo-lab-data-to-nwb.gitUseThe conversion function can be used in different forms:1. Imported and run from a python script:Here's an example: we'll grab raw data (.ncsfiles) and processed data (.matand.nex5files) and convert them to.nwbfiles.frombuffalonwb.conversion_moduleimportconversion_functionfrompathlibimportPathimportyamlbase_path=Path(BASE_PATH_TO_FILES)# Source filessource_paths=dict()source_paths['raw Nlx']={'type':'dir','path':base_path.joinpath("RawNlxCSCs")}source_paths['processed Nlx']={'type':'dir','path':str(base_path.joinpath('ProcessedNlxData'))}source_paths['processed behavior']={'type':'file','path':str(base_path.joinpath('ProcessedBehavior/MatFile_2017-04-27_11-41-21.mat'))}source_paths['sorted spikes']={'type':'file','path':str(base_path.joinpath('SortedSpikes/2017-04-27_11-41-21_sorted.nex5'))}# Output .nwb filef_nwb='buffalo.nwb'# Load metadata from YAML filemetafile='metafile.yml'withopen(metafile)asf:metadata=yaml.safe_load(f)kwargs_fields={'skip_raw':True,'skip_processed':False,'no_lfp_iterator':False,}conversion_function(source_paths=source_paths,f_nwb=f_nwb,metadata=metadata,**kwargs_fields)2. Command line:Similarly, the conversion function can be called from the command line in terminal:$ python conversion_module.py [raw_nlx_dir] [lfp_mat_dir]
  [sorted_spikes_nex5_file] [behavior_file] [output_file] [metadata_file]
  [-skipraw] [-skipprocessed] [-lfpiterator]IMPORTANT:[raw_nlx_dir] and [lfp_mat_dir] should be paths to directories[sorted_spikes_nex5_file] [behavior_file] [output_file] [metadata_file] should be paths to filesoptional inputs
add these after the positional arguments to use additional options"-skipraw" (will skip adding raw data to nwb file)"-skipprocessed" (will skip adding processed data to nwb file)"-lfpiterator" (change lfp data method to dataChunkIterator (for large data))3. Graphical User Interface:To use the GUI, just run the auxiliary functionnwb_gui.pyfrom terminal:$ python nwb_gui.pyThe GUI eases the task of editing the metadata of the resulting.nwbfile, it is integrated with the conversion module (conversion on-click) and allows for visually exploring the data in the end file withnwb-jupyter-widgets.
Package: buffercache
buffercache is a python3 library. It provides utility methods for data caching.buffercache supports Python 3.0+ only. It is contained in only one Python file, so it can be easily copied into your project. (The copyright and license notice must be retained.)example:frombuffercacheimportBufferCacheasBCset_data=((1,2,3),None,"","123",(),[],{})defget(data,args):returndata,argsbc=BC(timeout=0).set_getter(get)fordatainset_data:bc.update(data,{'key':data})print(bc.get())Bugs can be reported tohttps://github.com/caibingcheng/buffercache. The code can also be found there.
Package: buffered-encryption
Buffered EncryptionEncrypt large data files chunk-by-chunk, securely.This package uses AES in GCM mode to encrypt and decrypt file streams.It relies on the cryptography library to perform the encryption.big unencrypted file, verification data --> encrypt and sign --> encrypted file, iv, tag

big unencrypted file <-- decrypt and verify <-- encrypted file, iv, tag, verification dataExamplesAES in GCM modeTheaesgcmmodule provides a way to encrypt and decrypt entire files without loading the entire thing into memory. It does not provide a file-like interface to the encrypted file.importosfrombuffered_encryption.aesgcmimportEncryptionIterator,DecryptionIteratorplaintext=open("plain.txt","rb")key=os.urandom(32)sig=os.urandom(12)enc=EncryptionIterator(plaintext,key,sig)withopen("cipher","wb")asciphertext:forchunkinenc:ciphertext.write(chunk)plaintext.close()ciphertext=open("cipher","rb")dec=DecryptionIterator(ciphertext,key,sig,enc.iv,enc.tag)withopen("plain.dec.txt","wb")asdecrypted:forchunkindec:decrypted.write(chunk)ciphertext.close()AES in CTR modeTheaesctrmodule allows you to read and seek an encrypted file as if it was a normal file. This provides a file-like interface while the data on disk stays encrypted.This will be on the disk:b"1\xb2<\xcco\xbb\xa5%\xa9\xce\xb0\xac\x12\xc1Cw {\xdd\x0c\xa1\x93\x1b'E=v4L\xb8\xb9\x0e\xd5\x90\x8d\xf3H\xeb\x99iX\xcf\xea\xfc\xac\x92\xe8\xff\xb3\xbbS\xcaM\xb2\xf3?\xdf\xd9\x80\xbf\xef\x06\xa2\xab\x977\xc0\xcc\x0f\xd6\xd6' ,"This will be what you read into python:b"Hello, World!! This message is longer than the AES block size of 16 bytes!!"Key and nonce used in the above:key=b'\x0e\x07)\xb8*\xda\x13\x19\xc7`"\x14\xc1i\xe3\xf1$\xa5\xc7w\xda\x1dU\t\x9c\x1f{\xf5tR\xa7b'nonce=b'6\x03\xf5\xdd\x92\x17\x0cDg\xcc\x1a\x9f\xe1\x08\x98\x7f'To recreate this:importos,iofrombuffered_encryption.aesctrimportEncryptionIterator,ReadOnlyEncryptedFilekey=os.urandom(32)nonce=os.urandom(16)plaintext=b"Hello, World!! This message is longer than the AES block size of 16 bytes!!"# Write the ciphertext to a buffer (you can also write to a file)ciphertext_buf=io.BytesIO()enc=EncryptionIterator(io.BytesIO(plaintext),key,nonce)forchunkinenc:ciphertext_buf.write(chunk)ciphertext_buf.seek(0)# Create our read-only encrypted fileef=ReadOnlyEncryptedFile(ciphertext_buf,key,nonce)# Read 12 bytes of dataef.read(12)# returns b"Hello, World"# Seekableef.seek(7)# Keep readingef.read(18)# returns b"World!! This messa"Why read-only?Read-only ensures you do not use the same nonce for different messages. You cannot write different data to a block using the same nonce, and still be cryptographically secure. So if you were to re-write to the encrypted file, you have now defeated your own encryption.
Package: buffered-pipe
buffered_pipeBuffered pipe through shared memory.core featuresPipe: alias forGeneric_PipeGeneric_Pipe: free-length data, bytes or picklableStatic_Pipe: fixed length data, only bytes supportedinstallpipinstallbuffered-pipeusageGeneric_Pipeimportmultiprocessingimportthreadingfrombuffered_pipeimportGeneric_Pipedeffoo(barrier,pipe_send):pipe_send.register()barrier.wait()pipe_send.send("Hello, world!")defbar(barrier,pipe_recv):pipe_recv.register()barrier.wait()print(pipe_recv.recv())if__name__=="__main__":barrier=multiprocessing.Barrier(3)pipe_recv,pipe_send=Generic_Pipe(buffer_size=2048,duplex=False)P=multiprocessing.Process(target=foo,args=(barrier,pipe_send))T=threading.Thread(target=bar,args=(barrier,pipe_recv))P.start()T.start()barrier.wait()P.join()T.join()Static_Pipeimportmultiprocessingimportthreadingfrombuffered_pipeimportStatic_Pipedeffoo(barrier,pipe_send):pipe_send.register()barrier.wait()ret_string="Hello, world!"ret_string=ret_string+" "*(32-len(ret_string))ret_string=ret_string.encode()pipe_send.send(ret_string)defbar(barrier,pipe_recv):pipe_recv.register()barrier.wait()ret_string=pipe_recv.recv()print(ret_string.decode())if__name__=="__main__":barrier=multiprocessing.Barrier(3)pipe_recv,pipe_send=Static_Pipe(object_size=32,object_count=16,duplex=False)P=multiprocessing.Process(target=foo,args=(barrier,pipe_send))T=threading.Thread(target=bar,args=(barrier,pipe_recv))P.start()T.start()barrier.wait()P.join()T.join()When you create aprocessorthread, callregisterofPipeThebuffer_sizeofGeneric_Pipeis inbytes.Theobject_sizeofStatic_Pipeis inbytes.object_countinStatic_Pipeis the maximum number of objects placed in the buffer.duplexis equivalent tomultiprocessing.Pipe.tests>benchmark_result.txtforfinbenchmarks/*.py;dopython3"$f"&>>benchmark_result.txt;done>test_result.txtforfintests/*.py;dopython3"$f"&>>test_result.txt;done
Package: buffered-smtp-handler
Buffered SMTP Logging HandlerA library that mimics the standardlogging.handlers.SMTPHandlerclass but sends email messages only when a preconfigured buffer is full or on exit.Installation and dependenciesInstall the program using pip:pip install buffered_smtp_handlerHow to use itThis library offers two classes:BufferedSMTPHandlerandBufferedSMTPHandlerSSL.They accept the same arguments of thestandard SMTPHandler class, and also thecapacityargument to set the capacity of the buffer (default: 100).The SSL version is based on thesmtplib.SMTP_SSLand avoids to perform StartSSL.Via code:>>> import logging
>>> from pierky.buffered_smtp_handler import BufferedSMTPHandler
>>> logger = logging.getLogger("my_app")
>>> logger.setLevel(logging.INFO)
>>> h = BufferedSMTPHandler("smtp.example.com", "from@example.com", ["to@example.com"], "MyApp log", capacity=10)
>>> logger.addHandler(h)
>>> logger.warning("Test")Via alogging configuration file:[loggers]
keys=root

[formatters]
keys=simple

[handlers]
keys=stderr,smtp

[logger_root]
level=INFO

handlers=stderr,smtp

[formatter_simple]
format=ARouteServer %(asctime)s %(levelname)s %(message)s

[handler_stderr]
class=StreamHandler
formatter=simple
args=(sys.stderr,)

[handler_smtp]
class=pierky.buffered_smtp_handler.BufferedSMTPHandler
level=WARN
formatter=simple
args=(('smtp.example.com', 25), 'from@example.com', ['to@example.com'], 'MyApp log')AuthorPier Carlo Chiodi -https://pierky.com/Blog:https://blog.pierky.com/Twitter:@pierkyChange logv0.1.0First release.
Package: buffering-async-logger
buffering-async-loggerHelpers for sending logs to a destination in batches using a buffer in an async Python app.Built for use withSumo Logic, which allows for sending logs in batches via an HTTP endpoint. Can potentially work with any other similar service.Getting startedInstall a recent Python 3.x version (if you don't already have one).Create a project that uses asyncio (if you don't already have one) - for example aFastAPIbased project. It's also recommended, but not required, that the project usesLoguru.Installbuffering-async-loggeras a dependency usingPoetry, pip, or similar:poetryaddbuffering-async-loggerUse the utils:importjsonfromloggingimportLogRecordfromtypingimportNamedTuplefromfastapiimportFastAPIfromloguruimportloggerfrombuffering_async_loggerimportBufferingAsyncHandlerfrombuffering_async_loggerimportstart_flush_buffer_timerclassLogAggregatorContext(NamedTuple):foo:strmoo:strclassLogAggregatorKey(NamedTuple):woo:strhoo:strdefget_log_aggregator_context()->LogAggregatorContext:returnLogAggregatorContext(foo="foo123",moo="moo123",)defget_log_aggregator_key_for_record(record:LogRecord,context:LogAggregatorContext|None)->LogAggregatorKey:ifcontextisNone:raiseValueError("context is required by get_log_aggregator_key_for_record")returnLogAggregatorKey(woo=context.foo,hoo=f"{context.moo}/{record.levelname}",)defget_request_headers(headers:dict[str,Any],key:LogAggregatorKey)->dict[str,Any]:new_headers=headers.copy()new_headers["X-Logshmog-Woo"]=key.woonew_headers["X-Logshmog-Hoo"]=key.hooreturnnew_headersdefget_serialized_record(record:Any)->dict[str,Any]:_record={"timestamp":f"{record['time']}","level":f"{record['level']}","logger":record["name"],"message":record["message"],}ifrecord["extra"].get("foo"):_record["foo"]=record["extra"]["foo"]ifrecord["extra"].get("moo"):_record["moo"]=record["extra"]["moo"]return_recorddeflog_formatter(record:Any)->str:record["extra"]["serialized"]=json.dumps(get_serialized_record(record))return"{extra[serialized]}\n"asyncdefstart_logshmog_flush_buffer_timer():awaitstart_flush_buffer_timer(10)defconfigure_buffering_async_logger(context:LogAggregatorContext):handler=BufferingAsyncHandler(capacity=1000,url="https://foo.logshmog.com/v1/logs/a1b2c3",get_log_aggregator_key_func=get_aggregator_key_for_record,get_request_headers_func=get_request_headers,chunk_size=100,context=context,)logger.add(handler,format=log_formatter)defconfigure_logger():context=get_log_aggregator_context()logger.configure(extra=context._asdict())# Config for other log handlers may go here ...configure_buffering_async_logger(context)defget_app()->FastAPI:"""Create a FastAPI app instance."""returnFastAPI(on_startup=[start_logshmog_flush_buffer_timer])configure_logger()app=get_app()DevelopingTo clone the repo:gitclonegit@github.com:Jaza/buffering-async-logger.gitTo automatically fix code style issues:./scripts/format.shTo verify code style and static typing:./scripts/verify.shTo run tests:./scripts/test.shBuildingTo build the library:poetrybuildBuilt bySeertech.
Package: buffering-queue-logger
buffering-queue-loggerHelpers for sending logs to a destination in batches using a buffer in a queue alongside any Python app.Built for use withSumo Logic, which allows for sending logs in batches via an HTTP endpoint. Can potentially work with any other similar service.Getting startedInstall a recent Python 3.x version (if you don't already have one).Create any project (if you don't already have one) - for example aFastAPIbased project. It's also recommended, but not required, that the project usesLoguru.Installbuffering-queue-loggeras a dependency usingPoetry, pip, or similar:poetryaddbuffering-queue-loggerUse the utils:importjsonfromloggingimportLogRecordfromtypingimportNamedTuplefromfastapiimportFastAPIfromloguruimportloggerfrombuffering_queue_loggerimportget_buffering_queue_loggerclassLogAggregatorContext(NamedTuple):foo:strmoo:strclassLogAggregatorKey(NamedTuple):woo:strhoo:strdefget_log_aggregator_context()->LogAggregatorContext:returnLogAggregatorContext(foo="foo123",moo="moo123",)defget_log_aggregator_key_for_record(record:LogRecord,context:LogAggregatorContext|None)->LogAggregatorKey:ifcontextisNone:raiseValueError("context is required by get_log_aggregator_key_for_record")returnLogAggregatorKey(woo=context.foo,hoo=f"{context.moo}/{record.levelname}",)defget_request_headers(headers:dict[str,Any],key:LogAggregatorKey)->dict[str,Any]:new_headers=headers.copy()new_headers["X-Logshmog-Woo"]=key.woonew_headers["X-Logshmog-Hoo"]=key.hooreturnnew_headersdefget_serialized_record(record:Any)->dict[str,Any]:_record={"timestamp":f"{record['time']}","level":f"{record['level']}","logger":record["name"],"message":record["message"],}ifrecord["extra"].get("foo"):_record["foo"]=record["extra"]["foo"]ifrecord["extra"].get("moo"):_record["moo"]=record["extra"]["moo"]return_recorddeflog_formatter(record:Any)->str:record["extra"]["serialized"]=json.dumps(get_serialized_record(record))return"{extra[serialized]}\n"asyncdefstart_logshmog_flush_buffer_timer():awaitstart_flush_buffer_timer(10)defconfigure_buffering_queue_logger(context:LogAggregatorContext):handler,listener=get_buffering_queue_logger(capacity=1000,url="https://foo.logshmog.com/v1/logs/a1b2c3",get_log_aggregator_key_func=get_aggregator_key_for_record,get_request_headers_func=get_request_headers,chunk_size=100,flush_buffer_every_x_secs=10,context=context,)listener.start()logger.add(handler,format=log_formatter)defconfigure_logger():context=get_log_aggregator_context()logger.configure(extra=context._asdict())# Config for other log handlers may go here ...configure_buffering_queue_logger(context)defget_app()->FastAPI:"""Create a FastAPI app instance."""returnFastAPI()configure_logger()app=get_app()DevelopingTo clone the repo:gitclonegit@github.com:Jaza/buffering-queue-logger.gitTo automatically fix code style issues:./scripts/format.shTo verify code style and static typing:./scripts/verify.shTo run tests:./scripts/test.shBuildingTo build the library:poetrybuildBuilt bySeertech.
Package: bufferkdtree
bufferkdtreeThe bufferkdtree package is a Python library that aims at accelerating nearest neighbor computations using both k-d trees and modern many-core devices such as graphics processing units (GPUs). The implementation is based onOpenCL.The buffer k-d tree technique can be seen as an intermediate version between a standard parallel k-d tree traversal (on multi-core systems) and a massively-parallel brute-force implementation for nearest neighbor search. In particular, it makes use of the top of a standard k-d tree (which induces a spatial subdivision of the space) and resorts to a simple yet efficient brute-force implementation for processing chunks of “big” leaves. The implementation is well-suited for data sets with a large reference set (e.g., 1,000,000 points) and a huge query set (e.g., 10,000,000 points) given a moderate dimensionality of the search space (e.g., from d=5 to d=50).DocumentationSee thedocumentationfor details and examples.DependenciesThe bufferkdtree package has been tested under Python 2.6/2.7/3.*. The required Python dependencies are:NumPy >= 1.11.0Further,Swig,OpenCL(version >= 1.2),setuptools, and a working C/C++ compiler need to be available. See thedocumentationfor more details.QuickstartThe package can easily be installed via pip via:pip install bufferkdtreeTo install the package from the sources, first get the current stable release via:git clone https://github.com/gieseke/bufferkdtree.gitAfterwards, on Linux systems, you can install the package locally for the current user via:python setup.py install --userOn Debian/Ubuntu systems, the package can be installed globally for all users via:python setup.py build
sudo python setup.py installDisclaimerThe source code is published under the GNU General Public License (GPLv2). The authors are not responsible for any implications that stem from the use of this software.
Package: buffer-python-lib
Buffer-pythonBuffer-python is an API wrapper for the API v1 of Buffer written in PythonInstallingpip install buffer-python-libUsagefrom buffer.client import Client

client = Client('CLIENT_ID', 'CLIENT_SECRET')Get authorization urlurl = client.get_authorization_url('REDIRECT_URL')Exchange the code for an access tokentoken = client.exchange_code('REDIRECT_URL', 'CODE')Set the access tokenclient.set_token('TOKEN')Get user informationaccount = client.get_user_info()Get user registered profilesprofiles = client.get_user_profiles()Get specific user profileprofile = client.get_specific_profile('PROFILE_ID')Get leads given the formposting_schedules = client.get_posting_schedules('PROFILE_ID')Get sent postssent_posts = client.get_sent_post('PROFILE_ID')Get specific postspecific_post = client.get_specific_post('POST_ID')New post or updatepost = client.new_post('PROFILE_ID', 'TEXT', True)RequirementsrequestsTODOunittestContributingWe are always grateful for any kind of contribution including but not limited to bug reports, code enhancements, bug fixes, and even functionality suggestions.You can report any bug you find or suggest new functionality with a newissue.If you want to add yourself some functionality to the wrapper:Fork it (https://github.com/GearPlug/buffer-python)Create your feature branch (git checkout -b my-new-feature)Commit your changes (git commit -am 'Adds my new feature')Push to the branch (git push origin my-new-feature)Create a new Pull Request
Package: bufflogin
Authorization to buff.163.com through SteamSteam account should be registered on the buff.163.comInstallpipinstallbuffloginUsagefrombuffloginimportBufffrompysteamauth.authimportSteamasyncdefmain():steam=Steam(login='login',password='password',)buff=Buff(steam)awaitbuff.login_to_buff()response:str=awaitbuff.request('https://buff.163.com/')LicenseMIT
Package: buffpy
buffer-app-python (buffpy)Simple to use python library for Buffer AppORM`ishBufferapp.com details some useful entities:userprofileupdatelinkinfoEvery entity can be seen as an object that has attributes and methods. Those
methods and attributes are linked to certain endpoints.All objects are special dicts. For example, you can do something like:user.id=>'12455678976asd'user=>{...}If you want to see more complete examples, clickhereAuthorizationGet access_token using bufferdocsservice=AuthService(client_id,client_secret,redirect_uri)url=service.authorize_url# Access the url and retrieve the tokenauth_code=#Paste the code from the redirected urlaccess_token=service.get_access_token(auth_code)api=service.create_session(access_token)UserA user represents a single Buffer user account.api=API(client_id='client_id',client_secret='client_secret',access_token='access_token')# instantiate an user objectuser=User(api=api)print(user)print(user.id)print(user.timezone)ProfileA Buffer profile represents a connection to a single social media account.profiles=Profiles(api=api)print(profiles.all())# get all profiles# filter profiles using some criteriaprofile=Profiles(api=api).filter(service='twitter')[0]print(profile)# my twitter profile# get schedules of my twitter profileprint(profile.schedules)# update schedules times for my twitter profileprofile.schedules={'days':['tue','thu'],'times':['13:45']}UpdateAn update represents a single post to a single social media account.# retrieve a single update based on an idupdate=Update(api=api,id='51de8d33e48c051712000019')print(update)# get update's interactionsprint(update.interactions)# editupdate=update.edit(text="Hey!")# publish nowupdate.publish()# move to topupdate.move_to_top()# deleteupdate.delete()Updates and profiles# get all pending updates of a social network profileprofile=Profiles(api=api).filter(service='twitter')[0]print(profile.updates.pending)# get all sent updates of a social network profileprint(profile.updates.sent)# retrieve all update's interactionsprint(profile.updates.sent[0].interactions)# shuffle updatesprint(profile.updates.shuffle(count=10))# reorder updatesprint(profile.updates.reorder(['51dd27629f7fdf520d00009a']))# create an updateprint(profile.updates.new("Hello there",now=True))LinksA link represents a unique URL that has been shared through Buffer# get a link's sharesprint(Link(api=api,url='http%3A%2F%2Fbufferapp.com').shares)InfoReturns an object with the current configuration that Buffer is using,
including supported services, their icons and the varying limits of character
and schedules.# instantiate the api objectapi=API(client_id='client_id',client_secret='client_secret',access_token='access_token')# get api's infoprint(api.info)